diff --git a/.ci_fedora.sh b/.ci_fedora.sh index 5f0a36efea..a29a146d58 100755 --- a/.ci_fedora.sh +++ b/.ci_fedora.sh @@ -21,11 +21,10 @@ then cmd="sudo docker" fi test . != ".$2" && mpi="$2" || mpi=openmpi - test . != ".$3" && version="$3" || version=rawhide - time $cmd pull registry.fedoraproject.org/fedora:$version + time $cmd pull ghcr.io/boutproject/bout-container-base:main time $cmd create --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \ - --shm-size 256M \ - --name mobydick registry.fedoraproject.org/fedora:$version \ + --shm-size 1G \ + --name mobydick ghcr.io/boutproject/bout-container-base:main \ /tmp/BOUT-dev/.ci_fedora.sh $mpi time $cmd cp ${TRAVIS_BUILD_DIR:-$(pwd)} mobydick:/tmp/BOUT-dev time $cmd start -a mobydick @@ -34,32 +33,19 @@ fi test . != ".$1" && mpi="$1" || mpi=openmpi -## If we are called as root, setup everything -if [ $UID -eq 0 ] -then - cat /etc/os-release - # Ignore weak depencies - echo "install_weak_deps=False" >> /etc/dnf/dnf.conf - echo "minrate=10M" >> /etc/dnf/dnf.conf - export FORCE_COLUMNS=200 - time dnf -y install dnf5 - time dnf5 -y install dnf5-plugins cmake python3-zoidberg python3-natsort python3-boututils - # Allow to override packages - see #2073 - time dnf5 copr enable -y davidsch/fixes4bout || : - time dnf5 -y upgrade - time dnf5 -y builddep bout++ - useradd test - cp -a /tmp/BOUT-dev /home/test/ - chown -R test /home/test - chmod u+rwX /home/test -R - su - test -c "${0/\/tmp/\/home\/test} $mpi" ## If we are called as normal user, run test -else + cp -a /tmp/BOUT-dev /home/test/ . /etc/profile.d/modules.sh module load mpi/${1}-x86_64 - export OMPI_MCA_rmaps_base_oversubscribe=yes + sudo dnf install -y python3-pytest python3-pytest-xdist + # OpenMPI Oversubscription Overrides + export OMPI_MCA_rmaps_base_oversubscribe=1 + export OMPI_MCA_hwloc_base_binding_policy=none + export OMPI_MCA_rmaps_base_mapping_policy=core:OVERSUBSCRIBE + export PRTE_MCA_rmaps_default_mapping_policy=core:OVERSUBSCRIBE export PRTE_MCA_rmaps_default_mapping_policy=:oversubscribe export TRAVIS=true + export CI=true # Try limiting openmp threads export FLEXIBLAS=NETLIB export MKL_NUM_THREADS=1 @@ -67,13 +53,15 @@ else export OMP_NUM_THREADS=1 cd cd BOUT-dev + python3 -m ensurepip + python3 -m pip install -r requirements.txt echo "starting configure" time cmake -S . -B build -DBOUT_USE_PETSC=ON \ -DBOUT_UPDATE_GIT_SUBMODULE=OFF \ -DBOUT_USE_SYSTEM_FMT=ON \ -DBOUT_USE_SYSTEM_MPARK_VARIANT=ON \ - -DBOUT_USE_SUNDIALS=ON + -DBOUT_USE_SUNDIALS=ON \ + -DBOUT_USE_SYSTEM_CPPTRACE=ON time make -C build build-check -j 2 - time make -C build check -fi + cd build && time cmake --build . --target check diff --git a/.ci_with_cmake.sh b/.ci_with_cmake.sh index 71ea2204e2..c664d3d66e 100755 --- a/.ci_with_cmake.sh +++ b/.ci_with_cmake.sh @@ -13,7 +13,7 @@ fi cmake --build build --target build-check -j 2 cd build -ctest --output-on-failure --timeout 300 +cmake --build . --target check export LD_LIBRARY_PATH=/home/runner/local/lib:$LD_LIBRARY_PATH diff --git a/.clang-format b/.clang-format index a80c59bddd..9f7c5d763e 100644 --- a/.clang-format +++ b/.clang-format @@ -93,6 +93,7 @@ PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left +QualifierAlignment: Left ReflowComments: false SortIncludes: true # SortUsingDeclarations: true @@ -111,6 +112,6 @@ StatementMacros: - BOUT_OMP - BOUT_OMP_PERF - BOUT_OMP_SAFE -Standard: c++14 +Standard: c++20 TabWidth: 8 UseTab: Never diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 0000000000..58566f02b1 --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1,2 @@ +# ignore matlab files +**/*.m diff --git a/.clang-tidy b/.clang-tidy index 556b8738f8..6fc7fd19d9 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-misc-non-private-member-variables-in-classes,-clang-analyzer-optin.mpi*,-bugprone-exception-escape,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-readability-function-cognitive-complexity,-misc-no-recursion,-bugprone-easily-swappable-parameters,-readability-identifier-length' +Checks: 'clang-diagnostic-*,clang-analyzer-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-misc-non-private-member-variables-in-classes,-clang-analyzer-optin.mpi*,-bugprone-exception-escape,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-readability-function-cognitive-complexity,-misc-no-recursion,-bugprone-easily-swappable-parameters,-readability-identifier-length,-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access' WarningsAsErrors: '' HeaderFilterRegex: '' FormatStyle: file @@ -9,6 +9,18 @@ CheckOptions: # otherwise this breaks `ASSERT` macros! - key: readability-simplify-boolean-expr.IgnoreMacros value: 'true' + + - key: misc-include-cleaner.IgnoreHeaders + value: 'petsc.*\.h;mpi\.h' + + - key: readability-qualified-auto.IgnoreAliasing + value: 'false' + + - key: readability-qualified-auto.AllowedTypes + value: 'MPI_Comm' + + - key: misc-include-cleaner.IgnoreHeaders + value: 'adios2/.*;bits/.*;cpptrace/.*;petsc.*\.h' --- Disabled checks and reasons: @@ -17,6 +29,7 @@ These are all basically unavoidable in HPC numeric code: -readability-magic-numbers -cppcoreguidelines-avoid-magic-numbers -cppcoreguidelines-pro-bounds-pointer-arithmetic +-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access -readability-function-cognitive-complexity -bugprone-easily-swappable-parameters -readability-identifier-length diff --git a/.clangd b/.clangd new file mode 100644 index 0000000000..421b7e10d3 --- /dev/null +++ b/.clangd @@ -0,0 +1,6 @@ +Diagnostics: + MissingIncludes: Strict + ClangTidy: + FastCheckFilter: None + Includes: + IgnoreHeader: ["adios2/.*", "bits/.*", "cpptrace/.*", "petsc.*"] diff --git a/.docker/fedora/Dockerfile b/.docker/fedora/Dockerfile index 56445f8cea..e0351bb605 100644 --- a/.docker/fedora/Dockerfile +++ b/.docker/fedora/Dockerfile @@ -1,5 +1,5 @@ -ARG BASE -FROM ghcr.io/dschwoerer/bout-container-base:$BASE +ARG BASE=mpich-full-main +FROM ghcr.io/boutproject/bout-container-base:$BASE # ---------------------------------------------------------------- # Build and install BOUT++ @@ -22,18 +22,26 @@ RUN git clone $URL \ && git checkout $COMMIT \ && git submodule update --init --recursive - +ENV HOME=/home/boutuser WORKDIR /home/boutuser/BOUT-dev -RUN cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/opt/bout++/ \ +RUN cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr/local/ \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DBOUT_GENERATE_FIELDOPS=OFF \ - -DBOUT_USE_PETSC=ON -DPETSc_ROOT=/opt/petsc \ + -DBOUT_USE_PETSC=ON -DPETSc_ROOT=/usr/local \ -DBOUT_ENABLE_PYTHON=ON \ -DBOUT_USE_SUNDIALS=ON -DSUNDIALS_ROOT=/usr/lib64/$MPI/ -DSUNDIALS_INCLUDE_DIR=/usr/include/$MPI-x86_64/sundials/ \ - $CMAKE_OPTIONS || (cat /home/boutuser/BOUT-dev/build/CMakeFiles/CMake{Output,Error}.log ; exit 1) + $CMAKE_OPTIONS || (cat /home/boutuser/BOUT-dev/build/CMakeFiles/CMake{Output,Error}.log ; exit 1); \ + make -C build -j 2 VERBOSE=1; \ + sudo make -C build install; \ + rm -rf build +# Add unversioned path for python +RUN sudo ln -s /usr/local/lib/python3.* /usr/local/lib/python3.x -RUN make -C build -j 2 -RUN sudo make -C build install +ENV PATH=/usr/local/bin:$PATH \ + LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH \ + PYTHONPATH=/usr/local/lib/python3.x/site-packages/:$PYTHONPATH -RUN find /opt/bout++ +# smoke test +RUN python3 -c 'import boutpp' diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 4990f2586e..945f769e70 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,22 @@ # Clang-format whole repo d8f14fdddb5ca0fbb32d8e2bf5ac2960d6ac5ce6 ed2117e6d6826a98b6988e2f18c0c34e408563b6 +# CMake formatting +17ac13c28aa3b34a0e46dbe87bb3874f6b25e706 +# Added by the bot +4b010b7634aee1045743be80c268d4644522cd29 +52301380586fdbf890f620c04f689b08d89a6c34 +a71cad2dd6ace5741a754e2ca7daacd4bb094e0e +83cf77923a4c72e44303354923021acf932b4fd2 +2c2402ed59c91164eaff46dee0f79386b7347e9e +05b7c571544c3bcb153fce67d12b9ac48947fc2d +c8f38049359170a34c915e209276238ea66b9a1e +65880e4af16cb95438437bf057c4b9fdb427b142 +d1cfb8abd6aa5c76e6c1a4d7ab20929c65f8afc2 +8d5cb39e03c2644715a50684f8cd0318b4e82676 +ec69e8838be2dde140a915e50506f8e1ce3cb534 +f2bc0488a298f136294c523bc5ab4086d090059b +c59626a0498b0cfd1be46f84f0fa38b4855a43cc +1b4707187a3a85126338303dc766280b8fb2dc56 +b2e2f3575e68f771be2a4341af5fd14e2870469e +64e4285ec38569f66d31e589a4610cefd16d8076 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c6b0738bd2..e121ea49e4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,11 +6,6 @@ updates: interval: "weekly" directory: "/" - - package-ecosystem: "pip" - schedule: - interval: "daily" - directory: "/" - - package-ecosystem: "github-actions" schedule: interval: "weekly" diff --git a/.github/workflows/auto-formatting.yml b/.github/workflows/auto-formatting.yml new file mode 100644 index 0000000000..7274f34038 --- /dev/null +++ b/.github/workflows/auto-formatting.yml @@ -0,0 +1,33 @@ +name: format-command + +on: + pull_request: + +jobs: + clang-format: + # Release candidate branches tend to have big PRs which causes all sorts of problems + if: ${{ !endsWith(github.head_ref, '-rc') }} + runs-on: ubuntu-latest + steps: + # Checkout the pull request branch, also include all history + - uses: actions/checkout@v7 + with: + ref: ${{ github.head_ref }} + fetch-depth: 0 + + - name: "Set up Python" + uses: actions/setup-python@v7 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + enable-cache: true + + - name: Install dev tools + run: uv sync --only-dev + + - name: Check prek versions are up-to-date + run: uv tool run sync-with-uv --check --diff + + - name: Run everything + run: uv tool run prek run --show-diff-on-failure --from-ref origin/${{ github.base_ref }} diff --git a/.github/workflows/black-fix.yml b/.github/workflows/black-fix.yml deleted file mode 100644 index 92866dfcc2..0000000000 --- a/.github/workflows/black-fix.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: black - -on: - push: - paths: - - '**.py' - - 'bin/**' - - '**/runtest' - - '**/run' - - 'tests/integrated/test_suite' - - 'tests/requirements/*' - - 'tools/tokamak_grids/**' - -defaults: - run: - shell: bash - -jobs: - black: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - - - name: Install black - run: | - sudo apt update -y - sudo apt -y install python3-pip python3-setuptools python3-wheel - pip3 install black - - - name: Version - run: | - python3 --version - $HOME/.local/bin/black --version - - - name: Run black - run: | - pwd - ls - $HOME/.local/bin/black tests/ tools/ $(grep -EIlr '^#!.*python.*$' bin/ tests/ tools/ src/ | grep -v _boutpp_build) - - - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: "Apply black changes" diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml deleted file mode 100644 index 49dfb31e25..0000000000 --- a/.github/workflows/clang-format.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: clang-format-command - -on: - pull_request: - paths: - - '**.cxx' - - '**.hxx' - -jobs: - clang-format: - runs-on: ubuntu-latest - steps: - # Checkout the pull request branch, also include all history - - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - fetch-depth: 0 - - # This also installs git-clang-format - - name: Install clang-format - run: sudo apt install clang-format - - - name: Run clang-format - id: format - run: - while ! git clang-format origin/${{ github.base_ref }} ; do git add . ; done - - - name: Commit to the PR branch - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: "Apply clang-format changes" diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 1a9a0ea079..0573addd9c 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -5,9 +5,6 @@ on: paths: - '**.cxx' - '**.hxx' - branches-ignore: - # Release candidate branches tend to have big PRs which causes all sorts of problems - - 'v*rc' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -15,14 +12,16 @@ concurrency: jobs: review: + # Release candidate branches tend to have big PRs which causes all sorts of problems + if: ${{ !endsWith(github.head_ref, '-rc') }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: true - name: Run clang-tidy - uses: ZedThree/clang-tidy-review@v0.21.0 + uses: ZedThree/clang-tidy-review@v0.23.1 id: review with: build_dir: build @@ -47,4 +46,4 @@ jobs: -DBOUT_UPDATE_GIT_SUBMODULE=OFF - name: Upload clang-tidy fixes - uses: ZedThree/clang-tidy-review/upload@v0.21.0 + uses: ZedThree/clang-tidy-review/upload@v0.23.1 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a1dac41a6b..b8d5fc8a70 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -6,7 +6,7 @@ on: - master - next # Add your branch here if you want containers for it - - db-WIP + - fix3121 - docker-ci env: @@ -26,18 +26,18 @@ jobs: matrix: mpi: [mpich] metric3d: - - name: "With OpenMP" + - name: "With 3D Metrics" cmake: ON - base_prefix: "openmp-" + base_prefix: "" tag_prefix: "3d-" - - name: "Without OpenMP" + - name: "With 2D Metrics" cmake: OFF base_prefix: "" tag_prefix: "" config: - name: "Debug" tag_postfix: "debug" - options: "-DCHECK=3" + options: "-DCHECK=4" base_postfix: "mini" - name: "Optimised" @@ -47,12 +47,12 @@ jobs: - name: "Full" tag_postfix: "full" - options: "-DCHECK=3" + options: "-DCHECK=4" base_postfix: "full" steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Log in to the Container registry uses: docker/login-action@master @@ -75,7 +75,7 @@ jobs: build-args: | BASE=${{ matrix.mpi }}-${{ matrix.metric3d.base_prefix }}${{ matrix.config.base_postfix }}-main MPI=${{ matrix.mpi }} - CMAKE_OPTIONS=${{ matrix.config.options }} -DBOUT_ENABLE_METRIC_3D=${{ matrix.metric3d.cmake }} -DBOUT_ENABLE_OPENMP=${{ matrix.metric3d.cmake }} + CMAKE_OPTIONS=${{ matrix.config.options }} -DBOUT_ENABLE_METRIC_3D=${{ matrix.metric3d.cmake }} COMMIT=${{ github.sha }} URL=${{ github.server_url }}/${{ github.repository }} context: .docker/fedora/ diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index ea68e58c12..53561934e2 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -17,12 +17,12 @@ jobs: if: always() steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: fetch-depth: 0 submodules: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 - name: Install dependencies run: python -m pip install --upgrade pip && pip install --upgrade build && @@ -57,12 +57,12 @@ jobs: if: always() steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: fetch-depth: 0 submodules: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 - name: Install dependencies run: python -m pip install --upgrade pip && pip install --upgrade build && @@ -106,12 +106,12 @@ jobs: if: always() steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: fetch-depth: 0 submodules: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 - name: Install dependencies run: python -m pip install --upgrade pip && pip install --upgrade build && diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4153ebaefc..16218f39be 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,6 +30,7 @@ jobs: OMPI_MCA_rmaps_base_oversubscribe: yes PRTE_MCA_rmaps_default_mapping_policy: ":oversubscribe" MPIRUN: mpiexec -np + BOUT_TEST_DOWNLOAD_FLAGS: --retry-on-http-error=502,503,504 --tries 3 strategy: fail-fast: true matrix: @@ -39,9 +40,11 @@ jobs: is_cron: - ${{ github.event_name == 'cron' }} config: - - name: "CMake, PETSc unreleased, ADIOS2" + - name: "PETSc unreleased, ADIOS2, 3D metrics" os: ubuntu-24.04 - cmake_options: "-DBUILD_SHARED_LIBS=ON + cmake_options: "-DCHECK=2 + -DCMAKE_BUILD_TYPE=Debug + -DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_METRIC_3D=ON -DBOUT_ENABLE_OPENMP=ON -DBOUT_USE_PETSC=ON @@ -108,7 +111,9 @@ jobs: - name: "Shared, OpenMP, 3D metrics" os: ubuntu-latest - cmake_options: "-DBUILD_SHARED_LIBS=ON + cmake_options: "-DCHECK=2 + -DCMAKE_BUILD_TYPE=Debug + -DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_METRIC_3D=ON -DBOUT_ENABLE_OPENMP=ON -DBOUT_USE_PETSC=ON @@ -120,22 +125,6 @@ jobs: omp_num_threads: 2 on_cron: false - - name: "CMake, new PETSc" - os: ubuntu-latest - cmake_options: "-DBUILD_SHARED_LIBS=ON - -DBOUT_ENABLE_METRIC_3D=ON - -DBOUT_ENABLE_OPENMP=ON - -DBOUT_USE_PETSC=ON - -DBOUT_USE_SLEPC=ON - -DBOUT_USE_SUNDIALS=ON - -DBOUT_USE_HYPRE=OFF - -DBOUT_ENABLE_PYTHON=ON - -DSUNDIALS_ROOT=/home/runner/local - -DPETSC_DIR=/home/runner/local/petsc - -DSLEPC_DIR=/home/runner/local/slepc" - build_petsc: -petsc - on_cron: false - exclude: - is_cron: true config: @@ -148,41 +137,58 @@ jobs: echo CMake options: ${{ matrix.config.cmake_options }} - name: Install dependencies - run: sudo apt update && - sudo apt install -y - libfftw3-dev - libnetcdf-dev - libnetcdf-c++4-dev - netcdf-bin - python3 - python3-pip - python3-pytest - python3-numpy - python3-scipy - lcov - openmpi-bin - libopenmpi-dev - petsc-dev - slepc-dev - liblapack-dev - libparpack2-dev - libhypre-dev - - - uses: actions/checkout@v4 + run: | + sudo apt update + sudo apt install -y \ + libfftw3-dev \ + libnetcdf-dev \ + libnetcdf-c++4-dev \ + netcdf-bin \ + lcov \ + openmpi-bin \ + libopenmpi-dev \ + petsc-dev \ + slepc-dev \ + liblapack-dev \ + libparpack2-dev \ + libhypre-dev + + - uses: actions/checkout@v7 with: submodules: true - - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + enable-cache: true + + - uses: actions/setup-python@v7 with: python-version: '3.x' - - name: Install pip packages + - name: Setup virtual environment with uv run: | - python -m pip install --upgrade pip setuptools - python -m pip install -r requirements.txt + # uv sync automatically creates a .venv and installs the groups + uv sync --no-dev --group pytest --inexact + + # Install the core requirements into the same venv + uv pip install -r requirements.txt + + # Put the venv in the PATH + echo "$GITHUB_WORKSPACE/.venv/bin" >> $GITHUB_PATH + + # Force CMake to recognize the virtual environment + echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV + + - name: Cache Zenodo test data + uses: actions/cache@v6 + with: + path: build/tests/integrated/test-fci-mpi/grid.fci.nc + # If we update the test, invalidate the cache + key: zenodo-data-${{ hashFiles('tests/integrated/test-fci-mpi/CMakeLists.txt') }} - name: Cache SUNDIALS build - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: /home/runner/local key: bout-sundials-${{ matrix.config.os }}${{ matrix.config.build_petsc }} @@ -194,49 +200,34 @@ jobs: run: BUILD_PETSC=${{ matrix.config.build_petsc }} ./.build_petsc_for_ci.sh ${{ matrix.config.build_petsc_branch }} - name: Build ADIOS2 - run: BUILD_ADIOS2=${{ matrix.config.build_adios2 }} ./.build_adios2_for_ci.sh + run: BUILD_ADIOS2=${{ matrix.config.build_adios2 }} ./.build_adios2_for_ci.sh - name: Build BOUT++ - run: UNIT_ONLY=${{ matrix.config.unit_only }} ./.ci_with_cmake.sh ${{ matrix.config.cmake_options }} + run: | + UNIT_ONLY=${{ matrix.config.unit_only }} ./.ci_with_cmake.sh ${{ matrix.config.cmake_options }} \ + -DPython3_EXECUTABLE=$GITHUB_WORKSPACE/.venv/bin/python Fedora: # This is its own job as it doesn't use most of the steps of the # standard_tests timeout-minutes: 120 runs-on: ubuntu-latest + env: + BOUT_TEST_DOWNLOAD_FLAGS: --retry-on-http-error=502,503,504 --tries 3 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: true + + - name: Cache Zenodo test data + uses: actions/cache@v6 + with: + path: build/tests/integrated/test-fci-mpi/grid.fci.nc + # If we update the test, invalidate the cache + key: zenodo-data-${{ hashFiles('tests/integrated/test-fci-mpi/CMakeLists.txt') }} + - name: Build Fedora - run: ./.ci_fedora.sh setup openmpi latest + run: ./.ci_fedora.sh setup openmpi shell: bash env: TRAVIS_BUILD_DIR: ${{ github.workspace }} - CUDA: - timeout-minutes: 60 - runs-on: ubuntu-latest - container: ghcr.io/ggeorgakoudis/boutdev-cuda:latest - - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Build minimal CUDA 12.2 @ GCC9.4.0 @ Ubuntu 20.04 - run: | - . /spack/share/spack/setup-env.sh - spack env activate -p /spack-env - git config --global --add safe.directory $GITHUB_WORKSPACE - rm -rf build - cmake -S $GITHUB_WORKSPACE -B build \ - -DCMAKE_C_COMPILER=gcc \ - -DCMAKE_CXX_COMPILER=g++ \ - -DBOUT_ENABLE_RAJA=on \ - -DBOUT_ENABLE_UMPIRE=on \ - -DBOUT_ENABLE_CUDA=on \ - -DCMAKE_CUDA_ARCHITECTURES=80 \ - -DCUDA_ARCH=compute_80,code=sm_80 \ - -DBOUT_ENABLE_WARNINGS=off \ - -DBOUT_USE_SYSTEM_FMT=on - cd build - make -j 4 diff --git a/.gitignore b/.gitignore index 934da1c0de..164a88925c 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,4 @@ coverage/ /BOUT++-v*.tar.xz /CMakeCache.txt /CMakeFiles/cmake.check_cache +.vscode/ diff --git a/.gitmodules b/.gitmodules index 4b33b3b615..59fb05ab50 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "externalpackages/boutdata"] path = externalpackages/boutdata url = https://github.com/boutproject/boutdata.git +[submodule "externalpackages/cpptrace"] + path = externalpackages/cpptrace + url = https://github.com/jeremy-rifkin/cpptrace.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..31369b738b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,62 @@ +# This file requires prek rather than pre-commit +exclude: + glob: + - "tools/**/*.pro" + - "tools/**/*.m" + - "tools/**/*.[ch]" + +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: builtin + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + +# This would be nice to use, but it is a significant slowdown: + +# # Sync versions of hook tools with `uv.lock` +# - repo: https://github.com/tsvikas/sync-with-uv +# rev: v0.5.0 +# hooks: +# - id: sync-with-uv + +# C++ formatting +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v22.1.8 + hooks: + - id: clang-format + types_or: [c++, c, cuda] + +# Python linting and formatting +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.16.2 + hooks: + # Run the linter. + - id: ruff-check + # Run the formatter. + - id: ruff-format + +# CMake formatting +- repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.13 + hooks: + - id: cmake-format + additional_dependencies: [pyyaml>=5.1] + +# Various config files +- repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.37.0 + hooks: + - id: check-github-workflows + - id: check-readthedocs + - id: check-citation-file-format + - id: check-dependabot + +# Docs linting +- repo: https://github.com/sphinx-contrib/sphinx-lint + rev: v1.0.2 + hooks: + - id: sphinx-lint + files: 'manual/sphinx/.*' diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d346d47e8..a0cbfd5915 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,24 @@ # Changelog -## [v6.0.0](https://github.com/boutproject/BOUT-dev/tree/next) -[Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.1.0...next) +## [v6.0.0](https://github.com/boutproject/BOUT-dev/tree/v6.0.0 + +[Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.2.0...) + +### Breaking changes + +- `Coordinates` has been refactored to with a more encapsulated interface. This + allows us to ensure that derived quantities are correctly updated when the + metric components are changed, as well as defer creation of the Christoffel + symbols, and other derivatives of the metric components. This change will + require most physics models to be updated. You can do this with the + `bout-upgrader` from `boutdata`: + ```console + $ bout-upgrader v6 v6_upgrader file/to/update.cxx + ```` + +## [v5.2.0](https://github.com/boutproject/BOUT-dev/tree/v5.2.0 + +[Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.1.1...v5.2.0) ### Breaking changes @@ -16,6 +33,67 @@ confusing. Now, monitors are called with the current number of completed monitor-steps. +## Changes + +- Fixes for FreeBSD [\#3172][https://github.com/boutproject/BOUT-dev/pull/3172] ([tomc271][https://github.com/tomc271]) +- snes: Print a warning if the coloring is non-symmetric. [\#3159][https://github.com/boutproject/BOUT-dev/pull/3159] ([bendudson][https://github.com/bendudson]) +- Cmake fix from master [\#3152][https://github.com/boutproject/BOUT-dev/pull/3152] ([oparry-ukaea][https://github.com/oparry-ukaea]) +- Bump ZedThree/clang-tidy-review from 0.20.1 to 0.21.0 [\#3150][https://github.com/boutproject/BOUT-dev/pull/3150] ([ZedThree][https://github.com/ZedThree]) +- SNES solver: Added a PID controller to update the timestep [\#3146][https://github.com/boutproject/BOUT-dev/pull/3146] ([malamast][https://github.com/malamast]) +- Fix name clash in some examples and MMS tests [\#3145][https://github.com/boutproject/BOUT-dev/pull/3145] ([ZedThree][https://github.com/ZedThree]) +- Handle absolute paths to options file [\#3142][https://github.com/boutproject/BOUT-dev/pull/3142] ([bendudson][https://github.com/bendudson]) +- Revert eliminate hypre boundary equations [\#3136][https://github.com/boutproject/BOUT-dev/pull/3136] ([ZedThree][https://github.com/ZedThree]) +- CI: Switch to released fedora [\#3134][https://github.com/boutproject/BOUT-dev/pull/3134] ([dschwoerer][https://github.com/dschwoerer]) +- Generalise FakeMeshFixture to allow configurable grid spacing via templating [\#3132][https://github.com/boutproject/BOUT-dev/pull/3132] ([tomc271][https://github.com/tomc271]) +- Fixes for ELM-PB preconditioner [\#3128][https://github.com/boutproject/BOUT-dev/pull/3128] ([Steven-Roberts][https://github.com/Steven-Roberts]) +- Fix cast for new petsc [\#3117][https://github.com/boutproject/BOUT-dev/pull/3117] ([dschwoerer][https://github.com/dschwoerer]) +- Fix bug where ARKODE considered all problems linear [\#3114][https://github.com/boutproject/BOUT-dev/pull/3114] ([Steven-Roberts][https://github.com/Steven-Roberts]) +- cvode: Add linear_solver option [\#3112][https://github.com/boutproject/BOUT-dev/pull/3112] ([bendudson][https://github.com/bendudson]) +- periodicX communication fixes [\#3109][https://github.com/boutproject/BOUT-dev/pull/3109] ([bendudson][https://github.com/bendudson]) +- beuler solver timestep and Jacobian calculation [\#3107][https://github.com/boutproject/BOUT-dev/pull/3107] ([bendudson][https://github.com/bendudson]) +- Feature/snes stencil [\#3104][https://github.com/boutproject/BOUT-dev/pull/3104] ([seimtpow][https://github.com/seimtpow]) +- Add attributes to ADIOS2 output to "define" dimensions as names. We n… [\#3098][https://github.com/boutproject/BOUT-dev/pull/3098] ([pnorbert][https://github.com/pnorbert]) +- CI: Avoid issues with special characters [\#3090][https://github.com/boutproject/BOUT-dev/pull/3090] ([dschwoerer][https://github.com/dschwoerer]) +- CI: Fix clang format [\#3086][https://github.com/boutproject/BOUT-dev/pull/3086] ([dschwoerer][https://github.com/dschwoerer]) +- Small updates for FCI output [\#3085][https://github.com/boutproject/BOUT-dev/pull/3085] ([bendudson][https://github.com/bendudson]) +- Eliminate boundary equations to improve HYPRE solves [\#3082][https://github.com/boutproject/BOUT-dev/pull/3082] ([rfalgout][https://github.com/rfalgout]) +- Elm-pb example with relaxing phi [\#3081][https://github.com/boutproject/BOUT-dev/pull/3081] ([bendudson][https://github.com/bendudson]) +- CI: Show more output of dnf5 to help debugging [\#3071][https://github.com/boutproject/BOUT-dev/pull/3071] ([dschwoerer][https://github.com/dschwoerer]) +- Fix clang tidy review [\#3070][https://github.com/boutproject/BOUT-dev/pull/3070] ([ZedThree][https://github.com/ZedThree]) +- CMake: Bump downloaded SUNDIALS version [\#3067][https://github.com/boutproject/BOUT-dev/pull/3067] ([ZedThree][https://github.com/ZedThree]) +- Use isfinite, fix pvode linking [\#3063][https://github.com/boutproject/BOUT-dev/pull/3063] ([bendudson][https://github.com/bendudson]) +- Make iteration more robust and give more options in LaplaceNaulin [\#3061][https://github.com/boutproject/BOUT-dev/pull/3061] ([johnomotani][https://github.com/johnomotani]) +- Fixes zoidberg [\#3054][https://github.com/boutproject/BOUT-dev/pull/3054] ([dschwoerer][https://github.com/dschwoerer]) +- Fix finalise in boutpp [\#3053][https://github.com/boutproject/BOUT-dev/pull/3053] ([dschwoerer][https://github.com/dschwoerer]) +- Avoid some warnings for 3D Metrics [\#3052][https://github.com/boutproject/BOUT-dev/pull/3052] ([dschwoerer][https://github.com/dschwoerer]) +- Minor fixes for the python backend [\#3051][https://github.com/boutproject/BOUT-dev/pull/3051] ([dschwoerer][https://github.com/dschwoerer]) +- Cleanup BOUT_HOST_DEVICE qualifiers [\#3040][https://github.com/boutproject/BOUT-dev/pull/3040] ([ggeorgakoudis][https://github.com/ggeorgakoudis]) +- Deprecate options that are only used as default for other options [\#3038][https://github.com/boutproject/BOUT-dev/pull/3038] ([dschwoerer][https://github.com/dschwoerer]) +- Avoid using the wrong grid by accident [\#3036][https://github.com/boutproject/BOUT-dev/pull/3036] ([dschwoerer][https://github.com/dschwoerer]) +- Use PEP 625 compatible archive name (next) [\#3035][https://github.com/boutproject/BOUT-dev/pull/3035] ([dschwoerer][https://github.com/dschwoerer]) +- CI: Increase check level for debug run + unit test fixes [\#3033][https://github.com/boutproject/BOUT-dev/pull/3033] ([dschwoerer][https://github.com/dschwoerer]) +- Avoid `#define` conflict with sundials [\#3031][https://github.com/boutproject/BOUT-dev/pull/3031] ([dschwoerer][https://github.com/dschwoerer]) +- Ensure PETSc headers are included after `bout/petsclib.hxx` [\#3024][https://github.com/boutproject/BOUT-dev/pull/3024] ([ZedThree][https://github.com/ZedThree]) +- Fix minor HYPRE and ADIOS2 compilation issues [\#3022][https://github.com/boutproject/BOUT-dev/pull/3022] ([ZedThree][https://github.com/ZedThree]) +- Fix recompilation cascade [\#3021][https://github.com/boutproject/BOUT-dev/pull/3021] ([ZedThree][https://github.com/ZedThree]) +- Move `invert3x3` out of general purpose `utils.hxx` header [\#3018][https://github.com/boutproject/BOUT-dev/pull/3018] ([ZedThree][https://github.com/ZedThree]) +- Replace deprecated `boututils.file_import` [\#3017][https://github.com/boutproject/BOUT-dev/pull/3017] ([ZedThree][https://github.com/ZedThree]) +- CI: clang-tidy-review tweaks [\#3016][https://github.com/boutproject/BOUT-dev/pull/3016] ([ZedThree][https://github.com/ZedThree]) +- Backward Euler solver improvements [\#3009][https://github.com/boutproject/BOUT-dev/pull/3009] ([bendudson][https://github.com/bendudson]) +- Fix circular header dependency: mesh.hxx <-> griddata.hxx [\#3008][https://github.com/boutproject/BOUT-dev/pull/3008] ([ZedThree][https://github.com/ZedThree]) +- Fix exception message [\#3003][https://github.com/boutproject/BOUT-dev/pull/3003] ([dschwoerer][https://github.com/dschwoerer]) +- Ensure pointer is checked before dereferencing [\#3002][https://github.com/boutproject/BOUT-dev/pull/3002] ([dschwoerer][https://github.com/dschwoerer]) +- Fix: preserve regionID [\#3000][https://github.com/boutproject/BOUT-dev/pull/3000] ([dschwoerer][https://github.com/dschwoerer]) +- Lazy grid loading [\#2991][https://github.com/boutproject/BOUT-dev/pull/2991] ([dschwoerer][https://github.com/dschwoerer]) +- Fix compilation warnings with SUNDIALS 7.1.0 [\#2990][https://github.com/boutproject/BOUT-dev/pull/2990] ([Steven-Roberts][https://github.com/Steven-Roberts]) +- Add LC gitlab CI for GPU build/run tests [\#2989][https://github.com/boutproject/BOUT-dev/pull/2989] ([ggeorgakoudis][https://github.com/ggeorgakoudis]) +- BoutMask non-const operator[](Ind3D) [\#2988][https://github.com/boutproject/BOUT-dev/pull/2988] ([bendudson][https://github.com/bendudson]) +- Use consistently signed char [\#2987][https://github.com/boutproject/BOUT-dev/pull/2987] ([dschwoerer][https://github.com/dschwoerer]) +- naulin laplace: Acceptance tolerances after maxits [\#2983][https://github.com/boutproject/BOUT-dev/pull/2983] ([bendudson][https://github.com/bendudson]) +- Merge v5.1.1 into `next` [\#2978][https://github.com/boutproject/BOUT-dev/pull/2978] ([ZedThree][https://github.com/ZedThree]) +- CI: Bump all ubuntu images [\#2977][https://github.com/boutproject/BOUT-dev/pull/2977] ([ZedThree][https://github.com/ZedThree]) +- Read 2D variables into Field3D [\#2975][https://github.com/boutproject/BOUT-dev/pull/2975] ([bendudson][https://github.com/bendudson]) + ## [v5.1.1](https://github.com/boutproject/BOUT-dev/tree/v5.1.1) [Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.1.0...v5.1.1) diff --git a/CITATION.cff b/CITATION.cff index 81f5c35e82..318fcd1406 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -197,11 +197,27 @@ authors: - family-names: Kryjak given-names: Mike -version: 5.1.1 -date-released: 2023-04-10 + - family-names: Powell + given-names: Seimon + - family-names: Ağgül + given-names: Mustafa + - family-names: Parry + given-names: Owen + - family-names: Podhorszki + given-names: Norbert + - family-names: Falgout + given-names: Rob + - family-names: Li + given-names: Nami + - family-names: Body + given-names: Tom + - family-names: Tsagkaridis + given-names: Malamas +version: 5.2.0 +date-released: 2025-10-10 repository-code: https://github.com/boutproject/BOUT-dev url: http://boutproject.github.io/ -doi: 10.5281/zenodo.13753882 +doi: 10.5281/zenodo.17313945 license: 'LGPL-3.0-or-later' references: - type: article diff --git a/CMakeLists.txt b/CMakeLists.txt index 995cd976a5..0d74e9bf90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,55 +15,72 @@ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.22) cmake_policy(SET CMP0127 NEW) endif() -if ("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - option(BOUT_ALLOW_INSOURCE_BUILD "Whether BOUT++ should really allow to build in source." OFF) - if (NOT ${BOUT_ALLOW_INSOURCE_BUILD}) - message(FATAL_ERROR "BOUT++ does not recommend in source builds. Try building out of source, e.g. with `cmake -S . -B build` or set -DBOUT_ALLOW_INSOURCE_BUILD=ON - but things may break!") +if("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") + option(BOUT_ALLOW_INSOURCE_BUILD + "Whether BOUT++ should really allow to build in source." OFF + ) + if(NOT ${BOUT_ALLOW_INSOURCE_BUILD}) + message( + FATAL_ERROR + "BOUT++ does not recommend in source builds. Try building out of source, e.g. with `cmake -S . -B build` or set -DBOUT_ALLOW_INSOURCE_BUILD=ON - but things may break!" + ) endif() endif() # CMake currently doesn't support proper semver # Set the version here, strip any extra tags to use in `project` # We try to use git to get a full description, inspired by setuptools_scm -set(_bout_previous_version "5.1.1") -set(_bout_next_version "5.2.0") +set(_bout_previous_version "5.2.0") +set(_bout_next_version "6.0.0") execute_process( COMMAND "git" describe --tags --match=v${_bout_previous_version} - COMMAND sed -e s/${_bout_previous_version}-/${_bout_next_version}.dev/ -e s/-/+/ - RESULTS_VARIABLE error_codes + COMMAND sed -e s/${_bout_previous_version}-/${_bout_next_version}.dev/ -e + s/-/+/ RESULTS_VARIABLE error_codes OUTPUT_VARIABLE BOUT_FULL_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE - ) +) foreach(error_code ${error_codes}) - if (NOT ${error_code} STREQUAL 0) + if(NOT ${error_code} STREQUAL 0) set(BOUT_FULL_VERSION ${_bout_next_version}) endif() endforeach() # Remove leading "v" string(REGEX REPLACE "^v(.*)" "\\1" BOUT_FULL_VERSION ${BOUT_FULL_VERSION}) # Remove trailing tag -string(REGEX REPLACE "^([0-9]+\.[0-9]+\.[0-9]+)\..*" "\\1" BOUT_CMAKE_ACCEPTABLE_VERSION ${BOUT_FULL_VERSION}) +string(REGEX REPLACE "^([0-9]+\.[0-9]+\.[0-9]+)\..*" "\\1" + BOUT_CMAKE_ACCEPTABLE_VERSION ${BOUT_FULL_VERSION} +) # Get the trailing tag -string(REGEX REPLACE "^[0-9]+\.[0-9]+\.[0-9]+\.(.*)" "\\1" BOUT_VERSION_TAG ${BOUT_FULL_VERSION}) +string(REGEX REPLACE "^[0-9]+\.[0-9]+\.[0-9]+\.(.*)" "\\1" BOUT_VERSION_TAG + ${BOUT_FULL_VERSION} +) message(STATUS "Configuring BOUT++ version ${BOUT_FULL_VERSION}") -project(BOUT++ +project( + BOUT++ DESCRIPTION "Fluid PDE solver framework" VERSION ${BOUT_CMAKE_ACCEPTABLE_VERSION} - LANGUAGES CXX) + LANGUAGES CXX +) include(CMakeDependentOption) option(BUILD_SHARED_LIBS "Build shared libs" ON) # Override default -option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" OFF) +option( + INSTALL_GTEST + "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" + OFF +) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) include(BOUT++functions) -option(BOUT_UPDATE_GIT_SUBMODULE "Check submodules are up-to-date during build" ON) +option(BOUT_UPDATE_GIT_SUBMODULE "Check submodules are up-to-date during build" + ON +) # Adapted from https://cliutils.gitlab.io/modern-cmake/chapters/projects/submodule.html # Update submodules as needed function(bout_update_submodules) @@ -73,339 +90,393 @@ function(bout_update_submodules) find_package(Git QUIET) if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") message(STATUS "Submodule update") - execute_process(COMMAND ${GIT_EXECUTABLE} -c submodule.recurse=false submodule update --init --recursive + execute_process( + COMMAND ${GIT_EXECUTABLE} -c submodule.recurse=false submodule update + --init --recursive WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - RESULT_VARIABLE GIT_SUBMOD_RESULT) - if(NOT GIT_SUBMOD_RESULT EQUAL "0") - message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") + RESULT_VARIABLE GIT_SUBMOD_RESULT + ) + if(NOT GIT_SUBMOD_RESULT EQUAL "0") + message( + FATAL_ERROR + "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules" + ) endif() endif() endfunction() set(BOUT_SOURCES - ./include/bout/adios_object.hxx - ./include/bout/array.hxx - ./include/bout/assert.hxx - ./include/bout/boundary_factory.hxx - ./include/bout/boundary_op.hxx - ./include/bout/boundary_region.hxx - ./include/bout/boundary_standard.hxx - ./include/bout/bout.hxx - ./include/bout/bout_enum_class.hxx - ./include/bout/bout_types.hxx - ./include/bout/build_config.hxx - ./include/bout/boutcomm.hxx - ./include/bout/boutexception.hxx - ./include/bout/caliper_wrapper.hxx - ./include/bout/constants.hxx - ./include/bout/coordinates.hxx - ./include/bout/coordinates_accessor.hxx - ./include/bout/cyclic_reduction.hxx - ./include/bout/dcomplex.hxx - ./include/bout/deriv_store.hxx - ./include/bout/derivs.hxx - ./include/bout/difops.hxx - ./include/bout/expr.hxx - ./include/bout/fft.hxx - ./include/bout/field.hxx - ./include/bout/field2d.hxx - ./include/bout/field3d.hxx - ./include/bout/field_accessor.hxx - ./include/bout/field_data.hxx - ./include/bout/field_factory.hxx - ./include/bout/fieldgroup.hxx - ./include/bout/fieldperp.hxx - ./include/bout/fv_ops.hxx - ./include/bout/generic_factory.hxx - ./include/bout/globalfield.hxx - ./include/bout/globalindexer.hxx - ./include/bout/globals.hxx - ./include/bout/griddata.hxx - ./include/bout/gyro_average.hxx - ./include/bout/hypre_interface.hxx - ./include/bout/index_derivs.hxx - ./include/bout/index_derivs_interface.hxx - ./include/bout/initialprofiles.hxx - ./include/bout/interpolation.hxx - ./include/bout/interpolation_xz.hxx - ./include/bout/interpolation_z.hxx - ./include/bout/invert/laplacexy.hxx - ./include/bout/invert/laplacexz.hxx - ./include/bout/invert_laplace.hxx - ./include/bout/invert_parderiv.hxx - ./include/bout/invert_pardiv.hxx - ./include/bout/invertable_operator.hxx - ./include/bout/lapack_routines.hxx - ./include/bout/macro_for_each.hxx - ./include/bout/mask.hxx - ./include/bout/mesh.hxx - ./include/bout/monitor.hxx - ./include/bout/mpi_wrapper.hxx - ./include/bout/msg_stack.hxx - ./include/bout/multiostream.hxx - ./include/bout/openmpwrap.hxx - ./include/bout/operatorstencil.hxx - ./include/bout/options.hxx - ./include/bout/options_io.hxx - ./include/bout/optionsreader.hxx - ./include/bout/output.hxx - ./include/bout/output_bout_types.hxx - ./include/bout/parallel_boundary_op.hxx - ./include/bout/parallel_boundary_region.hxx - ./include/bout/paralleltransform.hxx - ./include/bout/petsc_interface.hxx - ./include/bout/petsclib.hxx - ./include/bout/physicsmodel.hxx - ./include/bout/rajalib.hxx - ./include/bout/region.hxx - ./include/bout/rkscheme.hxx - ./include/bout/rvec.hxx - ./include/bout/scorepwrapper.hxx - ./include/bout/single_index_ops.hxx - ./include/bout/slepclib.hxx - ./include/bout/smoothing.hxx - ./include/bout/snb.hxx - ./include/bout/solver.hxx - ./include/bout/solverfactory.hxx - ./include/bout/sourcex.hxx - ./include/bout/neutral.hxx - ./include/bout/stencils.hxx - ./include/bout/sundials_backports.hxx - ./include/bout/surfaceiter.hxx - ./include/bout/sys/expressionparser.hxx - ./include/bout/sys/generator_context.hxx - ./include/bout/sys/gettext.hxx - ./include/bout/sys/range.hxx - ./include/bout/sys/timer.hxx - ./include/bout/sys/type_name.hxx - ./include/bout/sys/uncopyable.hxx - ./include/bout/sys/uuid.h - ./include/bout/sys/variant.hxx - ./include/bout/template_combinations.hxx - ./include/bout/traits.hxx - ./include/bout/unused.hxx - ./include/bout/utils.hxx - ./include/bout/vecops.hxx - ./include/bout/vector2d.hxx - ./include/bout/vector3d.hxx - ./include/bout/where.hxx - ./src/bout++.cxx - ./src/bout++-time.hxx - ./src/field/field.cxx - ./src/field/field2d.cxx - ./src/field/field3d.cxx - ./src/field/field_data.cxx - ./src/field/field_factory.cxx - ./src/field/fieldgenerators.cxx - ./src/field/fieldgenerators.hxx - ./src/field/fieldgroup.cxx - ./src/field/fieldperp.cxx - ./src/field/generated_fieldops.cxx - ./src/field/globalfield.cxx - ./src/field/initialprofiles.cxx - ./src/field/vecops.cxx - ./src/field/vector2d.cxx - ./src/field/vector3d.cxx - ./src/field/where.cxx - ./src/invert/fft_fftw.cxx - ./src/invert/lapack_routines.cxx - ./src/invert/laplace/impls/cyclic/cyclic_laplace.cxx - ./src/invert/laplace/impls/cyclic/cyclic_laplace.hxx - ./src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx - ./src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx - ./src/invert/laplace/impls/multigrid/multigrid_alg.cxx - ./src/invert/laplace/impls/multigrid/multigrid_laplace.cxx - ./src/invert/laplace/impls/multigrid/multigrid_laplace.hxx - ./src/invert/laplace/impls/multigrid/multigrid_solver.cxx - ./src/invert/laplace/impls/naulin/naulin_laplace.cxx - ./src/invert/laplace/impls/naulin/naulin_laplace.hxx - ./src/invert/laplace/impls/pcr/pcr.cxx - ./src/invert/laplace/impls/pcr/pcr.hxx - ./src/invert/laplace/impls/pcr_thomas/pcr_thomas.cxx - ./src/invert/laplace/impls/pcr_thomas/pcr_thomas.hxx - ./src/invert/laplace/impls/petsc/petsc_laplace.cxx - ./src/invert/laplace/impls/petsc/petsc_laplace.hxx - ./src/invert/laplace/impls/petsc3damg/petsc3damg.cxx - ./src/invert/laplace/impls/petsc3damg/petsc3damg.hxx - ./src/invert/laplace/impls/serial_band/serial_band.cxx - ./src/invert/laplace/impls/serial_band/serial_band.hxx - ./src/invert/laplace/impls/serial_tri/serial_tri.cxx - ./src/invert/laplace/impls/serial_tri/serial_tri.hxx - ./src/invert/laplace/impls/spt/spt.cxx - ./src/invert/laplace/impls/spt/spt.hxx - ./src/invert/laplace/impls/hypre3d/hypre3d_laplace.cxx - ./src/invert/laplace/impls/hypre3d/hypre3d_laplace.hxx - ./src/invert/laplace/invert_laplace.cxx - ./src/invert/laplacexy/laplacexy.cxx - ./include/bout/invert/laplacexy2.hxx - ./src/invert/laplacexy2/laplacexy2.cxx - ./include/bout/invert/laplacexy2_hypre.hxx - ./src/invert/laplacexy2/laplacexy2_hypre.cxx - ./src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx - ./src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx - ./src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx - ./src/invert/laplacexz/impls/petsc/laplacexz-petsc.hxx - ./src/invert/laplacexz/laplacexz.cxx - ./src/invert/parderiv/impls/cyclic/cyclic.cxx - ./src/invert/parderiv/impls/cyclic/cyclic.hxx - ./src/invert/parderiv/invert_parderiv.cxx - ./src/invert/pardiv/impls/cyclic/pardiv_cyclic.cxx - ./src/invert/pardiv/impls/cyclic/pardiv_cyclic.hxx - ./src/invert/pardiv/invert_pardiv.cxx - ./src/mesh/boundary_factory.cxx - ./src/mesh/boundary_region.cxx - ./src/mesh/boundary_standard.cxx - ./src/mesh/coordinates.cxx - ./src/mesh/coordinates_accessor.cxx - ./src/mesh/data/gridfromfile.cxx - ./src/mesh/data/gridfromoptions.cxx - ./src/mesh/difops.cxx - ./src/mesh/fv_ops.cxx - ./src/mesh/impls/bout/boutmesh.cxx - ./src/mesh/impls/bout/boutmesh.hxx - ./src/mesh/index_derivs.cxx - ./src/mesh/interpolation_xz.cxx - ./src/mesh/interpolation/bilinear_xz.cxx - ./src/mesh/interpolation/hermite_spline_xz.cxx - ./src/mesh/interpolation/hermite_spline_z.cxx - ./src/mesh/interpolation/interpolation_z.cxx - ./src/mesh/interpolation/lagrange_4pt_xz.cxx - ./src/mesh/interpolation/monotonic_hermite_spline_xz.cxx - ./src/mesh/invert3x3.hxx - ./src/mesh/mesh.cxx - ./src/mesh/parallel/fci.cxx - ./src/mesh/parallel/fci.hxx - ./src/mesh/parallel/identity.cxx - ./src/mesh/parallel/shiftedmetric.cxx - ./src/mesh/parallel/shiftedmetricinterp.cxx - ./src/mesh/parallel/shiftedmetricinterp.hxx - ./src/mesh/parallel_boundary_op.cxx - ./src/mesh/parallel_boundary_region.cxx - ./src/mesh/surfaceiter.cxx - ./src/physics/gyro_average.cxx - ./src/physics/physicsmodel.cxx - ./src/physics/smoothing.cxx - ./src/physics/snb.cxx - ./src/physics/sourcex.cxx - ./src/physics/neutral.cxx - ./src/solver/impls/adams_bashforth/adams_bashforth.cxx - ./src/solver/impls/adams_bashforth/adams_bashforth.hxx - ./src/solver/impls/arkode/arkode.cxx - ./src/solver/impls/arkode/arkode.hxx - ./src/solver/impls/arkode/arkode_mri.cxx - ./src/solver/impls/arkode/arkode_mri.hxx - ./src/solver/impls/cvode/cvode.cxx - ./src/solver/impls/cvode/cvode.hxx - ./src/solver/impls/euler/euler.cxx - ./src/solver/impls/euler/euler.hxx - ./src/solver/impls/ida/ida.cxx - ./src/solver/impls/ida/ida.hxx - ./src/solver/impls/imex-bdf2/imex-bdf2.cxx - ./src/solver/impls/imex-bdf2/imex-bdf2.hxx - ./src/solver/impls/petsc/petsc.cxx - ./src/solver/impls/petsc/petsc.hxx - ./src/solver/impls/power/power.cxx - ./src/solver/impls/power/power.hxx - ./src/solver/impls/pvode/pvode.cxx - ./src/solver/impls/pvode/pvode.hxx - ./src/solver/impls/rk3-ssp/rk3-ssp.cxx - ./src/solver/impls/rk3-ssp/rk3-ssp.hxx - ./src/solver/impls/rk4/rk4.cxx - ./src/solver/impls/rk4/rk4.hxx - ./src/solver/impls/rkgeneric/impls/cashkarp/cashkarp.cxx - ./src/solver/impls/rkgeneric/impls/cashkarp/cashkarp.hxx - ./src/solver/impls/rkgeneric/impls/rk4simple/rk4simple.cxx - ./src/solver/impls/rkgeneric/impls/rk4simple/rk4simple.hxx - ./src/solver/impls/rkgeneric/impls/rkf34/rkf34.cxx - ./src/solver/impls/rkgeneric/impls/rkf34/rkf34.hxx - ./src/solver/impls/rkgeneric/impls/rkf45/rkf45.cxx - ./src/solver/impls/rkgeneric/impls/rkf45/rkf45.hxx - ./src/solver/impls/rkgeneric/rkgeneric.cxx - ./src/solver/impls/rkgeneric/rkgeneric.hxx - ./src/solver/impls/rkgeneric/rkscheme.cxx - ./src/solver/impls/slepc/slepc.cxx - ./src/solver/impls/slepc/slepc.hxx - ./src/solver/impls/snes/snes.cxx - ./src/solver/impls/snes/snes.hxx - ./src/solver/impls/split-rk/split-rk.cxx - ./src/solver/impls/split-rk/split-rk.hxx - ./src/solver/solver.cxx - ./src/sys/adios_object.cxx - ./src/sys/bout_types.cxx - ./src/sys/boutcomm.cxx - ./src/sys/boutexception.cxx - ./src/sys/derivs.cxx - ./src/sys/expressionparser.cxx - ./src/sys/generator_context.cxx - ./include/bout/hyprelib.hxx - ./src/sys/hyprelib.cxx - ./src/sys/msg_stack.cxx - ./src/sys/options.cxx - ./src/sys/options/optionparser.hxx - ./src/sys/options/options_ini.cxx - ./src/sys/options/options_ini.hxx - ./src/sys/options/options_io.cxx - ./src/sys/options/options_netcdf.cxx - ./src/sys/options/options_netcdf.hxx - ./src/sys/options/options_adios.cxx - ./src/sys/options/options_adios.hxx - ./src/sys/optionsreader.cxx - ./src/sys/output.cxx - ./src/sys/petsclib.cxx - ./src/sys/range.cxx - ./src/sys/slepclib.cxx - ./src/sys/timer.cxx - ./src/sys/type_name.cxx - ./src/sys/utils.cxx - ${CMAKE_CURRENT_BINARY_DIR}/include/bout/revision.hxx - ${CMAKE_CURRENT_BINARY_DIR}/include/bout/version.hxx - ) - + ./include/bout/adios_object.hxx + ./include/bout/array.hxx + ./include/bout/assert.hxx + ./include/bout/boundary_factory.hxx + ./include/bout/boundary_op.hxx + ./include/bout/boundary_region.hxx + ./include/bout/boundary_standard.hxx + ./include/bout/bout.hxx + ./include/bout/bout_enum_class.hxx + ./include/bout/bout_types.hxx + ./include/bout/boutcomm.hxx + ./include/bout/boutexception.hxx + ./include/bout/build_config.hxx + ./include/bout/caliper_wrapper.hxx + ./include/bout/christoffel_symbols.hxx + ./include/bout/constants.hxx + ./include/bout/coordinates.hxx + ./include/bout/coordinates_accessor.hxx + ./include/bout/cyclic_reduction.hxx + ./include/bout/dcomplex.hxx + ./include/bout/deriv_store.hxx + ./include/bout/derivs.hxx + ./include/bout/difops.hxx + ./include/bout/fft.hxx + ./include/bout/field.hxx + ./include/bout/field2d.hxx + ./include/bout/field3d.hxx + ./include/bout/field_accessor.hxx + ./include/bout/field_data.hxx + ./include/bout/field_factory.hxx + ./include/bout/fieldgroup.hxx + ./include/bout/fieldops.hxx + ./include/bout/fieldperp.hxx + ./include/bout/fv_ops.hxx + ./include/bout/fv_ops_impl.hxx + ./include/bout/g_values.hxx + ./include/bout/generic_factory.hxx + ./include/bout/git_metadata.hxx + ./include/bout/globalfield.hxx + ./include/bout/globalindexer.hxx + ./include/bout/globals.hxx + ./include/bout/griddata.hxx + ./include/bout/gyro_average.hxx + ./include/bout/hypre_interface.hxx + ./include/bout/hyprelib.hxx + ./include/bout/index_derivs.hxx + ./include/bout/index_derivs_interface.hxx + ./include/bout/initialprofiles.hxx + ./include/bout/interpolation.hxx + ./include/bout/interpolation_xz.hxx + ./include/bout/interpolation_z.hxx + ./include/bout/invert/laplacexy.hxx + ./include/bout/invert/laplacexz.hxx + ./include/bout/invert_laplace.hxx + ./include/bout/invert_parderiv.hxx + ./include/bout/invert_pardiv.hxx + ./include/bout/invertable_operator.hxx + ./include/bout/lapack_routines.hxx + ./include/bout/macro_for_each.hxx + ./include/bout/mask.hxx + ./include/bout/mesh.hxx + ./include/bout/metric_tensor.hxx + ./include/bout/monitor.hxx + ./include/bout/mpi_wrapper.hxx + ./include/bout/msg_stack.hxx + ./include/bout/multiostream.hxx + ./include/bout/openmpwrap.hxx + ./include/bout/operatorstencil.hxx + ./include/bout/options.hxx + ./include/bout/options_io.hxx + ./include/bout/optionsreader.hxx + ./include/bout/output.hxx + ./include/bout/output_bout_types.hxx + ./include/bout/parallel_boundary_op.hxx + ./include/bout/paralleltransform.hxx + ./include/bout/petsc_interface.hxx + ./include/bout/petsc_operators.hxx + ./include/bout/petsclib.hxx + ./include/bout/physicsmodel.hxx + ./include/bout/rajalib.hxx + ./include/bout/region.hxx + ./include/bout/rkscheme.hxx + ./include/bout/rvec.hxx + ./include/bout/scorepwrapper.hxx + ./include/bout/single_index_ops.hxx + ./include/bout/slepclib.hxx + ./include/bout/smoothing.hxx + ./include/bout/snb.hxx + ./include/bout/solver.hxx + ./include/bout/solverfactory.hxx + ./include/bout/sourcex.hxx + ./include/bout/stencils.hxx + ./include/bout/sundials_backports.hxx + ./include/bout/surfaceiter.hxx + ./include/bout/sys/expressionparser.hxx + ./include/bout/sys/generator_context.hxx + ./include/bout/sys/gettext.hxx + ./include/bout/sys/range.hxx + ./include/bout/sys/timer.hxx + ./include/bout/sys/type_name.hxx + ./include/bout/sys/uncopyable.hxx + ./include/bout/sys/uuid.h + ./include/bout/sys/variant.hxx + ./include/bout/template_combinations.hxx + ./include/bout/tokamak_coordinates.hxx + ./include/bout/traits.hxx + ./include/bout/twiddle.hxx + ./include/bout/unused.hxx + ./include/bout/utils.hxx + ./include/bout/vecops.hxx + ./include/bout/vector2d.hxx + ./include/bout/vector3d.hxx + ./include/bout/where.hxx + ./include/bout/yboundary_regions.hxx + ./src/bout++-time.hxx + ./src/bout++.cxx + ./src/field/field.cxx + ./src/field/field2d.cxx + ./src/field/field3d.cxx + ./src/field/field_data.cxx + ./src/field/field_factory.cxx + ./src/field/fieldgenerators.cxx + ./src/field/fieldgenerators.hxx + ./src/field/fieldgroup.cxx + ./src/field/fieldperp.cxx + ./src/field/generated_fieldops.cxx + ./src/field/globalfield.cxx + ./src/field/initialprofiles.cxx + ./src/field/vecops.cxx + ./src/field/vector2d.cxx + ./src/field/vector3d.cxx + ./src/field/where.cxx + ./src/invert/fft_fftw.cxx + ./src/invert/lapack_routines.cxx + ./src/invert/laplace/common_transform.cxx + ./src/invert/laplace/common_transform.hxx + ./src/invert/laplace/impls/cyclic/cyclic_laplace.cxx + ./src/invert/laplace/impls/cyclic/cyclic_laplace.hxx + ./src/invert/laplace/impls/hypre3d/hypre3d_laplace.cxx + ./src/invert/laplace/impls/hypre3d/hypre3d_laplace.hxx + ./src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx + ./src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx + ./src/invert/laplace/impls/multigrid/multigrid_alg.cxx + ./src/invert/laplace/impls/multigrid/multigrid_laplace.cxx + ./src/invert/laplace/impls/multigrid/multigrid_laplace.hxx + ./src/invert/laplace/impls/multigrid/multigrid_solver.cxx + ./src/invert/laplace/impls/naulin/naulin_laplace.cxx + ./src/invert/laplace/impls/naulin/naulin_laplace.hxx + ./src/invert/laplace/impls/pcr/pcr.cxx + ./src/invert/laplace/impls/pcr/pcr.hxx + ./src/invert/laplace/impls/pcr_thomas/pcr_thomas.cxx + ./src/invert/laplace/impls/pcr_thomas/pcr_thomas.hxx + ./src/invert/laplace/impls/petsc/petsc_laplace.cxx + ./src/invert/laplace/impls/petsc/petsc_laplace.hxx + ./src/invert/laplace/impls/petsc3damg/petsc3damg.cxx + ./src/invert/laplace/impls/petsc3damg/petsc3damg.hxx + ./src/invert/laplace/impls/serial_band/serial_band.cxx + ./src/invert/laplace/impls/serial_band/serial_band.hxx + ./src/invert/laplace/impls/serial_tri/serial_tri.cxx + ./src/invert/laplace/impls/serial_tri/serial_tri.hxx + ./src/invert/laplace/impls/spt/spt.cxx + ./src/invert/laplace/impls/spt/spt.hxx + ./src/invert/laplace/invert_laplace.cxx + ./src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx + ./src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx + ./src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx + ./src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx + ./src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx + ./src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx + ./src/invert/laplacexy/laplacexy.cxx + ./src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx + ./src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx + ./src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx + ./src/invert/laplacexz/impls/petsc/laplacexz-petsc.hxx + ./src/invert/laplacexz/laplacexz.cxx + ./src/invert/parderiv/impls/cyclic/cyclic.cxx + ./src/invert/parderiv/impls/cyclic/cyclic.hxx + ./src/invert/parderiv/invert_parderiv.cxx + ./src/invert/pardiv/impls/cyclic/pardiv_cyclic.cxx + ./src/invert/pardiv/impls/cyclic/pardiv_cyclic.hxx + ./src/invert/pardiv/invert_pardiv.cxx + ./src/mesh/boundary_factory.cxx + ./src/mesh/boundary_region.cxx + ./src/mesh/boundary_standard.cxx + ./src/mesh/christoffel_symbols.cxx + ./src/mesh/coordinates.cxx + ./src/mesh/coordinates_accessor.cxx + ./src/mesh/data/gridfromfile.cxx + ./src/mesh/data/gridfromoptions.cxx + ./src/mesh/difops.cxx + ./src/mesh/fv_ops.cxx + ./src/mesh/g_values.cxx + ./src/mesh/impls/bout/boutmesh.cxx + ./src/mesh/impls/bout/boutmesh.hxx + ./src/mesh/index_derivs.cxx + ./src/mesh/interpolation/bilinear_xz.cxx + ./src/mesh/interpolation/hermite_spline_xz.cxx + ./src/mesh/interpolation/hermite_spline_z.cxx + ./src/mesh/interpolation/interpolation_z.cxx + ./src/mesh/interpolation/lagrange_4pt_xz.cxx + ./src/mesh/interpolation_xz.cxx + ./src/mesh/invert3x3.hxx + ./src/mesh/mesh.cxx + ./src/mesh/metric_tensor.cxx + ./src/mesh/parallel/fci.cxx + ./src/mesh/parallel/fci.hxx + ./src/mesh/parallel/fci_comm.cxx + ./src/mesh/parallel/fci_comm.hxx + ./src/mesh/parallel/identity.cxx + ./src/mesh/parallel/shiftedmetric.cxx + ./src/mesh/parallel/shiftedmetricinterp.cxx + ./src/mesh/parallel/shiftedmetricinterp.hxx + ./src/mesh/parallel_boundary_op.cxx + ./src/mesh/parallel_boundary_region.cxx + ./src/mesh/petsc_operators.cxx + ./src/mesh/surfaceiter.cxx + ./src/mesh/tokamak_coordinates.cxx + ./src/mesh/yboundary_regions.cxx + ./src/physics/gyro_average.cxx + ./src/physics/physicsmodel.cxx + ./src/physics/smoothing.cxx + ./src/physics/snb.cxx + ./src/physics/sourcex.cxx + ./src/solver/impls/adams_bashforth/adams_bashforth.cxx + ./src/solver/impls/adams_bashforth/adams_bashforth.hxx + ./src/solver/impls/arkode/arkode.cxx + ./src/solver/impls/arkode/arkode.hxx + ./src/solver/impls/arkode/arkode_mri.cxx + ./src/solver/impls/arkode/arkode_mri.hxx + ./src/solver/impls/cvode/cvode.cxx + ./src/solver/impls/cvode/cvode.hxx + ./src/solver/impls/euler/euler.cxx + ./src/solver/impls/euler/euler.hxx + ./src/solver/impls/ida/ida.cxx + ./src/solver/impls/ida/ida.hxx + ./src/solver/impls/imex-bdf2/imex-bdf2.cxx + ./src/solver/impls/imex-bdf2/imex-bdf2.hxx + ./src/solver/impls/petsc/petsc.cxx + ./src/solver/impls/petsc/petsc.hxx + ./src/solver/impls/power/power.cxx + ./src/solver/impls/power/power.hxx + ./src/solver/impls/pvode/pvode.cxx + ./src/solver/impls/pvode/pvode.hxx + ./src/solver/impls/rk3-ssp/rk3-ssp.cxx + ./src/solver/impls/rk3-ssp/rk3-ssp.hxx + ./src/solver/impls/rk4/rk4.cxx + ./src/solver/impls/rk4/rk4.hxx + ./src/solver/impls/rkgeneric/impls/cashkarp/cashkarp.cxx + ./src/solver/impls/rkgeneric/impls/cashkarp/cashkarp.hxx + ./src/solver/impls/rkgeneric/impls/rk4simple/rk4simple.cxx + ./src/solver/impls/rkgeneric/impls/rk4simple/rk4simple.hxx + ./src/solver/impls/rkgeneric/impls/rkf34/rkf34.cxx + ./src/solver/impls/rkgeneric/impls/rkf34/rkf34.hxx + ./src/solver/impls/rkgeneric/impls/rkf45/rkf45.cxx + ./src/solver/impls/rkgeneric/impls/rkf45/rkf45.hxx + ./src/solver/impls/rkgeneric/rkgeneric.cxx + ./src/solver/impls/rkgeneric/rkgeneric.hxx + ./src/solver/impls/rkgeneric/rkscheme.cxx + ./src/solver/impls/slepc/slepc.cxx + ./src/solver/impls/slepc/slepc.hxx + ./src/solver/impls/snes/snes.cxx + ./src/solver/impls/snes/snes.hxx + ./src/solver/impls/split-rk/split-rk.cxx + ./src/solver/impls/split-rk/split-rk.hxx + ./src/solver/petsc_preconditioner.cxx + ./src/solver/solver.cxx + ./src/sys/adios_object.cxx + ./src/sys/bout_types.cxx + ./src/sys/boutcomm.cxx + ./src/sys/boutexception.cxx + ./src/sys/derivs.cxx + ./src/sys/expressionparser.cxx + ./src/sys/generator_context.cxx + ./src/sys/hyprelib.cxx + ./src/sys/hypre_interface.cxx + ./src/sys/msg_stack.cxx + ./src/sys/options.cxx + ./src/sys/options/optionparser.hxx + ./src/sys/options/options_adios.cxx + ./src/sys/options/options_adios.hxx + ./src/sys/options/options_ini.cxx + ./src/sys/options/options_ini.hxx + ./src/sys/options/options_io.cxx + ./src/sys/options/options_netcdf.cxx + ./src/sys/options/options_netcdf.hxx + ./src/sys/optionsreader.cxx + ./src/sys/output.cxx + ./src/sys/output_bout_types.cxx + ./src/sys/petsclib.cxx + ./src/sys/range.cxx + ./src/sys/slepclib.cxx + ./src/sys/timer.cxx + ./src/sys/type_name.cxx + ./src/sys/utils.cxx + ${CMAKE_CURRENT_BINARY_DIR}/include/bout/revision.hxx + ${CMAKE_CURRENT_BINARY_DIR}/include/bout/version.hxx +) find_package(Python3) find_package(ClangFormat) -if (Python3_FOUND AND ClangFormat_FOUND) +if(Python3_FOUND AND ClangFormat_FOUND) set(BOUT_GENERATE_FIELDOPS_DEFAULT ON) else() set(BOUT_GENERATE_FIELDOPS_DEFAULT OFF) endif() -execute_process(COMMAND ${Python3_EXECUTABLE} -c "import importlib.util ; import sys; sys.exit(importlib.util.find_spec(\"zoidberg\") is None)" - RESULT_VARIABLE zoidberg_FOUND) -if (zoidberg_FOUND EQUAL 0) +execute_process( + COMMAND + ${Python3_EXECUTABLE} -c + "import importlib.util ; import sys; sys.exit(importlib.util.find_spec(\"zoidberg\") is None)" + RESULT_VARIABLE zoidberg_FOUND +) +if(zoidberg_FOUND EQUAL 0) set(zoidberg_FOUND ON) else() set(zoidberg_FOUND OFF) endif() +message(STATUS "Found Zoidberg for FCI tests: ${zoidberg_FOUND}") -option(BOUT_GENERATE_FIELDOPS "Automatically re-generate the Field arithmetic operators from the Python templates. \ +option( + BOUT_GENERATE_FIELDOPS + "Automatically re-generate the Field arithmetic operators from the Python templates. \ Requires Python3, clang-format, and Jinja2. Turn this OFF to skip generating them if, for example, \ -you are unable to install the Jinja2 Python module. This is only important for BOUT++ developers." ${BOUT_GENERATE_FIELDOPS_DEFAULT}) +you are unable to install the Jinja2 Python module. This is only important for BOUT++ developers." + ${BOUT_GENERATE_FIELDOPS_DEFAULT} +) -if (BOUT_GENERATE_FIELDOPS) - if (NOT Python3_FOUND) - message(FATAL_ERROR "python not found, but you have requested to generate code!") +if(BOUT_GENERATE_FIELDOPS) + if(NOT Python3_FOUND) + message( + FATAL_ERROR "python not found, but you have requested to generate code!" + ) endif() - if (NOT ClangFormat_FOUND) - message(FATAL_ERROR "clang-format not found, but you have requested to generate code!") + if(NOT ClangFormat_FOUND) + message( + FATAL_ERROR + "clang-format not found, but you have requested to generate code!" + ) endif() - add_custom_command( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/field/generated_fieldops.cxx - COMMAND ${Python3_EXECUTABLE} gen_fieldops.py --filename generated_fieldops.cxx.tmp + if(BOUT_ENABLE_RAJA) + set(GEN_LOOP_EXEC "raja") + elseif(BOUT_ENABLE_OPENMP) + set(GEN_LOOP_EXEC "openmp") + else() + set(GEN_LOOP_EXEC "serial") + endif() + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/field/generated_fieldops.cxx + COMMAND ${Python3_EXECUTABLE} gen_fieldops.py --loop-exec ${GEN_LOOP_EXEC} + --filename generated_fieldops.cxx.tmp COMMAND ${ClangFormat_BIN} generated_fieldops.cxx.tmp -i - COMMAND ${CMAKE_COMMAND} -E rename generated_fieldops.cxx.tmp generated_fieldops.cxx - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/field/gen_fieldops.jinja ${CMAKE_CURRENT_SOURCE_DIR}/src/field/gen_fieldops.py + COMMAND ${CMAKE_COMMAND} -E rename generated_fieldops.cxx.tmp + generated_fieldops.cxx + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/field/gen_fieldops.jinja + ${CMAKE_CURRENT_SOURCE_DIR}/src/field/gen_fieldops.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/field/ - COMMENT "Generating source code" ) + COMMENT "Generating source code" + ) else() - message(AUTHOR_WARNING "'src/field/generated_fieldops.cxx' will not be \ + message( + AUTHOR_WARNING + "'src/field/generated_fieldops.cxx' will not be \ regenerated when you make changes to either \ 'src/field/gen_fieldops.py' or 'src/field/gen_fieldops.jinja'. \ This is because either Python3 or clang-format is missing \ (see above messages for more information) \ or BOUT_GENERATE_FIELDOPS is OFF (current value: ${BOUT_GENERATE_FIELDOPS}). \ This warning is only important for BOUT++ developers and can otherwise be \ -safely ignored.") +safely ignored." + ) endif() include(GNUInstallDirs) @@ -422,59 +493,86 @@ set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") # which point to directories outside the build tree to the install RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - -execute_process(COMMAND ${Python3_EXECUTABLE} -c "import site ; print('/'.join(site.getusersitepackages().split('/')[-2:]))" +execute_process( + COMMAND + ${Python3_EXECUTABLE} -c + "import site ; print('/'.join(site.getusersitepackages().split('/')[-2:]))" RESULT_VARIABLE PYTHON_WORKING OUTPUT_VARIABLE PYTHON_SITEPATH_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE ) -set(CMAKE_INSTALL_PYTHON_SITEARCH lib/${PYTHON_SITEPATH_SUFFIX} CACHE STRING "Location to install python arch-specific modules") +set(CMAKE_INSTALL_PYTHON_SITEARCH + lib/${PYTHON_SITEPATH_SUFFIX} + CACHE STRING "Location to install python arch-specific modules" +) set(ON_OFF_AUTO ON OFF AUTO) -set(BOUT_ENABLE_PYTHON AUTO CACHE STRING "Build the Python interface") +set(BOUT_ENABLE_PYTHON + AUTO + CACHE STRING "Build the Python interface" +) set_property(CACHE BOUT_ENABLE_PYTHON PROPERTY STRINGS ${ON_OFF_AUTO}) -if (NOT BOUT_ENABLE_PYTHON IN_LIST ON_OFF_AUTO) +if(NOT BOUT_ENABLE_PYTHON IN_LIST ON_OFF_AUTO) message(FATAL_ERROR "BOUT_ENABLE_PYTHON must be one of ${ON_OFF_AUTO}") endif() -if (BOUT_ENABLE_PYTHON OR BOUT_ENABLE_PYTHON STREQUAL "AUTO") +if(BOUT_ENABLE_PYTHON OR BOUT_ENABLE_PYTHON STREQUAL "AUTO") add_subdirectory(tools/pylib/_boutpp_build) else() set(BOUT_ENABLE_PYTHON OFF) endif() set(BOUT_USE_PYTHON ${BOUT_ENABLE_PYTHON}) +set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/git_metadata.cxx PROPERTIES GENERATED TRUE +) +add_custom_target( + bout++-git-metadata + COMMAND + ${CMAKE_COMMAND} -DOUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/git_metadata.cxx + -DSOURCE_DIR=${PROJECT_SOURCE_DIR} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -P + "${CMAKE_CURRENT_LIST_DIR}/cmake/GenerateGitMetadata.cmake" + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/git_metadata.cxx + COMMENT "Generating git metadata source" +) + # Ensure that the compile date/time is up-to-date when any of the sources change add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bout++-time.cxx - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/cmake/GenerateDateTimeFile.cmake" - DEPENDS ${BOUT_SOURCES} + COMMAND ${CMAKE_COMMAND} -P + "${CMAKE_CURRENT_LIST_DIR}/cmake/GenerateDateTimeFile.cmake" + DEPENDS ${BOUT_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/git_metadata.cxx MAIN_DEPENDENCY "${CMAKE_CURRENT_LIST_DIR}/cmake/GenerateDateTimeFile.cmake" - ) - +) -add_library(bout++ - ${BOUT_SOURCES} - ${CMAKE_CURRENT_BINARY_DIR}/bout++-time.cxx - ) +add_library( + bout++ ${BOUT_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/bout++-time.cxx + ${CMAKE_CURRENT_BINARY_DIR}/git_metadata.cxx +) add_library(bout++::bout++ ALIAS bout++) +add_dependencies(bout++ bout++-git-metadata) target_link_libraries(bout++ PUBLIC MPI::MPI_CXX) -target_include_directories(bout++ PUBLIC - $ - $ - $ - ) +target_include_directories( + bout++ + PUBLIC $ + $ + $ +) set(BOUT_LIB_PATH "${CMAKE_CURRENT_BINARY_DIR}/lib") -set_target_properties(bout++ PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${BOUT_LIB_PATH}" - ARCHIVE_OUTPUT_DIRECTORY "${BOUT_LIB_PATH}" - SOVERSION 5.1.0) +set_target_properties( + bout++ + PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${BOUT_LIB_PATH}" + ARCHIVE_OUTPUT_DIRECTORY "${BOUT_LIB_PATH}" + SOVERSION 5.2.0 +) # Set some variables for the bout-config script set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} -L\$BOUT_LIB_PATH -lbout++") set(BOUT_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include") -set(CONFIG_CFLAGS "${CONFIG_CFLAGS} -I\${BOUT_INCLUDE_PATH} -I${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CXX_FLAGS} -std=c++17") +set(CONFIG_CFLAGS + "${CONFIG_CFLAGS} -I\${BOUT_INCLUDE_PATH} -I${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CXX_FLAGS} -std=c++20" +) -target_compile_features(bout++ PUBLIC cxx_std_17) +target_compile_features(bout++ PUBLIC cxx_std_20) set_target_properties(bout++ PROPERTIES CXX_EXTENSIONS OFF) # Optional compiler features @@ -496,6 +594,7 @@ set(BOUT_VERSION_MINOR ${PROJECT_VERSION_MINOR}) set(BOUT_VERSION_PATCH ${PROJECT_VERSION_PATCH}) # Get the git commit +find_package(Git QUIET) include(GetGitRevisionDescription) get_git_head_revision(GIT_REFSPEC BOUT_REVISION) if(BOUT_REVISION STREQUAL "GITDIR-NOTFOUND") @@ -506,58 +605,77 @@ message(STATUS "Git revision: ${BOUT_REVISION}") # Build the file containing the version information configure_file( "${PROJECT_SOURCE_DIR}/include/bout/version.hxx.in" - "${PROJECT_BINARY_DIR}/include/bout/version.hxx") + "${PROJECT_BINARY_DIR}/include/bout/version.hxx" +) # Build the file containing just the commit hash # This will be rebuilt on every commit! configure_file( "${PROJECT_SOURCE_DIR}/include/bout/revision.hxx.in" - "${PROJECT_BINARY_DIR}/include/bout/revision.hxx") + "${PROJECT_BINARY_DIR}/include/bout/revision.hxx" +) ################################################## option(BOUT_ENABLE_WARNINGS "Enable compiler warnings" ON) -if (BOUT_ENABLE_WARNINGS) - target_compile_options(bout++ PRIVATE - $<$>: - $<$,$,$>: - -Wall -Wextra > > - $<$: - /W4 > - $<$:-Xcompiler=-Wall -Xcompiler=-Wextra > - ) - - include(EnableCXXWarningIfSupport) - # Note we explicitly turn off -Wcast-function-type as PETSc *requires* - # we cast a function to the wrong type in MatFDColoringSetFunction - target_enable_cxx_warning_if_supported(bout++ - FLAGS -Wnull-dereference -Wno-cast-function-type - ) +if(BOUT_ENABLE_WARNINGS) + target_compile_options( + bout++ + PRIVATE + $<$>: + $<$,$,$>: + -Wall + -Wextra + > + > + $<$: + /W4 + > + $<$:-Xcompiler=-Wall + -Xcompiler=-Wextra + > + ) + + include(EnableCXXWarningIfSupport) + # Note we explicitly turn off -Wcast-function-type as PETSc *requires* + # we cast a function to the wrong type in MatFDColoringSetFunction + target_enable_cxx_warning_if_supported( + bout++ FLAGS -Wnull-dereference -Wno-cast-function-type + ) endif() # Compile time features set(CHECK_LEVELS 0 1 2 3 4) -set(CHECK 2 CACHE STRING "Set run-time checking level") +set(CHECK + 2 + CACHE STRING "Set run-time checking level" +) set_property(CACHE CHECK PROPERTY STRINGS ${CHECK_LEVELS}) -if (NOT CHECK IN_LIST CHECK_LEVELS) +if(NOT CHECK IN_LIST CHECK_LEVELS) message(FATAL_ERROR "CHECK must be one of ${CHECK_LEVELS}") endif() message(STATUS "Runtime checking level: CHECK=${CHECK}") target_compile_definitions(bout++ PUBLIC "CHECK=${CHECK}") set(BOUT_CHECK_LEVEL ${CHECK}) -if (CHECK GREATER 1) +if(CHECK GREATER 1) set(bout_use_msgstack_default ON) else() set(bout_use_msgstack_default OFF) endif() -set(BOUT_ENABLE_MSGSTACK ${bout_use_msgstack_default} CACHE BOOL "Enable debug message stack") +set(BOUT_ENABLE_MSGSTACK + ${bout_use_msgstack_default} + CACHE BOOL "Enable debug message stack" +) message(STATUS "Message stack: BOUT_USE_MSGSTACK=${BOUT_ENABLE_MSGSTACK}") set(BOUT_USE_MSGSTACK ${BOUT_ENABLE_MSGSTACK}) -cmake_dependent_option(BOUT_ENABLE_OUTPUT_DEBUG "Enable extra debug output" OFF - "CHECK LESS 3" ON) -message(STATUS "Extra debug output: BOUT_USE_OUTPUT_DEBUG=${BOUT_ENABLE_OUTPUT_DEBUG}") +cmake_dependent_option( + BOUT_ENABLE_OUTPUT_DEBUG "Enable extra debug output" OFF "CHECK LESS 3" ON +) +message( + STATUS "Extra debug output: BOUT_USE_OUTPUT_DEBUG=${BOUT_ENABLE_OUTPUT_DEBUG}" +) set(BOUT_USE_OUTPUT_DEBUG ${BOUT_ENABLE_OUTPUT_DEBUG}) option(BOUT_ENABLE_SIGNAL "SegFault handling" ON) @@ -573,21 +691,12 @@ message(STATUS "Field name tracking: BOUT_USE_TRACK=${BOUT_ENABLE_TRACK}") set(BOUT_USE_TRACK ${BOUT_ENABLE_TRACK}) option(BOUT_ENABLE_SIGFPE "Signalling floating point exceptions" OFF) -message(STATUS "Signalling floating point exceptions: BOUT_USE_SIGFPE=${BOUT_ENABLE_SIGFPE}") +message( + STATUS + "Signalling floating point exceptions: BOUT_USE_SIGFPE=${BOUT_ENABLE_SIGFPE}" +) set(BOUT_USE_SIGFPE ${BOUT_ENABLE_SIGFPE}) -option(BOUT_ENABLE_BACKTRACE "Enable backtrace" ON) -if (BOUT_ENABLE_BACKTRACE) - find_program(ADDR2LINE_FOUND addr2line) - if (NOT ADDR2LINE_FOUND) - message(FATAL_ERROR "addr2line not found. Disable backtrace by setting BOUT_ENABLE_BACKTRACE=Off") - endif() - target_link_libraries(bout++ PUBLIC ${CMAKE_DL_LIBS}) - set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} -l${CMAKE_DL_LIBS}") -endif() -message(STATUS "Enable backtrace: BOUT_USE_BACKTRACE=${BOUT_ENABLE_BACKTRACE}") -set(BOUT_USE_BACKTRACE ${BOUT_ENABLE_BACKTRACE}) - option(BOUT_ENABLE_METRIC_3D "Enable 3D metric support" OFF) if(BOUT_ENABLE_METRIC_3D) set(BOUT_METRIC_TYPE "3D") @@ -597,12 +706,15 @@ endif() set(BOUT_USE_METRIC_3D ${BOUT_ENABLE_METRIC_3D}) include(CheckCXXSourceCompiles) -check_cxx_source_compiles("int main() { const char* name = __PRETTY_FUNCTION__; }" - HAS_PRETTY_FUNCTION) +check_cxx_source_compiles( + "int main() { const char* name = __PRETTY_FUNCTION__; }" HAS_PRETTY_FUNCTION +) set(BOUT_HAS_PRETTY_FUNCTION ${HAS_PRETTY_FUNCTION}) # Locations of the various Python modules, including the generated boutconfig module -set(BOUT_PYTHONPATH "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib:${CMAKE_CURRENT_SOURCE_DIR}/tools/pylib") +set(BOUT_PYTHONPATH + "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib:${CMAKE_CURRENT_SOURCE_DIR}/tools/pylib" +) # Variables for boutconfig module -- note that these will contain # generator expressions and CMake targets, and not generally be very # useful @@ -615,18 +727,22 @@ get_target_property(BOUT_CFLAGS bout++ INTERFACE_INCLUDE_DIRECTORIES) # 1. Get the macro definitions. They come as a ;-separated list and # without the -D. We also need to also stick a -D on the front of # the first item -get_property(BOUT_COMPILE_DEFINITIONS +get_property( + BOUT_COMPILE_DEFINITIONS TARGET bout++ - PROPERTY COMPILE_DEFINITIONS) + PROPERTY COMPILE_DEFINITIONS +) string(REPLACE ";" " -D" BOUT_COMPILE_DEFINITIONS "${BOUT_COMPILE_DEFINITIONS}") string(CONCAT BOUT_COMPILE_DEFINITIONS " -D" "${BOUT_COMPILE_DEFINITIONS}") # 2. Get the compiler options. Again, they come as a ;-separated # list. Note that they don't include optimisation or debug flags: # they're in the CMAKE_CXX_FLAGS* variables -get_property(BOUT_COMPILE_OPTIONS +get_property( + BOUT_COMPILE_OPTIONS TARGET bout++ - PROPERTY COMPILE_OPTIONS) + PROPERTY COMPILE_OPTIONS +) string(REPLACE ";" " " BOUT_COMPILE_OPTIONS "${BOUT_COMPILE_OPTIONS}") # 3. The optimisation and/or debug flags are in the CMAKE_CXX_FLAGS* @@ -638,32 +754,35 @@ string(REPLACE ";" " " BOUT_COMPILE_OPTIONS "${BOUT_COMPILE_OPTIONS}") include(BuildType) # Here CMAKE_BUILD_TYPE is always set string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPER) -string(CONCAT BOUT_COMPILE_BUILD_FLAGS - " " - "${CMAKE_CXX_FLAGS}" - "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") +string(CONCAT BOUT_COMPILE_BUILD_FLAGS " " "${CMAKE_CXX_FLAGS}" + "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}" +) # 4. Now we join all the flags from the first three steps together -string(CONCAT BOUT_FLAGS_STRING - "${BOUT_COMPILE_OPTIONS}" - "${BOUT_COMPILE_DEFINITIONS}" - "${BOUT_COMPILE_BUILD_FLAGS}") +string(CONCAT BOUT_FLAGS_STRING "${BOUT_COMPILE_OPTIONS}" + "${BOUT_COMPILE_DEFINITIONS}" "${BOUT_COMPILE_BUILD_FLAGS}" +) # 5. Finally actually add the flags as a define -target_compile_definitions(bout++ - PRIVATE BOUT_FLAGS_STRING=${BOUT_FLAGS_STRING}) +target_compile_definitions( + bout++ PRIVATE BOUT_FLAGS_STRING=${BOUT_FLAGS_STRING} +) ################################################## # Tests # Are we building BOUT++ directly, or as part of another project -string(COMPARE EQUAL - "${PROJECT_NAME}" "${CMAKE_PROJECT_NAME}" - PROJECT_IS_TOP_LEVEL +string(COMPARE EQUAL "${PROJECT_NAME}" "${CMAKE_PROJECT_NAME}" + PROJECT_IS_TOP_LEVEL ) option(BOUT_TESTS "Build the tests" ${PROJECT_IS_TOP_LEVEL}) -option(BOUT_ENABLE_ALL_TESTS "Enable running all of the tests, rather then the standard selection of fast tests" OFF) +option( + BOUT_ENABLE_ALL_TESTS + "Enable running all of the tests, rather then the standard selection of fast tests" + OFF +) if(BOUT_TESTS) + set(CMAKE_CTEST_ARGUMENTS "--output-on-failure" "--timeout" "300") enable_testing() # Targets for just building the tests # Tests need to add themselves as dependencies to these targets @@ -673,34 +792,63 @@ if(BOUT_TESTS) # Build all the tests add_custom_target(build-check) - add_dependencies(build-check build-check-unit-tests build-check-integrated-tests build-check-mms-tests) + add_dependencies( + build-check build-check-unit-tests build-check-integrated-tests + build-check-mms-tests + ) add_subdirectory(tests/unit EXCLUDE_FROM_ALL) add_subdirectory(tests/integrated EXCLUDE_FROM_ALL) add_subdirectory(tests/MMS EXCLUDE_FROM_ALL) # Targets for running the tests - if (BOUT_ENABLE_UNIT_TESTS) - add_custom_target(check-unit-tests - COMMAND ctest -R serial_tests --output-on-failure) + if(BOUT_ENABLE_UNIT_TESTS) + add_custom_target( + check-unit-tests COMMAND ctest -R serial_tests --output-on-failure + ) add_dependencies(check-unit-tests build-check-unit-tests) endif() - add_custom_target(check-integrated-tests - COMMAND ctest -R "test-" --output-on-failure) + add_custom_target( + check-integrated-tests + COMMAND bash "${PROJECT_BINARY_DIR}/tests/run_integrated_tests.sh" + ) add_dependencies(check-integrated-tests build-check-integrated-tests) - add_custom_target(check-mms-tests - COMMAND ctest -R "MMS-" --output-on-failure) + add_custom_target(check-mms-tests COMMAND ctest -R "MMS-" --output-on-failure) add_dependencies(check-mms-tests build-check-mms-tests) # Run all the tests add_custom_target(check) add_dependencies(check check-integrated-tests check-mms-tests) - if (BOUT_ENABLE_UNIT_TESTS) + if(BOUT_ENABLE_UNIT_TESTS) add_dependencies(check check-unit-tests) endif() + # Copy the pytest config file + configure_file( + "${PROJECT_SOURCE_DIR}/tests/conftest.py" + "${PROJECT_BINARY_DIR}/tests/conftest.py" + ) + + # Copy the pyproject.toml file + configure_file( + "${PROJECT_SOURCE_DIR}/pyproject.toml" + "${PROJECT_BINARY_DIR}/pyproject.toml" + ) + + # Copy the pytest config file for the boutpp tests + configure_file( + "${PROJECT_SOURCE_DIR}/tests/integrated/test-boutpp/conftest.py" + "${PROJECT_BINARY_DIR}/tests/integrated/test-boutpp/conftest.py" + ) + + # Copy the pytest shell script + configure_file( + "${PROJECT_SOURCE_DIR}/tests/run_integrated_tests.sh" + "${PROJECT_BINARY_DIR}/tests/run_integrated_tests.sh" @ONLY + ) + endif() option(BOUT_BUILD_EXAMPLES "Build the examples" ON) @@ -709,21 +857,22 @@ if(BOUT_BUILD_EXAMPLES) add_subdirectory(examples EXCLUDE_FROM_ALL) endif() - ################################################## # L10N: localisation - include translations find_package(Gettext) -if (GETTEXT_FOUND) +if(GETTEXT_FOUND) #add_custom_target(mofiles ALL) set(bout_langs es de fr zh_CN zh_TW) foreach(_lang IN LISTS bout_langs) set(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/locale/${_lang}/libbout.gmo) set(_poFile ${CMAKE_CURRENT_SOURCE_DIR}/locale/${_lang}/libbout.po) - add_custom_command(OUTPUT ${_gmoFile} _mo_file_${_lang} - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/locale/${_lang}/ + add_custom_command( + OUTPUT ${_gmoFile} _mo_file_${_lang} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_CURRENT_BINARY_DIR}/locale/${_lang}/ COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_poFile} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" DEPENDS ${_poFile} @@ -731,41 +880,46 @@ if (GETTEXT_FOUND) list(APPEND _gmoFiles ${_gmoFile}) - install(FILES ${_gmoFile} DESTINATION ${CMAKE_INSTALL_LOCALEDIR}/${_lang}/LC_MESSAGES/ RENAME libbout.mo) + install( + FILES ${_gmoFile} + DESTINATION ${CMAKE_INSTALL_LOCALEDIR}/${_lang}/LC_MESSAGES/ + RENAME libbout.mo + ) endforeach() - add_custom_target(mofiles ALL - DEPENDS ${_gmoFiles}) + add_custom_target(mofiles ALL DEPENDS ${_gmoFiles}) endif() - ################################################## # Documentation option(BOUT_BUILD_DOCS "Build the documentation" OFF) -if (BOUT_BUILD_DOCS) - add_subdirectory(manual EXCLUDE_FROM_ALL) +if(BOUT_BUILD_DOCS) + add_subdirectory(manual) endif() - -add_custom_target(dist - COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/pylib/_boutpp_build/backend.py dist +add_custom_target( + dist + COMMAND ${Python3_EXECUTABLE} + ${CMAKE_SOURCE_DIR}/tools/pylib/_boutpp_build/backend.py dist # there is no cmake equivalent to `mv` - so only works on systems that are not inentionally non-POSIX complient COMMAND mv BOUT++-v${BOUT_FULL_VERSION}.tar.gz ${CMAKE_CURRENT_BINARY_DIR}/ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) +) ################################################## # Generate the build config header -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include/bout/build_defines.hxx") +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include/bout/build_defines.hxx") # If we do in source builds, this is fine - if (NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) - message(FATAL_ERROR "Generated build_defines.hxx header already exists; please remove '${CMAKE_CURRENT_SOURCE_DIR}/include/bout/build_defines.hxx' before continuing") + if(NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + message( + FATAL_ERROR + "Generated build_defines.hxx header already exists; please remove '${CMAKE_CURRENT_SOURCE_DIR}/include/bout/build_defines.hxx' before continuing" + ) endif() endif() configure_file(cmake_build_defines.hxx.in include/bout/build_defines.hxx) - ################################################## # Generate the bout-config script @@ -777,9 +931,11 @@ set(BOUT_HAS_PNETCDF OFF) # For shared libraries we only need to know how to link against BOUT++, # while for static builds we need the dependencies too -if (BUILD_SHARED_LIBS) +if(BUILD_SHARED_LIBS) # Include rpath linker flag so user doesn't need to set LD_LIBRARY_PATH - set(CONFIG_LDFLAGS "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}\$BOUT_LIB_PATH -L\$BOUT_LIB_PATH -lbout++ -lfmt ${CONFIG_LDFLAGS_SHARED}") + set(CONFIG_LDFLAGS + "${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG}\$BOUT_LIB_PATH -L\$BOUT_LIB_PATH -lbout++ -lfmt ${CONFIG_LDFLAGS_SHARED}" + ) else() set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS}") endif() @@ -788,9 +944,9 @@ set(ISINSTALLED "FALSE") set(_CONFIG_LDFLAGS) string(REPLACE " " ";" CONFIG_LDFLAGS_LIST ${CONFIG_LDFLAGS}) -foreach (flag ${CONFIG_LDFLAGS_LIST}) +foreach(flag ${CONFIG_LDFLAGS_LIST}) string(REGEX MATCH "^-.*$" isopt "${flag}") - if (isopt) + if(isopt) # message("${flag} is an option") set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} ${flag}") # All good @@ -800,70 +956,93 @@ foreach (flag ${CONFIG_LDFLAGS_LIST}) set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} ${flag}") else() string(FIND "${flag}" "::" hascolcol) - if (${hascolcol} EQUAL -1) - message("Fixing ${flag} to -l${flag}") - set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag}") + if(${hascolcol} EQUAL -1) + message("Fixing ${flag} to -l${flag}") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag}") else() - string(REGEX MATCH "[^:]*$" flag2 "${flag}") - message("Fixing ${flag} to -l${flag2}") - set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag2}") + string(REGEX MATCH "[^:]*$" flag2 "${flag}") + message("Fixing ${flag} to -l${flag2}") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag2}") endif() endif() endif() endforeach() -set( CONFIG_LDFLAGS ${_CONFIG_LDFLAGS}) +set(CONFIG_LDFLAGS ${_CONFIG_LDFLAGS}) # This version of the file allows the build directory to be used directly configure_file(bin/bout-config.in bin/bout-config @ONLY) -configure_file(tools/pylib/boutconfig/__init__.py.cin tools/pylib/boutconfig/__init__.py @ONLY) +configure_file( + tools/pylib/boutconfig/__init__.py.cin tools/pylib/boutconfig/__init__.py + @ONLY +) configure_file(bout++Config.cmake.in bout++Config.cmake @ONLY) # We need to generate a separate version for installation, with the # correct install paths. So first we need to replace the build # directory library path with the installation path -string(REPLACE - "${CMAKE_BINARY_DIR}/lib" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" - CONFIG_LDFLAGS "${CONFIG_LDFLAGS}") +string(REPLACE "${CMAKE_BINARY_DIR}/lib" + "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" CONFIG_LDFLAGS + "${CONFIG_LDFLAGS}" +) set(BOUT_LIB_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") # Update mpark.variant and fmt include paths if we're building them -if (NOT BOUT_USE_SYSTEM_MPARK_VARIANT) - set(MPARK_VARIANT_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") +if(NOT BOUT_USE_SYSTEM_MPARK_VARIANT) + set(MPARK_VARIANT_INCLUDE_PATH + "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}" + ) endif() -if (NOT BOUT_USE_SYSTEM_FMT) +if(NOT BOUT_USE_SYSTEM_FMT) set(FMT_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") endif() +if(NOT BOUT_USE_SYSTEM_CPPTRACE) + set(CPPTRACE_INCLUDE_PATH + "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}" + ) +endif() set(BOUT_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") # We don't need the build include path any more -string(REPLACE "-I${CMAKE_CURRENT_BINARY_DIR}/include" "" CONFIG_CFLAGS "${CONFIG_CFLAGS}") +string(REPLACE "-I${CMAKE_CURRENT_BINARY_DIR}/include" "" CONFIG_CFLAGS + "${CONFIG_CFLAGS}" +) set(PYTHONCONFIGPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_PYTHON_SITEARCH}") set(ISINSTALLED "TRUE") # This version now has the correct paths to use the final installation configure_file(bin/bout-config.in bin/bout-config-install @ONLY) -configure_file(tools/pylib/boutconfig/__init__.py.cin tools/pylib/boutconfig/__init__.py-install @ONLY) +configure_file( + tools/pylib/boutconfig/__init__.py.cin + tools/pylib/boutconfig/__init__.py-install @ONLY +) configure_file(bout++Config.cmake.in bout++Config.cmake-install @ONLY) ################################################## # Installation -install(TARGETS bout++ +install( + TARGETS bout++ EXPORT bout++Targets LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - ) + INCLUDES + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) # Repo files -install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING PATTERN "*.hxx") +install( + DIRECTORY include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING + PATTERN "*.hxx" +) # Generated headers install(DIRECTORY "${PROJECT_BINARY_DIR}/include/" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) # The various helper scripts -install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/" - USE_SOURCE_PERMISSIONS +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/" USE_SOURCE_PERMISSIONS DESTINATION "${CMAKE_INSTALL_BINDIR}" REGEX "bout-squashoutput" EXCLUDE REGEX "bout-config\.in" EXCLUDE @@ -874,69 +1053,71 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/" # it. Note this MUST be done after the installation of bin/, to make # sure we clobber any versions of bout-config hanging around from an # autotools build -install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/bin/bout-config-install" +install( + PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/bin/bout-config-install" DESTINATION "${CMAKE_INSTALL_BINDIR}" RENAME "bout-config" - ) +) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib/boutconfig/__init__.py-install" DESTINATION "${CMAKE_INSTALL_PYTHON_SITEARCH}/boutconfig" RENAME "__init__.py" - ) +) include(CMakePackageConfigHelpers) write_basic_package_version_file( bout++ConfigVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY SameMajorVersion - ) +) -install(EXPORT bout++Targets +install( + EXPORT bout++Targets FILE bout++Targets.cmake NAMESPACE bout++:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bout++" - ) +) # CMake configuration files install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/bout++ConfigVersion.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/BOUT++functions.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CorrectWindowsPaths.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindClangFormat.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindFFTW.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindHYPRE.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindnetCDF.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindnetCDFCxx.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindPackageMultipass.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindLibuuid.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindPETSc.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindScoreP.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindSLEPc.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindSUNDIALS.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindSphinx.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ResolveCompilerPaths.cmake" + FILES "${CMAKE_CURRENT_BINARY_DIR}/bout++ConfigVersion.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/BOUT++functions.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CorrectWindowsPaths.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindClangFormat.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindFFTW.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindHYPRE.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindnetCDF.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindnetCDFCxx.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindPackageMultipass.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindLibuuid.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindPETSc.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindScoreP.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindSLEPc.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindSUNDIALS.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindSphinx.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ResolveCompilerPaths.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bout++" - ) +) install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake-install" + FILES "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake-install" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bout++" RENAME "bout++Config.cmake" - ) +) -export(EXPORT bout++Targets +export( + EXPORT bout++Targets FILE "${CMAKE_CURRENT_BINARY_DIR}/bout++Targets.cmake" NAMESPACE bout++:: - ) +) export(PACKAGE bout) ################################################## # Configure summary -message(" +message( + " -------------------------------- BOUT++ Configuration Summary -------------------------------- @@ -960,7 +1141,6 @@ message(" Output coloring : ${BOUT_USE_COLOR} Field name tracking : ${BOUT_USE_TRACK} Floating point exceptions: ${BOUT_USE_SIGFPE} - Backtrace enabled : ${BOUT_USE_BACKTRACE} RAJA enabled : ${BOUT_HAS_RAJA} Umpire enabled : ${BOUT_HAS_UMPIRE} Caliper enabled : ${BOUT_HAS_CALIPER} @@ -977,4 +1157,5 @@ message(" export PYTHONPATH=${BOUT_PYTHONPATH}:\$PYTHONPATH *** Now run `cmake --build ${CMAKE_BINARY_DIR}` to compile BOUT++ *** -") +" +) diff --git a/LICENSE.MIT b/LICENSE.MIT new file mode 100644 index 0000000000..14e2e075df --- /dev/null +++ b/LICENSE.MIT @@ -0,0 +1,19 @@ +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index c2e035e924..84062638fa 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://github.com/boutproject/BOUT-dev/actions/workflows/tests.yml/badge.svg?branch=next)](https://github.com/boutproject/BOUT-dev/actions) [![License](https://img.shields.io/badge/license-LGPL-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0.en.html) [![py3comp](https://img.shields.io/badge/py3-compatible-brightgreen.svg)](https://img.shields.io/badge/py3-compatible-brightgreen.svg) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13753882.svg)](https://doi.org/10.5281/zenodo.8369888) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17313945.svg)](https://doi.org/10.5281/zenodo.17313945) ``` .______ ______ __ __ .___________. @@ -62,7 +62,7 @@ Homepage found at [http://boutproject.github.io/](http://boutproject.github.io/) BOUT++ needs the following: -* A C++17 compiler +* A C++20 compiler * MPI * NetCDF @@ -113,7 +113,7 @@ You can convert the CITATION.cff file into a Bibtex file as follows: See [CONTRIBUTING.md](CONTRIBUTING.md) and the [manual page](https://bout-dev.readthedocs.io/en/stable/developer_docs/contributing.html) ## License -Copyright 2010-2024 BOUT++ contributors +Copyright 2010-2026 BOUT++ contributors BOUT++ is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff --git a/bin/bout-add-mod-path b/bin/bout-add-mod-path index 9faf1be3de..ee7ea66d25 100755 --- a/bin/bout-add-mod-path +++ b/bin/bout-add-mod-path @@ -104,8 +104,7 @@ def create_mod(modulepath, name, top, build): else: prereq = "" with open(filename, "w") as f: - f.write( - f"""#%Module 1.0 + f.write(f"""#%Module 1.0 # # BOUT++ module for use with 'environment-modules' package # Created by bout-add-mod-path v0.9 @@ -119,17 +118,14 @@ setenv BOUT_TOP {top} prepend-path PATH {top}/bin prepend-path PYTHONPATH {top}/tools/pylib prepend-path IDL_PATH +{top}/tools/idllib:'' -""" - ) +""") if build != top: - f.write( - f"""#%Module 1.0 + f.write(f"""#%Module 1.0 setenv BOUT_BUILD {build} prepend-path PATH {build}/bin prepend-path LD_LIBRARY_PATH {build}/lib prepend-path PYTHONPATH {build}/tools/pylib -""" - ) +""") print(f"created `{filename}`") diff --git a/bin/bout-changelog-generator.py b/bin/bout-changelog-generator.py index cfb9a30bb0..d5ad11892e 100755 --- a/bin/bout-changelog-generator.py +++ b/bin/bout-changelog-generator.py @@ -1,4 +1,10 @@ #! /usr/bin/env python3 +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "pygithub", +# ] +# /// import argparse import os diff --git a/bin/bout-pylib-cmd-to-bin b/bin/bout-pylib-cmd-to-bin index 8f88a5dbf4..8d6dbed7ae 100755 --- a/bin/bout-pylib-cmd-to-bin +++ b/bin/bout-pylib-cmd-to-bin @@ -126,8 +126,7 @@ def createwrapper(mod, func_name, func, name): out += end f.write(out) - fprint( - """#!/usr/bin/env python3 + fprint("""#!/usr/bin/env python3 # PYTHON_ARGCOMPLETE_OK import argparse @@ -136,8 +135,7 @@ try: except ImportError: argcomplete=None -""" - ) +""") doc = True para = False ret = False @@ -183,19 +181,16 @@ except ImportError: arg_help[curarg].append(esc(blas)) # Print functions that are needed if "str_to_slice" in arg_type.values(): - fprint( - """ + fprint(""" def str_to_slice(sstr): args=[] for s in sstr.split(','): args.append(int(s)) print(args) return slice(*args) -""" - ) +""") if "str_to_bool" in arg_type.values(): - fprint( - """ + fprint(""" def str_to_bool(sstr): low=sstr.lower() # no or false @@ -206,8 +201,7 @@ def str_to_bool(sstr): return True else: raise ArgumentTypeError("Cannot parse %s to bool type"%sstr) -""" - ) +""") # Create the parser fprint("parser = argparse.ArgumentParser(%s)" % (esc(docs))) spec = inspect.signature(func) @@ -247,24 +241,19 @@ def str_to_bool(sstr): pre = "\n " fprint(")") - fprint( - """ + fprint(""" if argcomplete: argcomplete.autocomplete(parser) -# late import for faster auto-complete""" - ) +# late import for faster auto-complete""") fprint("from %s import %s" % (mod, func_name)) - fprint( - """ + fprint(""" args = parser.parse_args() # Call the function %s, using command line arguments %s(**args.__dict__) -""" - % (func_name, func_name) - ) +""" % (func_name, func_name)) # alternative, but I think 0o755 is easier to read # import stat # os.chmod(filename,stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) diff --git a/bin/bout-v5-factory-upgrader.py b/bin/bout-v5-factory-upgrader.py index 29fc07db30..ee24572a94 100755 --- a/bin/bout-v5-factory-upgrader.py +++ b/bin/bout-v5-factory-upgrader.py @@ -5,7 +5,6 @@ import difflib import re - # Dictionary of factory methods that may need updating factories = { "Interpolation": { @@ -62,9 +61,7 @@ def find_factory_calls(factory, source): \s*=\s* {factory_name}:: .*{create_method}.* - """.format( - **factory - ), + """.format(**factory), source, re.VERBOSE, ) @@ -75,9 +72,7 @@ def find_type_pointers(factory, source): r""" \b{type_name}\s*\*\s* # Type name and pointer ([\w_]+)\s*; # Variable name - """.format( - **factory - ), + """.format(**factory), source, re.VERBOSE, ) @@ -107,9 +102,7 @@ def fix_declarations(factory, variables, source): (.*?)(class\s*)? # optional "class" keyword \b({type_name})\s*\*\s* # Type-pointer ({variable_name})\s*; # Variable - """.format( - type_name=factory["type_name"], variable_name=variable - ), + """.format(type_name=factory["type_name"], variable_name=variable), r"\1std::unique_ptr<\3> \4{nullptr};", source, flags=re.VERBOSE, @@ -123,9 +116,7 @@ def fix_declarations(factory, variables, source): ({variable_name})\s* # Variable =\s* # Assignment from factory ({factory_name}::.*{create_method}.*); - """.format( - variable_name=variable, **factory - ), + """.format(variable_name=variable, **factory), r"\1auto \4 = \5;", source, flags=re.VERBOSE, @@ -139,9 +130,7 @@ def fix_declarations(factory, variables, source): ({variable_name})\s* # Variable =\s* # Assignment (0|nullptr|NULL); - """.format( - variable_name=variable, **factory - ), + """.format(variable_name=variable, **factory), r"\1std::unique_ptr<\2> \3{nullptr};", source, flags=re.VERBOSE, diff --git a/bin/bout-v5-format-upgrader.py b/bin/bout-v5-format-upgrader.py index 7c7d13ac7f..a534ca240a 100755 --- a/bin/bout-v5-format-upgrader.py +++ b/bin/bout-v5-format-upgrader.py @@ -5,7 +5,6 @@ import difflib import re - format_replacements = { "c": "c", "d": "d", diff --git a/bin/bout-v5-header-upgrader.py b/bin/bout-v5-header-upgrader.py index 49a8fbcbe4..77794ab920 100755 --- a/bin/bout-v5-header-upgrader.py +++ b/bin/bout-v5-header-upgrader.py @@ -9,7 +9,6 @@ from typing import List from subprocess import run - header_shim_sentinel = "// BOUT++ header shim" header_warning = f"""\ @@ -122,8 +121,7 @@ def create_patch(filename, original, modified): if __name__ == "__main__": parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description=textwrap.dedent( - """\ + description=textwrap.dedent("""\ Fix deprecated header locations for BOUT++ v4 -> v5 All BOUT++ headers are now under ``include/bout`` and @@ -142,8 +140,7 @@ def create_patch(filename, original, modified): If you have staged changes, this tool will not work, so to avoid committing undesired or unrelated changes. - """ - ), + """), ) parser.add_argument( diff --git a/bin/bout-v5-input-file-upgrader.py b/bin/bout-v5-input-file-upgrader.py index e2940ff58a..ea979005d5 100755 --- a/bin/bout-v5-input-file-upgrader.py +++ b/bin/bout-v5-input-file-upgrader.py @@ -271,8 +271,7 @@ def possibly_apply_patch(patch, options_file, quiet=False, force=False): if __name__ == "__main__": parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description=textwrap.dedent( - """\ + description=textwrap.dedent("""\ Fix input files for BOUT++ v5+ Please note that this will only fix input options in sections with @@ -300,8 +299,7 @@ def possibly_apply_patch(patch, options_file, quiet=False, force=False): Files that change in this way will have the "canonicalisation" patch presented first. If you choose not to apply this patch, the "upgrade - fixer" patch will still include it.""" - ), + fixer" patch will still include it."""), ) parser.add_argument("files", action="store", nargs="+", help="Input files") diff --git a/bin/bout-v5-macro-upgrader.py b/bin/bout-v5-macro-upgrader.py index 11b4926255..d644fed9e8 100755 --- a/bin/bout-v5-macro-upgrader.py +++ b/bin/bout-v5-macro-upgrader.py @@ -342,8 +342,7 @@ def create_patch(filename, original, modified): if __name__ == "__main__": parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description=textwrap.dedent( - """\ + description=textwrap.dedent("""\ Fix macro defines for BOUT++ v4 -> v5 Please note that this is only slightly better than dumb text replacement. It @@ -359,8 +358,7 @@ def create_patch(filename, original, modified): still replace them in strings or comments. Please check the diff output carefully! - """ - ), + """), ) parser.add_argument("files", action="store", nargs="+", help="Input files") diff --git a/bin/bout-v5-physics-model-upgrader.py b/bin/bout-v5-physics-model-upgrader.py index 26fb8ef6e0..260d1d59ee 100755 --- a/bin/bout-v5-physics-model-upgrader.py +++ b/bin/bout-v5-physics-model-upgrader.py @@ -8,7 +8,6 @@ import textwrap import warnings - PHYSICS_MODEL_INCLUDE = '#include "bout/physicsmodel.hxx"' PHYSICS_MODEL_SKELETON = """ @@ -213,13 +212,11 @@ def fix_bout_constrain(source, error_on_warning): "\n ".join(["{}:{}".format(i, source_lines[i]) for i in line_range]) ) - message = textwrap.dedent( - """\ + message = textwrap.dedent("""\ Some uses of `bout_constrain` remain, but we could not automatically convert them to use `Solver::constraint`. Please fix them before continuing: - """ - ) + """) message += " " + "\n ".join(lines_context) if error_on_warning: @@ -389,8 +386,7 @@ def create_patch(filename, original, modified): if __name__ == "__main__": parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description=textwrap.dedent( - """\ + description=textwrap.dedent("""\ Upgrade legacy physics models to use the PhysicsModel class This will do the bare minimum required to compile, and @@ -403,8 +399,7 @@ def create_patch(filename, original, modified): By default, this will use the file name stripped of file extensions as the name of the new class. Use '--name=' to give a different name. - """ - ), + """), ) parser.add_argument("files", action="store", nargs="+", help="Files to fix") diff --git a/bin/bout-v5-xzinterpolation-upgrader.py b/bin/bout-v5-xzinterpolation-upgrader.py index 37c79e0de8..e70c3c54ae 100755 --- a/bin/bout-v5-xzinterpolation-upgrader.py +++ b/bin/bout-v5-xzinterpolation-upgrader.py @@ -54,9 +54,7 @@ def fix_header_includes(old_header, new_header, source): (<|") ({header}) # Header name (>|") - """.format( - header=old_header - ), + """.format(header=old_header), r"\1\2{header}\4".format(header=new_header), source, flags=re.VERBOSE, @@ -67,9 +65,7 @@ def fix_interpolations(old_interpolation, new_interpolation, source): return re.sub( r""" \b{}\b - """.format( - old_interpolation - ), + """.format(old_interpolation), r"{}".format(new_interpolation), source, flags=re.VERBOSE, @@ -120,9 +116,7 @@ def fix_factories(old_factory, new_factory, source): return re.sub( r""" \b{}\b - """.format( - old_factory - ), + """.format(old_factory), r"{}".format(new_factory), source, flags=re.VERBOSE, diff --git a/bin/update_citations.py b/bin/update_citations.py index c7771a3611..63f597f588 100755 --- a/bin/update_citations.py +++ b/bin/update_citations.py @@ -1,4 +1,11 @@ #!/usr/bin/env python3 +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "ruamel-yaml", +# "unidecode", +# ] +# /// import argparse import subprocess from collections import defaultdict @@ -242,6 +249,9 @@ def update_citations(): new_authors = [] for author in unrecognised_authors: + if " " not in author: + # This is just a GitHub handle, skip + continue first_name, last_name = author.rsplit(maxsplit=1) new_authors.append({"family-names": last_name, "given-names": first_name}) diff --git a/bin/update_version_number_in_files.py b/bin/update_version_number_in_files.py index 85df930aea..3e9758a8c1 100755 --- a/bin/update_version_number_in_files.py +++ b/bin/update_version_number_in_files.py @@ -66,11 +66,6 @@ def update_version_number_in_file(relative_filepath, pattern, new_version_number def bump_version_numbers( new_version_number: VersionNumber, next_version_number: VersionNumber ): - update_version_number_in_file( - "configure.ac", - r"^AC_INIT\(\[BOUT\+\+\],\[(\d+\.\d+\.\d+)\]", - new_version_number, - ) update_version_number_in_file( "CITATION.cff", r"^version: (\d+\.\d+\.\d+)", new_version_number ) @@ -163,8 +158,7 @@ def create_patch(filename, original, modified): if __name__ == "__main__": parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description=textwrap.dedent( - """\ + description=textwrap.dedent("""\ Update the software version number to the specified version, to be given in the form major.minor.patch, e.g. 5.10.3 @@ -177,8 +171,7 @@ def create_patch(filename, original, modified): the 'minor' version number of the provided version will be incremented by 1, e.g. 5.10.3 -> 5.11.3 - """ - ), + """), ) parser.add_argument( diff --git a/bout++Config.cmake.in b/bout++Config.cmake.in index d461e58e4b..5cc68aefde 100644 --- a/bout++Config.cmake.in +++ b/bout++Config.cmake.in @@ -6,10 +6,9 @@ set(BOUT_USE_SIGNAL @BOUT_USE_SIGNAL@) set(BOUT_USE_COLOR @BOUT_USE_COLOR@) set(BOUT_USE_TRACK @BOUT_USE_TRACK@) set(BOUT_USE_SIGFPE @BOUT_USE_SIGFPE@) -set(BOUT_USE_BACKTRACE @BOUT_USE_BACKTRACE@) set(BOUT_USE_OPENMP @BOUT_USE_OPENMP@) set(BOUT_HAS_CUDA @BOUT_HAS_CUDA@) -set(BOUT_HAS_OUTPUT_DEBUG @BOUT_HAS_OUTPUT_DEBUG@) +set(BOUT_USE_OUTPUT_DEBUG @BOUT_USE_OUTPUT_DEBUG@) set(BOUT_CHECK_LEVEL @BOUT_CHECK_LEVEL@) set(BOUT_USE_METRIC_3D @BOUT_USE_METRIC_3D@) @@ -109,6 +108,14 @@ elseif(EXISTS "@ADIOS2_BINARY_DIR@") # If we downloaded ADIOS2, then we need to add its build directory to our search paths list(APPEND CMAKE_PREFIX_PATH "@ADIOS2_BINARY_DIR@") endif() +if(EXISTS "@cpptrace_ROOT@") + set(cpptrace_ROOT "@cpptrace_ROOT@") +elseif(EXISTS "@cpptrace_BINARY_DIR@") + list(APPEND CMAKE_PREFIX_PATH "@cpptrace_BINARY_DIR@") + list(APPEND CMAKE_PREFIX_PATH "@cpptrace_BINARY_DIR@/cmake") + list(APPEND CMAKE_PREFIX_PATH "@libdwarf_BINARY_DIR@/src/lib/libdwarf") + list(APPEND CMAKE_PREFIX_PATH "@zstd_BINARY_DIR@") +endif() if(@BOUT_USE_SYSTEM_MPARK_VARIANT@) set(mpark_variant_ROOT "@mpark_variant_ROOT@") @@ -160,6 +167,7 @@ if (BOUT_HAS_GETTEXT) endif() find_dependency(mpark_variant @mpark_variant_VERSION@) find_dependency(fmt @fmt_VERSION@) +find_dependency(cpptrace @cpptrace_VERSION@) if (BOUT_HAS_SLEPC) find_dependency(SLEPc @SLEPC_VERSION@) endif() @@ -174,3 +182,30 @@ if (BOUT_HAS_ADIOS2) endif() include("${CMAKE_CURRENT_LIST_DIR}/bout++Targets.cmake") + +add_library(bout++ INTERFACE IMPORTED) +set_target_properties(bout++ + PROPERTIES BOUT_USE_SIGNAL @BOUT_USE_SIGNAL@ + BOUT_USE_COLOR @BOUT_USE_COLOR@ + BOUT_USE_TRACK @BOUT_USE_TRACK@ + BOUT_USE_SIGFPE @BOUT_USE_SIGFPE@ + BOUT_USE_OPENMP @BOUT_USE_OPENMP@ + BOUT_HAS_CUDA @BOUT_HAS_CUDA@ + BOUT_USE_OUTPUT_DEBUG @BOUT_USE_OUTPUT_DEBUG@ + BOUT_CHECK_LEVEL @BOUT_CHECK_LEVEL@ + BOUT_USE_METRIC_3D @BOUT_USE_METRIC_3D@ + BOUT_HAS_PVODE @BOUT_HAS_PVODE@ + BOUT_HAS_NETCDF @BOUT_HAS_NETCDF@ + BOUT_HAS_ADIOS2 @BOUT_HAS_ADIOS2@ + BOUT_HAS_FFTW @BOUT_HAS_FFTW@ + BOUT_HAS_LAPACK @BOUT_HAS_LAPACK@ + BOUT_HAS_PETSC @BOUT_HAS_PETSC@ + BOUT_HAS_SLEPC @BOUT_HAS_SLEPC@ + BOUT_HAS_SCOREP @BOUT_HAS_SCOREP@ + BOUT_USE_UUID_SYSTEM_GENERATOR @BOUT_USE_UUID_SYSTEM_GENERATOR@ + BOUT_HAS_SUNDIALS @BOUT_HAS_SUNDIALS@ + BOUT_HAS_HYPRE @BOUT_HAS_HYPRE@ + BOUT_HAS_GETTEXT @BOUT_HAS_GETTEXT@ + BOUT_HAS_UMPIRE @BOUT_HAS_UMPIRE@ + BOUT_HAS_RAJA @BOUT_HAS_RAJA@ +) diff --git a/build-aux/config.guess b/build-aux/config.guess deleted file mode 100755 index c6fad2f5e5..0000000000 --- a/build-aux/config.guess +++ /dev/null @@ -1,1568 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-06-10' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD -# -# Please send patches with a ChangeLog entry to config-patches@gnu.org. - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - ;; -esac - -case "${UNAME_MACHINE}" in - i?86) - test -z "$VENDOR" && VENDOR=pc - ;; - *) - test -z "$VENDOR" && VENDOR=unknown - ;; -esac -test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-${VENDOR}-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-${VENDOR}-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-${VENDOR}-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-${VENDOR}-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-${VENDOR}-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-${VENDOR}-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-${VENDOR}-osf1mk - else - echo ${UNAME_MACHINE}-${VENDOR}-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-${VENDOR}-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-${VENDOR}-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-${VENDOR}-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-${VENDOR}-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-${VENDOR}-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-${VENDOR}-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-${VENDOR}-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-${VENDOR}-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-${LIBC}"; exit; } - ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-${VENDOR}-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-${VENDOR}-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-${VENDOR}-linux-${LIBC} ;; - PA8*) echo hppa2.0-${VENDOR}-linux-${LIBC} ;; - *) echo hppa-${VENDOR}-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-${VENDOR}-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-${VENDOR}-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-${VENDOR}-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-${VENDOR}-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-${VENDOR}-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-${VENODR}-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-${VENDOR}-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-${VENODR}-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-${VENDOR}-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-${VENDOR}-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-${VENDOR}-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-${VENDOR}-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-${VENDOR}-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-${VENDOR}-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-${VENDOR}-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-esx - exit ;; -esac - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build-aux/config.rpath b/build-aux/config.rpath deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build-aux/config.sub b/build-aux/config.sub deleted file mode 100755 index 8b612ab89d..0000000000 --- a/build-aux/config.sub +++ /dev/null @@ -1,1788 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-04-24' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches with a ChangeLog entry to config-patches@gnu.org. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i386-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or1k-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build-aux/install-sh b/build-aux/install-sh deleted file mode 100755 index 377bb8687f..0000000000 --- a/build-aux/install-sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2011-11-20.07; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh deleted file mode 100644 index 63ae69dc6f..0000000000 --- a/build-aux/ltmain.sh +++ /dev/null @@ -1,9655 +0,0 @@ - -# libtool (GNU libtool) 2.4.2 -# Written by Gordon Matzigkeit , 1996 - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory -# -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. -# -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: -# -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 -# automake: $automake_version -# autoconf: $autoconf_version -# -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . - -PROGRAM=libtool -PACKAGE=libtool -VERSION=2.4.2 -TIMESTAMP="" -package_revision=1.3337 - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" - fi" -done -LC_ALL=C -LANGUAGE=C -export LANGUAGE LC_ALL - -$lt_unset CDPATH - - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" - - - -: ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -exit_status=$EXIT_SUCCESS - -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" - -dirname="s,/[^/]*$,," -basename="s,^.*/,," - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation - - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation - - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation - - -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' - -# func_normal_abspath PATH -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -# value returned in "$func_normal_abspath_result" -func_normal_abspath () -{ - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi - - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi -} - -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result - -# Make sure we have an absolute path for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=$func_dirname_result - progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" - ;; - *) - save_IFS="$IFS" - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS="$save_IFS" - test -x "$progdir/$progname" && break - done - IFS="$save_IFS" - test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' - -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" - -# Standard options: -opt_dry_run=false -opt_help=false -opt_quiet=false -opt_verbose=false -opt_warning=: - -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} - -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} - -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 - - # bash bug again: - : -} - -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" -} -help="Try \`$progname --help' for more information." ## default - - -# func_grep expression filename -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_mkdir_p directory-path -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - my_directory_path="$1" - my_dir_list= - - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" - - # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` - done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` - - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : - done - IFS="$save_mkdir_p_IFS" - - # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" - fi -} - - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$opt_dry_run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" - fi - - $ECHO "$my_tmpdir" -} - - -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. -func_quote_for_eval () -{ - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; - *) - func_quote_for_eval_unquoted_result="$1" ;; - esac - - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" - ;; - *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" - esac -} - - -# func_quote_for_expand arg -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - case $1 in - *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; - *) - my_arg="$1" ;; - esac - - case $my_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" - ;; - esac - - func_quote_for_expand_result="$my_arg" -} - - -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - - -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - -# func_tr_sh -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_version -# Echo version message to standard output and exit. -func_version () -{ - $opt_debug - - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? -} - -# func_usage -# Echo short help message to standard output and exit. -func_usage () -{ - $opt_debug - - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? -} - -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. -func_help () -{ - $opt_debug - - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi -} - -# func_missing_arg argname -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $opt_debug - - func_error "missing argument for $1." - exit_cmd=exit -} - - -# func_split_short_opt shortopt -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () -{ - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' - - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation - - -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () -{ - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' - - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation - -exit_cmd=: - - - - - -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" - -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation - -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () -{ - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation - - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation - - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation - - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation - - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation - - -# func_fatal_configuration arg... -# Echo program name prefixed message to standard error, followed by -# a configuration failure hint, and exit. -func_fatal_configuration () -{ - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." -} - - -# func_config -# Display the configuration for all the tags in this script. -func_config () -{ - re_begincf='^# ### BEGIN LIBTOOL' - re_endcf='^# ### END LIBTOOL' - - # Default configuration. - $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" - - # Now print the configurations for the tags. - for tagname in $taglist; do - $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" - done - - exit $? -} - -# func_features -# Display the features supported by this script. -func_features () -{ - echo "host: $host" - if test "$build_libtool_libs" = yes; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - - exit $? -} - -# func_enable_tag tagname -# Verify that TAGNAME is valid, and either flag an error and exit, or -# enable the TAGNAME tag. We also add TAGNAME to the global $taglist -# variable here. -func_enable_tag () -{ - # Global variable: - tagname="$1" - - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac - - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; - *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac -} - -# func_check_version_match -# Ensure that we are using m4 macros, and libtool script from the same -# release of libtool. -func_check_version_match () -{ - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from an older release. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - fi - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, -$progname: but the definition of this LT_INIT comes from revision $macro_revision. -$progname: You should recreate aclocal.m4 with macros from revision $package_revision -$progname: of $PACKAGE $VERSION and run autoconf again. -_LT_EOF - fi - - exit $EXIT_MISMATCH - fi -} - - -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - - - -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false - - -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. -{ - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; - - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; - - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; - esac - done - - # Validate options: - - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi - - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" - - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" - fi - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } - - - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE -} - - - - -## ----------- ## -## Main. ## -## ----------- ## - -# func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_lalib_p () -{ - test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - -# func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function implements the same check as func_lalib_p without -# resorting to external programs. To this end, it redirects stdin and -# closes it afterwards, without saving the original file descriptor. -# As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. -func_lalib_unsafe_p () -{ - lalib_p=no - if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then - for lalib_p_l in 1 2 3 4 - do - read lalib_p_line - case "$lalib_p_line" in - \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; - esac - done - exec 0<&5 5<&- - fi - test "$lalib_p" = yes -} - -# func_ltwrapper_script_p file -# True iff FILE is a libtool wrapper script -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_script_p () -{ - func_lalib_p "$1" -} - -# func_ltwrapper_executable_p file -# True iff FILE is a libtool wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_executable_p () -{ - func_ltwrapper_exec_suffix= - case $1 in - *.exe) ;; - *) func_ltwrapper_exec_suffix=.exe ;; - esac - $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 -} - -# func_ltwrapper_scriptname file -# Assumes file is an ltwrapper_executable -# uses $file to determine the appropriate filename for a -# temporary ltwrapper_script. -func_ltwrapper_scriptname () -{ - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" -} - -# func_ltwrapper_p file -# True iff FILE is a libtool wrapper script or wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_p () -{ - func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" -} - - -# func_execute_cmds commands fail_cmd -# Execute tilde-delimited COMMANDS. -# If FAIL_CMD is given, eval that upon failure. -# FAIL_CMD may read-access the current command in variable CMD! -func_execute_cmds () -{ - $opt_debug - save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$save_ifs - eval cmd=\"$cmd\" - func_show_eval "$cmd" "${2-:}" - done - IFS=$save_ifs -} - - -# func_source file -# Source FILE, adding directory component if necessary. -# Note that it is not necessary on cygwin/mingw to append a dot to -# FILE even if both FILE and FILE.exe exist: automatic-append-.exe -# behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. -func_source () -{ - $opt_debug - case $1 in - */* | *\\*) . "$1" ;; - *) . "./$1" ;; - esac -} - - -# func_resolve_sysroot PATH -# Replace a leading = in PATH with a sysroot. Store the result into -# func_resolve_sysroot_result -func_resolve_sysroot () -{ - func_resolve_sysroot_result=$1 - case $func_resolve_sysroot_result in - =*) - func_stripname '=' '' "$func_resolve_sysroot_result" - func_resolve_sysroot_result=$lt_sysroot$func_stripname_result - ;; - esac -} - -# func_replace_sysroot PATH -# If PATH begins with the sysroot, replace it with = and -# store the result into func_replace_sysroot_result. -func_replace_sysroot () -{ - case "$lt_sysroot:$1" in - ?*:"$lt_sysroot"*) - func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" - ;; - *) - # Including no sysroot. - func_replace_sysroot_result=$1 - ;; - esac -} - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - $opt_debug - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case "$@ " in - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" -# else -# func_verbose "using $tagname tagged configuration" - fi - ;; - esac - fi -} - - - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () -{ - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' - else - write_lobj=none - fi - - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' - else - write_oldobj=none - fi - - $opt_dry_run || { - cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then - func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` - else - func_convert_core_file_wine_to_w32_result= - fi - fi -} -# end: func_convert_core_file_wine_to_w32 - - -# func_convert_core_path_wine_to_w32 ARG -# Helper function used by path conversion functions when $build is *nix, and -# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly -# configured wine environment available, with the winepath program in $build's -# $PATH. Assumes ARG has no leading or trailing path separator characters. -# -# ARG is path to be converted from $build format to win32. -# Result is available in $func_convert_core_path_wine_to_w32_result. -# Unconvertible file (directory) names in ARG are skipped; if no directory names -# are convertible, then the result may be empty. -func_convert_core_path_wine_to_w32 () -{ - $opt_debug - # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" - if test -n "$1"; then - oldIFS=$IFS - IFS=: - for func_convert_core_path_wine_to_w32_f in $1; do - IFS=$oldIFS - func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then - if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" - else - func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" - fi - fi - done - IFS=$oldIFS - fi -} -# end: func_convert_core_path_wine_to_w32 - - -# func_cygpath ARGS... -# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when -# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) -# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or -# (2), returns the Cygwin file name or path in func_cygpath_result (input -# file name or path is assumed to be in w32 format, as previously converted -# from $build's *nix or MSYS format). In case (3), returns the w32 file name -# or path in func_cygpath_result (input file name or path is assumed to be in -# Cygwin format). Returns an empty string on error. -# -# ARGS are passed to cygpath, with the last one being the file name or path to -# be converted. -# -# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH -# environment variable; do not put it in $PATH. -func_cygpath () -{ - $opt_debug - if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then - func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` - if test "$?" -ne 0; then - # on failure, ensure result is empty - func_cygpath_result= - fi - else - func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" - fi -} -#end: func_cygpath - - -# func_convert_core_msys_to_w32 ARG -# Convert file name or path ARG from MSYS format to w32 format. Return -# result in func_convert_core_msys_to_w32_result. -func_convert_core_msys_to_w32 () -{ - $opt_debug - # awkward: cmd appends spaces to result - func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` -} -#end: func_convert_core_msys_to_w32 - - -# func_convert_file_check ARG1 ARG2 -# Verify that ARG1 (a file name in $build format) was converted to $host -# format in ARG2. Otherwise, emit an error message, but continue (resetting -# func_to_host_file_result to ARG1). -func_convert_file_check () -{ - $opt_debug - if test -z "$2" && test -n "$1" ; then - func_error "Could not determine host file name corresponding to" - func_error " \`$1'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback: - func_to_host_file_result="$1" - fi -} -# end func_convert_file_check - - -# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH -# Verify that FROM_PATH (a path in $build format) was converted to $host -# format in TO_PATH. Otherwise, emit an error message, but continue, resetting -# func_to_host_file_result to a simplistic fallback value (see below). -func_convert_path_check () -{ - $opt_debug - if test -z "$4" && test -n "$3"; then - func_error "Could not determine the host path corresponding to" - func_error " \`$3'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback. This is a deliberately simplistic "conversion" and - # should not be "improved". See libtool.info. - if test "x$1" != "x$2"; then - lt_replace_pathsep_chars="s|$1|$2|g" - func_to_host_path_result=`echo "$3" | - $SED -e "$lt_replace_pathsep_chars"` - else - func_to_host_path_result="$3" - fi - fi -} -# end func_convert_path_check - - -# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG -# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT -# and appending REPL if ORIG matches BACKPAT. -func_convert_path_front_back_pathsep () -{ - $opt_debug - case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" - ;; - esac - case $4 in - $2 ) func_append func_to_host_path_result "$3" - ;; - esac -} -# end func_convert_path_front_back_pathsep - - -################################################## -# $build to $host FILE NAME CONVERSION FUNCTIONS # -################################################## -# invoked via `$to_host_file_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# Result will be available in $func_to_host_file_result. - - -# func_to_host_file ARG -# Converts the file name ARG from $build format to $host format. Return result -# in func_to_host_file_result. -func_to_host_file () -{ - $opt_debug - $to_host_file_cmd "$1" -} -# end func_to_host_file - - -# func_to_tool_file ARG LAZY -# converts the file name ARG from $build format to toolchain format. Return -# result in func_to_tool_file_result. If the conversion in use is listed -# in (the comma separated) LAZY, no conversion takes place. -func_to_tool_file () -{ - $opt_debug - case ,$2, in - *,"$to_tool_file_cmd",*) - func_to_tool_file_result=$1 - ;; - *) - $to_tool_file_cmd "$1" - func_to_tool_file_result=$func_to_host_file_result - ;; - esac -} -# end func_to_tool_file - - -# func_convert_file_noop ARG -# Copy ARG to func_to_host_file_result. -func_convert_file_noop () -{ - func_to_host_file_result="$1" -} -# end func_convert_file_noop - - -# func_convert_file_msys_to_w32 ARG -# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_file_result. -func_convert_file_msys_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_w32 - - -# func_convert_file_cygwin_to_w32 ARG -# Convert file name ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_file_cygwin_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # because $build is cygwin, we call "the" cygpath in $PATH; no need to use - # LT_CYGPATH in this case. - func_to_host_file_result=`cygpath -m "$1"` - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_cygwin_to_w32 - - -# func_convert_file_nix_to_w32 ARG -# Convert file name ARG from *nix to w32 format. Requires a wine environment -# and a working winepath. Returns result in func_to_host_file_result. -func_convert_file_nix_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_w32 - - -# func_convert_file_msys_to_cygwin ARG -# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_file_msys_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_cygwin - - -# func_convert_file_nix_to_cygwin ARG -# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed -# in a wine environment, working winepath, and LT_CYGPATH set. Returns result -# in func_to_host_file_result. -func_convert_file_nix_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. - func_convert_core_file_wine_to_w32 "$1" - func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_cygwin - - -############################################# -# $build to $host PATH CONVERSION FUNCTIONS # -############################################# -# invoked via `$to_host_path_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# The result will be available in $func_to_host_path_result. -# -# Path separators are also converted from $build format to $host format. If -# ARG begins or ends with a path separator character, it is preserved (but -# converted to $host format) on output. -# -# All path conversion functions are named using the following convention: -# file name conversion function : func_convert_file_X_to_Y () -# path conversion function : func_convert_path_X_to_Y () -# where, for any given $build/$host combination the 'X_to_Y' value is the -# same. If conversion functions are added for new $build/$host combinations, -# the two new functions must follow this pattern, or func_init_to_host_path_cmd -# will break. - - -# func_init_to_host_path_cmd -# Ensures that function "pointer" variable $to_host_path_cmd is set to the -# appropriate value, based on the value of $to_host_file_cmd. -to_host_path_cmd= -func_init_to_host_path_cmd () -{ - $opt_debug - if test -z "$to_host_path_cmd"; then - func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" - fi -} - - -# func_to_host_path ARG -# Converts the path ARG from $build format to $host format. Return result -# in func_to_host_path_result. -func_to_host_path () -{ - $opt_debug - func_init_to_host_path_cmd - $to_host_path_cmd "$1" -} -# end func_to_host_path - - -# func_convert_path_noop ARG -# Copy ARG to func_to_host_path_result. -func_convert_path_noop () -{ - func_to_host_path_result="$1" -} -# end func_convert_path_noop - - -# func_convert_path_msys_to_w32 ARG -# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_path_result. -func_convert_path_msys_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from ARG. MSYS - # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; - # and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_msys_to_w32 - - -# func_convert_path_cygwin_to_w32 ARG -# Convert path ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_path_cygwin_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_cygwin_to_w32 - - -# func_convert_path_nix_to_w32 ARG -# Convert path ARG from *nix to w32 format. Requires a wine environment and -# a working winepath. Returns result in func_to_host_file_result. -func_convert_path_nix_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_nix_to_w32 - - -# func_convert_path_msys_to_cygwin ARG -# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_path_msys_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_msys_to_cygwin - - -# func_convert_path_nix_to_cygwin ARG -# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a -# a wine environment, working winepath, and LT_CYGPATH set. Returns result in -# func_to_host_file_result. -func_convert_path_nix_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from - # ARG. msys behavior is inconsistent here, cygpath turns them - # into '.;' and ';.', and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_nix_to_cygwin - - -# func_mode_compile arg... -func_mode_compile () -{ - $opt_debug - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - pie_flag= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" - arg_mode=target - continue - ;; - - -pie | -fpie | -fPIE) - func_append pie_flag " $arg" - continue - ;; - - -shared | -static | -prefer-pic | -prefer-non-pic) - func_append later " $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - func_append_quoted lastarg "$arg" - done - IFS="$save_ifs" - func_stripname ' ' '' "$lastarg" - lastarg=$func_stripname_result - - # Add the arguments to base_compile. - func_append base_compile " $lastarg" - continue - ;; - - *) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - func_append_quoted base_compile "$lastarg" - done # for arg - - case $arg_mode in - arg) - func_fatal_error "you must specify an argument for -Xcompile" - ;; - target) - func_fatal_error "you must specify a target with \`-o'" - ;; - *) - # Get the name of the library object. - test -z "$libobj" && { - func_basename "$srcfile" - libobj="$func_basename_result" - } - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - case $libobj in - *.[cCFSifmso] | \ - *.ada | *.adb | *.ads | *.asm | \ - *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ - *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) - func_xform "$libobj" - libobj=$func_xform_result - ;; - esac - - case $libobj in - *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; - *) - func_fatal_error "cannot determine name of library object from \`$libobj'" - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - continue - ;; - - -static) - build_libtool_libs=no - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ - && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." - func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname - - test -z "$base_compile" && \ - func_fatal_help "you must specify a compilation command" - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2* | cegcc*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $ECHO "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - func_append removelist " $output_obj" - $ECHO "$srcfile" > "$lockfile" - fi - - $opt_dry_run || $RM $removelist - func_append removelist " $lockfile" - trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - - func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 - srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result - - # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - if test "$pic_mode" != no; then - command="$base_compile $qsrcfile $pic_flag" - else - # Don't build PIC code - command="$base_compile $qsrcfile" - fi - - func_mkdir_p "$xdir$objdir" - - if test -z "$output_obj"; then - # Place PIC objects in $objdir - func_append command " -o $lobj" - fi - - func_show_eval_locale "$command" \ - 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - func_show_eval '$MV "$output_obj" "$lobj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - - # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then - suppress_output=' >/dev/null 2>&1' - fi - fi - - # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then - # Don't build PIC code - command="$base_compile $qsrcfile$pie_flag" - else - command="$base_compile $qsrcfile $pic_flag" - fi - if test "$compiler_c_o" = yes; then - func_append command " -o $obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - func_append command "$suppress_output" - func_show_eval_locale "$command" \ - '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - func_show_eval '$MV "$output_obj" "$obj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - fi - - $opt_dry_run || { - func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" - - # Unlock the critical section if it was locked - if test "$need_locks" != no; then - removelist=$lockfile - $RM "$lockfile" - fi - } - - exit $EXIT_SUCCESS -} - -$opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} -} - -func_mode_help () -{ - # We need to display help for each of the modes. - case $opt_mode in - "") - # Generic help is extracted from the usage comments - # at the start of this file. - func_help - ;; - - clean) - $ECHO \ -"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - - compile) - $ECHO \ -"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to build PIC objects only - -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - - execute) - $ECHO \ -"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - - finish) - $ECHO \ -"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - - install) - $ECHO \ -"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The following components of INSTALL-COMMAND are treated specially: - - -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - - link) - $ECHO \ -"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -bindir BINDIR specify path to binaries directory (for systems where - libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -shared only do dynamic linking of libtool libraries - -shrext SUFFIX override the standard shared library file extension - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -weak LIBNAME declare that the target provides the LIBNAME interface - -Wc,FLAG - -Xcompiler FLAG pass linker-specific FLAG directly to the compiler - -Wl,FLAG - -Xlinker FLAG pass linker-specific FLAG directly to the linker - -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - - uninstall) - $ECHO \ -"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - - *) - func_fatal_help "invalid operation mode \`$opt_mode'" - ;; - esac - - echo - $ECHO "Try \`$progname --help' for more information about other modes." -} - -# Now that we've collected a possible --mode arg, show help if necessary -if $opt_help; then - if test "$opt_help" = :; then - func_mode_help - else - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - func_mode_help - done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - echo - func_mode_help - done - } | - sed '1d - /^When reporting/,/^Report/{ - H - d - } - $x - /information about other modes/d - /more detailed .*MODE/d - s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' - fi - exit $? -fi - - -# func_mode_execute arg... -func_mode_execute () -{ - $opt_debug - # The first argument is the command name. - cmd="$nonopt" - test -z "$cmd" && \ - func_fatal_help "you must specify a COMMAND" - - # Handle -dlopen flags immediately. - for file in $opt_dlopen; do - test -f "$file" \ - || func_fatal_help "\`$file' is not a file" - - dir= - case $file in - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" - - # Read the libtool library. - dlname= - library_names= - func_source "$file" - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" - continue - fi - - func_dirname "$file" "" "." - dir="$func_dirname_result" - - if test -f "$dir/$objdir/$dlname"; then - func_append dir "/$objdir" - else - if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - func_dirname "$file" "" "." - dir="$func_dirname_result" - ;; - - *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -* | *.la | *.lo ) ;; - *) - # Do a test to see if this is really a libtool program. - if func_ltwrapper_script_p "$file"; then - func_source "$file" - # Transform arg to wrapped name. - file="$progdir/$program" - elif func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - func_source "$func_ltwrapper_scriptname_result" - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - func_append_quoted args "$file" - done - - if test "X$opt_dry_run" = Xfalse; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} - - -# func_mode_finish arg... -func_mode_finish () -{ - $opt_debug - libs= - libdirs= - admincmds= - - for opt in "$nonopt" ${1+"$@"} - do - if test -d "$opt"; then - func_append libdirs " $opt" - - elif test -f "$opt"; then - if func_lalib_unsafe_p "$opt"; then - func_append libs " $opt" - else - func_warning "\`$opt' is not a valid libtool archive" - fi - - else - func_fatal_error "invalid argument \`$opt'" - fi - done - - if test -n "$libs"; then - if test -n "$lt_sysroot"; then - sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` - sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" - else - sysroot_cmd= - fi - - # Remove sysroot references - if $opt_dry_run; then - for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" - done - else - tmpdir=`func_mktempdir` - for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ - > $tmpdir/tmp-la - mv -f $tmpdir/tmp-la $lib - done - ${RM}r "$tmpdir" - fi - fi - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - func_execute_cmds "$finish_cmds" 'admincmds="$admincmds -'"$cmd"'"' - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || func_append admincmds " - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $ECHO " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - echo - - echo "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" - echo "pages." - ;; - *) - echo "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - echo "----------------------------------------------------------------------" - fi - exit $EXIT_SUCCESS -} - -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} - - -# func_mode_install arg... -func_mode_install () -{ - $opt_debug - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then - # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " - arg=$1 - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" - install_shared_prog=$install_prog - case " $install_prog " in - *[\\\ /]cp\ *) install_cp=: ;; - *) install_cp=false ;; - esac - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - no_mode=: - for arg - do - arg2= - if test -n "$dest"; then - func_append files " $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) - if $install_cp; then :; else - prev=$arg - fi - ;; - -g | -m | -o) - prev=$arg - ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then - arg2=$install_override_mode - no_mode=false - fi - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" - if test -n "$arg2"; then - func_quote_for_eval "$arg2" - fi - func_append install_shared_prog " $func_quote_for_eval_result" - done - - test -z "$install_prog" && \ - func_fatal_help "you must specify an install program" - - test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" - - if test -n "$install_override_mode" && $no_mode; then - if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" - fi - fi - - if test -z "$files"; then - if test -z "$dest"; then - func_fatal_help "no file or destination specified" - else - func_fatal_help "you must specify a destination" - fi - fi - - # Strip any trailing slash from the destination. - func_stripname '' '/' "$dest" - dest=$func_stripname_result - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" - - # Not a directory, so check to see that there is only one file specified. - set dummy $files; shift - test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - func_fatal_help "\`$destdir' must be an absolute directory name" - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - func_append staticlibs " $file" - ;; - - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" - - library_names= - old_library= - relink_command= - func_source "$file" - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) func_append current_libdirs " $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) func_append future_libdirs " $libdir" ;; - esac - fi - - func_dirname "$file" "/" "" - dir="$func_dirname_result" - func_append dir "$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - func_warning "relinking \`$file'" - func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' - fi - - # See the names of the shared library. - set dummy $library_names; shift - if test -n "$1"; then - realname="$1" - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ - 'exit $?' - tstripme="$stripme" - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - case $realname in - *.dll.a) - tstripme="" - ;; - esac - ;; - esac - if test -n "$tstripme" && test -n "$striplib"; then - func_show_eval "$striplib $destdir/$realname" 'exit $?' - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - test "$linkname" != "$realname" \ - && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - func_execute_cmds "$postinstall_cmds" 'exit $?' - fi - - # Install the pseudo-library for information purposes. - func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i - func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' - - # Maybe install the static library, too. - test -n "$old_library" && func_append staticlibs " $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - func_lo2o "$destfile" - staticdest=$func_lo2o_result - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" - ;; - esac - - # Install the libtool object if requested. - test -n "$destfile" && \ - func_show_eval "$install_prog $file $destfile" 'exit $?' - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - func_lo2o "$file" - staticobj=$func_lo2o_result - func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - func_stripname '' '.exe' "$file" - file=$func_stripname_result - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin* | *mingw*) - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - wrapper=$func_ltwrapper_scriptname_result - else - func_stripname '' '.exe' "$file" - wrapper=$func_stripname_result - fi - ;; - *) - wrapper=$file - ;; - esac - if func_ltwrapper_script_p "$wrapper"; then - notinst_deplibs= - relink_command= - - func_source "$wrapper" - - # Check the variables that should have been set. - test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - func_source "$lib" - fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no - fi - done - - relink_command= - func_source "$wrapper" - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - $opt_dry_run || { - if test "$finalize" = yes; then - tmpdir=`func_mktempdir` - func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - - $opt_silent || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" - } - if eval "$relink_command"; then : - else - func_error "error: relink \`$file' with the above command before installing it" - $opt_dry_run || ${RM}r "$tmpdir" - continue - fi - file="$outputname" - else - func_warning "cannot relink \`$file'" - fi - } - else - # Install the binary that we compiled earlier. - file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - func_stripname '' '.exe' "$destfile" - destfile=$func_stripname_result - ;; - esac - ;; - esac - func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' - $opt_dry_run || if test -n "$outputname"; then - ${RM}r "$tmpdir" - fi - ;; - esac - done - - for file in $staticlibs; do - func_basename "$file" - name="$func_basename_result" - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - - func_show_eval "$install_prog \$file \$oldlib" 'exit $?' - - if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $tool_oldlib" 'exit $?' - fi - - # Do each command in the postinstall commands. - func_execute_cmds "$old_postinstall_cmds" 'exit $?' - done - - test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = install && func_mode_install ${1+"$@"} - - -# func_generate_dlsyms outputname originator pic_p -# Extract symbols from dlprefiles and create ${outputname}S.o with -# a dlpreopen symbol table. -func_generate_dlsyms () -{ - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` - my_dlsyms= - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" - else - func_error "not configured to extract global symbols from dlpreopened files" - fi - fi - - if test -n "$my_dlsyms"; then - case $my_dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" - - func_show_eval "$RM $nlist ${nlist}S ${nlist}T" - - # Parse the name list into a source file. - func_verbose "creating $output_objdir/$my_dlsyms" - - $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) -#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" -#endif - -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined(__osf__) -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" - - $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` - for progfile in $progfiles; do - func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" - $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $opt_dry_run || { - eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - if test -n "$export_symbols_regex"; then - $opt_dry_run || { - eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" - $opt_dry_run || { - $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - } - else - $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - } - fi - fi - - for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" - func_basename "$dlprefile" - name="$func_basename_result" - case $host in - *cygwin* | *mingw* | *cegcc* ) - # if an import library, we need to obtain dlname - if func_win32_import_lib_p "$dlprefile"; then - func_tr_sh "$dlprefile" - eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" - if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then - # Use subshell, to avoid clobbering current variable values - dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then - func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" - else - # no lafile. user explicitly requested -dlpreopen . - $sharedlib_from_linklib_cmd "$dlprefile" - dlprefile_dlbasename=$sharedlib_from_linklib_result - fi - fi - $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then - eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' - else - func_warning "Could not compute DLL name from $name" - eval '$ECHO ": $name " >> "$nlist"' - fi - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | - $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" - } - else # not an import lib - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - fi - ;; - *) - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - ;; - esac - done - - $opt_dry_run || { - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $MV "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$my_dlsyms" - fi - - echo >> "$output_objdir/$my_dlsyms" "\ - -/* The mapping between symbol names and symbols. */ -typedef struct { - const char *name; - void *address; -} lt_dlsymlist; -extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; -LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," - - case $need_lib_prefix in - no) - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - *) - eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - esac - echo >> "$output_objdir/$my_dlsyms" "\ - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_${my_prefix}_LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - } # !$opt_dry_run - - pic_flag_for_symtable= - case "$compile_command " in - *" -static "*) ;; - *) - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; - *-*-hpux*) - pic_flag_for_symtable=" $pic_flag" ;; - *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi - ;; - esac - ;; - esac - symtab_cflags= - for arg in $LTCFLAGS; do - case $arg in - -pie | -fpie | -fPIE) ;; - *) func_append symtab_cflags " $arg" ;; - esac - done - - # Now compile the dynamic symbol file. - func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' - - # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' - - # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" - case $host in - *cygwin* | *mingw* | *cegcc* ) - if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - else - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - fi - ;; - *) - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - ;; - esac - ;; - *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` - fi -} - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -# Despite the name, also deal with 64 bit binaries. -func_win32_libid () -{ - $opt_debug - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' - 1,100{ - / I /{ - s,.*,import, - p - q - } - }'` - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $ECHO "$win32_libid_type" -} - -# func_cygming_dll_for_implib ARG -# -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib () -{ - $opt_debug - sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` -} - -# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs -# -# The is the core of a fallback implementation of a -# platform-specific function to extract the name of the -# DLL associated with the specified import library LIBNAME. -# -# SECTION_NAME is either .idata$6 or .idata$7, depending -# on the platform and compiler that created the implib. -# -# Echos the name of the DLL associated with the -# specified import library. -func_cygming_dll_for_implib_fallback_core () -{ - $opt_debug - match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` - $OBJDUMP -s --section "$1" "$2" 2>/dev/null | - $SED '/^Contents of section '"$match_literal"':/{ - # Place marker at beginning of archive member dllname section - s/.*/====MARK====/ - p - d - } - # These lines can sometimes be longer than 43 characters, but - # are always uninteresting - /:[ ]*file format pe[i]\{,1\}-/d - /^In archive [^:]*:/d - # Ensure marker is printed - /^====MARK====/p - # Remove all lines with less than 43 characters - /^.\{43\}/!d - # From remaining lines, remove first 43 characters - s/^.\{43\}//' | - $SED -n ' - # Join marker and all lines until next marker into a single line - /^====MARK====/ b para - H - $ b para - b - :para - x - s/\n//g - # Remove the marker - s/^====MARK====// - # Remove trailing dots and whitespace - s/[\. \t]*$// - # Print - /./p' | - # we now have a list, one entry per line, of the stringified - # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is - # a '.' (that is, objdump's representation of an unprintable - # character.) This should work for all archives with less than - # 0x302f exports -- but will fail for DLLs whose name actually - # begins with a literal '.' or a single character followed by - # a '.'. - # - # Of those that remain, print the first one. - $SED -e '/^\./d;/^.\./d;q' -} - -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - -# func_cygming_dll_for_implib_fallback ARG -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# -# This fallback implementation is for use when $DLLTOOL -# does not support the --identify-strict option. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib_fallback () -{ - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then - # binutils import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then - # ms-generated import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` - else - # unknown - sharedlib_from_linklib_result="" - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then - lockfile=$f_ex_an_ar_oldlib.lock - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - fi - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ - 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then - $opt_dry_run || rm -f "$lockfile" - fi - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" - fi -} - - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - $opt_debug - my_gentop="$1"; shift - my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - func_basename "$my_xlib" - my_xlib="$func_basename_result" - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - func_arith $extracted_serial + 1 - extracted_serial=$func_arith_result - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" - - func_mkdir_p "$my_xdir" - - case $host in - *-darwin*) - func_verbose "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - $opt_dry_run || { - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` - darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` - if test -n "$darwin_arches"; then - darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" - cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" - done # $darwin_arches - ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` - $LIPO -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - $RM -rf unfat-$$ - cd "$darwin_orig_dir" - else - cd $darwin_orig_dir - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - } # !$opt_dry_run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` - done - - func_extract_archives_result="$my_oldobjs" -} - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=${1-no} - - $ECHO "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variables: - generated_by_libtool_version='$macro_version' - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$ECHO are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` - $ECHO "\ - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - ECHO=\"$qECHO\" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on -# windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's $0 value, followed by "$@". -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=\$0 - shift - for lt_opt - do - case \"\$lt_opt\" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` - test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. - lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` - cat \"\$lt_dump_D/\$lt_dump_F\" - exit 0 - ;; - --lt-*) - \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" - lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from \$@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case \" \$* \" in - *\\ --lt-*) - for lt_wr_arg - do - case \$lt_wr_arg in - --lt-*) ;; - *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; - esac - shift - done ;; - esac - func_exec_program_core \${1+\"\$@\"} -} - - # Parse options - func_parse_lt_options \"\$0\" \${1+\"\$@\"} - - # Find the directory that this script lives in. - thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 - if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then - # special case for '.' - if test \"\$thisdir\" = \".\"; then - thisdir=\`pwd\` - fi - # remove .libs from thisdir - case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; - $objdir ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $ECHO "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $MKDIR \"\$progdir\" - else - $RM \"\$progdir/\$file\" - fi" - - $ECHO "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $ECHO \"\$relink_command_output\" >&2 - $RM \"\$progdir/\$file\" - exit 1 - fi - fi - - $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $RM \"\$progdir/\$program\"; - $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $RM \"\$progdir/\$file\" - fi" - else - $ECHO "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $ECHO "\ - - if test -f \"\$progdir/\$program\"; then" - - # fixup the dll searchpath if we need to. - # - # Fix the DLL searchpath if we need to. Do this before prepending - # to shlibpath, because on Windows, both are PATH and uninstalled - # libraries must come first. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $ECHO "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` - - export $shlibpath_var -" - fi - - $ECHO "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. - func_exec_program \${1+\"\$@\"} - fi - else - # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 - \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" -} - - -# func_emit_cwrapperexe_src -# emit the source code for a wrapper executable on stdout -# Must ONLY be called from within func_mode_link because -# it depends on a number of variable set therein. -func_emit_cwrapperexe_src () -{ - cat < -#include -#ifdef _MSC_VER -# include -# include -# include -#else -# include -# include -# ifdef __CYGWIN__ -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -/* declarations of non-ANSI functions */ -#if defined(__MINGW32__) -# ifdef __STRICT_ANSI__ -int _putenv (const char *); -# endif -#elif defined(__CYGWIN__) -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif -/* #elif defined (other platforms) ... */ -#endif - -/* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -# define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -#elif defined(__CYGWIN__) -# define HAVE_SETENV -# define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ -#endif - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef S_IXOTH -# define S_IXOTH 0 -#endif -#ifndef S_IXGRP -# define S_IXGRP 0 -#endif - -/* path handling portability macros */ -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -# define HAVE_DOS_BASED_FILE_SYSTEM -# define FOPEN_WB "wb" -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#ifndef FOPEN_WB -# define FOPEN_WB "w" -#endif -#ifndef _O_BINARY -# define _O_BINARY 0 -#endif - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -#if defined(LT_DEBUGWRAPPER) -static int lt_debug = 1; -#else -static int lt_debug = 0; -#endif - -const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ - -void *xmalloc (size_t num); -char *xstrdup (const char *string); -const char *base_name (const char *name); -char *find_executable (const char *wrapper); -char *chase_symlinks (const char *pathspec); -int make_executable (const char *path); -int check_executable (const char *path); -char *strendzap (char *str, const char *pat); -void lt_debugprintf (const char *file, int line, const char *fmt, ...); -void lt_fatal (const char *file, int line, const char *message, ...); -static const char *nonnull (const char *s); -static const char *nonempty (const char *s); -void lt_setenv (const char *name, const char *value); -char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_update_exe_path (const char *name, const char *value); -void lt_update_lib_path (const char *name, const char *value); -char **prepare_spawn (char **argv); -void lt_dump_script (FILE *f); -EOF - - cat <= 0) - && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - return 1; - else - return 0; -} - -int -make_executable (const char *path) -{ - int rval = 0; - struct stat st; - - lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", - nonempty (path)); - if ((!path) || (!*path)) - return 0; - - if (stat (path, &st) >= 0) - { - rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); - } - return rval; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise - Does not chase symlinks, even on platforms that support them. -*/ -char * -find_executable (const char *wrapper) -{ - int has_slash = 0; - const char *p; - const char *p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - int tmp_len; - char *concat_name; - - lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", - nonempty (wrapper)); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char *path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char *q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR (*q)) - break; - p_len = q - p; - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = - XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = - XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - return NULL; -} - -char * -chase_symlinks (const char *pathspec) -{ -#ifndef S_ISLNK - return xstrdup (pathspec); -#else - char buf[LT_PATHMAX]; - struct stat s; - char *tmp_pathspec = xstrdup (pathspec); - char *p; - int has_symlinks = 0; - while (strlen (tmp_pathspec) && !has_symlinks) - { - lt_debugprintf (__FILE__, __LINE__, - "checking path component for symlinks: %s\n", - tmp_pathspec); - if (lstat (tmp_pathspec, &s) == 0) - { - if (S_ISLNK (s.st_mode) != 0) - { - has_symlinks = 1; - break; - } - - /* search backwards for last DIR_SEPARATOR */ - p = tmp_pathspec + strlen (tmp_pathspec) - 1; - while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - p--; - if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - { - /* no more DIR_SEPARATORS left */ - break; - } - *p = '\0'; - } - else - { - lt_fatal (__FILE__, __LINE__, - "error accessing file \"%s\": %s", - tmp_pathspec, nonnull (strerror (errno))); - } - } - XFREE (tmp_pathspec); - - if (!has_symlinks) - { - return xstrdup (pathspec); - } - - tmp_pathspec = realpath (pathspec, buf); - if (tmp_pathspec == 0) - { - lt_fatal (__FILE__, __LINE__, - "could not follow symlinks for %s", pathspec); - } - return xstrdup (tmp_pathspec); -#endif -} - -char * -strendzap (char *str, const char *pat) -{ - size_t len, patlen; - - assert (str != NULL); - assert (pat != NULL); - - len = strlen (str); - patlen = strlen (pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp (str, pat) == 0) - *str = '\0'; - } - return str; -} - -void -lt_debugprintf (const char *file, int line, const char *fmt, ...) -{ - va_list args; - if (lt_debug) - { - (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); - } -} - -static void -lt_error_core (int exit_status, const char *file, - int line, const char *mode, - const char *message, va_list ap) -{ - fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *file, int line, const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); - va_end (ap); -} - -static const char * -nonnull (const char *s) -{ - return s ? s : "(null)"; -} - -static const char * -nonempty (const char *s) -{ - return (s && !*s) ? "(empty)" : nonnull (s); -} - -void -lt_setenv (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_setenv) setting '%s' to '%s'\n", - nonnull (name), nonnull (value)); - { -#ifdef HAVE_SETENV - /* always make a copy, for consistency with !HAVE_SETENV */ - char *str = xstrdup (value); - setenv (name, str, 1); -#else - int len = strlen (name) + 1 + strlen (value) + 1; - char *str = XMALLOC (char, len); - sprintf (str, "%s=%s", name, value); - if (putenv (str) != EXIT_SUCCESS) - { - XFREE (str); - } -#endif - } -} - -char * -lt_extend_str (const char *orig_value, const char *add, int to_end) -{ - char *new_value; - if (orig_value && *orig_value) - { - int orig_value_len = strlen (orig_value); - int add_len = strlen (add); - new_value = XMALLOC (char, add_len + orig_value_len + 1); - if (to_end) - { - strcpy (new_value, orig_value); - strcpy (new_value + orig_value_len, add); - } - else - { - strcpy (new_value, add); - strcpy (new_value + add_len, orig_value); - } - } - else - { - new_value = xstrdup (add); - } - return new_value; -} - -void -lt_update_exe_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - /* some systems can't cope with a ':'-terminated path #' */ - int len = strlen (new_value); - while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) - { - new_value[len-1] = '\0'; - } - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -void -lt_update_lib_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -EOF - case $host_os in - mingw*) - cat <<"EOF" - -/* Prepares an argument vector before calling spawn(). - Note that spawn() does not by itself call the command interpreter - (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : - ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&v); - v.dwPlatformId == VER_PLATFORM_WIN32_NT; - }) ? "cmd.exe" : "command.com"). - Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() - interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a - special way: - - Space and tab are interpreted as delimiters. They are not treated as - delimiters if they are surrounded by double quotes: "...". - - Unescaped double quotes are removed from the input. Their only effect is - that within double quotes, space and tab are treated like normal - characters. - - Backslashes not followed by double quotes are not special. - - But 2*n+1 backslashes followed by a double quote become - n backslashes followed by a double quote (n >= 0): - \" -> " - \\\" -> \" - \\\\\" -> \\" - */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -char ** -prepare_spawn (char **argv) -{ - size_t argc; - char **new_argv; - size_t i; - - /* Count number of arguments. */ - for (argc = 0; argv[argc] != NULL; argc++) - ; - - /* Allocate new argument vector. */ - new_argv = XMALLOC (char *, argc + 1); - - /* Put quoted arguments into the new argument vector. */ - for (i = 0; i < argc; i++) - { - const char *string = argv[i]; - - if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); - else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = XMALLOC (char, length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } - else - new_argv[i] = (char *) string; - } - new_argv[argc] = NULL; - - return new_argv; -} -EOF - ;; - esac - - cat <<"EOF" -void lt_dump_script (FILE* f) -{ -EOF - func_emit_wrapper yes | - $SED -n -e ' -s/^\(.\{79\}\)\(..*\)/\1\ -\2/ -h -s/\([\\"]\)/\\\1/g -s/$/\\n/ -s/\([^\n]*\).*/ fputs ("\1", f);/p -g -D' - cat <<"EOF" -} -EOF -} -# end: func_emit_cwrapperexe_src - -# func_win32_import_lib_p ARG -# True if ARG is an import lib, as indicated by $file_magic_cmd -func_win32_import_lib_p () -{ - $opt_debug - case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in - *import*) : ;; - *) false ;; - esac -} - -# func_mode_link arg... -func_mode_link () -{ - $opt_debug - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra - # flag for every libtool invocation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - ;; - *) - allow_undefined=yes - ;; - esac - libtool_args=$nonopt - base_compile="$nonopt $@" - compile_command=$nonopt - finalize_command=$nonopt - - compile_rpath= - finalize_rpath= - compile_shlibpath= - finalize_shlibpath= - convenience= - old_convenience= - deplibs= - old_deplibs= - compiler_flags= - linker_flags= - dllsearchpath= - lib_search_path=`pwd` - inst_prefix_dir= - new_inherited_linker_flags= - - avoid_version=no - bindir= - dlfiles= - dlprefiles= - dlself=no - export_dynamic=no - export_symbols= - export_symbols_regex= - generated= - libobjs= - ltlibs= - module=no - no_install=no - objs= - non_pic_objects= - precious_files_regex= - prefer_static_libs=no - preload=no - prev= - prevarg= - release= - rpath= - xrpath= - perm_rpath= - temp_rpath= - thread_safe=no - vinfo= - vinfo_number=no - weak_libs= - single_module="${wl}-single_module" - func_infer_tag $base_compile - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - break - ;; - -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then - func_warning "complete static linking is impossible in this configuration" - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - func_append compile_command " @OUTPUT@" - func_append finalize_command " @OUTPUT@" - ;; - esac - - case $prev in - bindir) - bindir="$arg" - prev= - continue - ;; - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - func_append compile_command " @SYMFILE@" - func_append finalize_command " @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - func_append dlfiles " $arg" - else - func_append dlprefiles " $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - framework) - case $host in - *-*-darwin*) - case "$deplibs " in - *" $qarg.ltframework "*) ;; - *) func_append deplibs " $qarg.ltframework" # this is fixed later - ;; - esac - ;; - esac - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat "$save_arg"` - do -# func_append moreargs " $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - done - else - func_fatal_error "link input file \`$arg' does not exist" - fi - arg=$save_arg - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) func_append rpath " $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) func_append xrpath " $arg" ;; - esac - fi - prev= - continue - ;; - shrext) - shrext_cmds="$arg" - prev= - continue - ;; - weak) - func_append weak_libs " $arg" - prev= - continue - ;; - xcclinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xcompiler) - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xlinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $wl$qarg" - prev= - func_append compile_command " $wl$qarg" - func_append finalize_command " $wl$qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - # See comment for -static flag below, for more details. - func_append compile_command " $link_static_flag" - func_append finalize_command " $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -bindir) - prev=bindir - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - func_fatal_error "more than one -exported-symbols argument is not allowed" - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework) - prev=framework - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - func_append compile_command " $arg" - func_append finalize_command " $arg" - ;; - esac - continue - ;; - - -L*) - func_stripname "-L" '' "$arg" - if test -z "$func_stripname_result"; then - if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" - else - func_fatal_error "need path for \`-L' option" - fi - fi - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "* | *" $arg "*) - # Will only happen for absolute or sysroot arguments - ;; - *) - # Preserve sysroot, but never include relative directories - case $dir in - [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; - *) func_append deplibs " -L$dir" ;; - esac - func_append lib_search_path " $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - ::) dllsearchpath=$dir;; - *) func_append dllsearchpath ":$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - func_append deplibs " System.ltframework" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test "X$arg" = "X-lc" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue - ;; - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - func_append deplibs " $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot|--sysroot) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case "$new_inherited_linker_flags " in - *" $arg "*) ;; - * ) func_append new_inherited_linker_flags " $arg" ;; - esac - continue - ;; - - -multi_module) - single_module="${wl}-multi_module" - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - func_stripname '-R' '' "$arg" - dir=$func_stripname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - =*) - func_stripname '=' '' "$dir" - dir=$lt_sysroot$func_stripname_result - ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - continue - ;; - - -shared) - # The effects of -shared are defined in a previous loop. - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -weak) - prev=weak - continue - ;; - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Wl,*) - func_stripname '-Wl,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # -msg_* for osf cc - -msg_*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - # Flags to be passed through unchanged, with rationale: - # -64, -mips[0-9] enable 64-bit mode for the SGI compiler - # -r[0-9][0-9]* specify processor for the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler - # +DA*, +DD* enable 64-bit mode for the HP compiler - # -q* compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* architecture-specific flags for GCC - # -F/path path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # @file GCC response files - # -tp=* Portland pgcc target processor selection - # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - func_append compile_command " $arg" - func_append finalize_command " $arg" - func_append compiler_flags " $arg" - continue - ;; - - # Some other compiler flag. - -* | +*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - *.$objext) - # A standard object. - func_append objs " $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - ;; - - *.$libext) - # An archive. - func_append deplibs " $arg" - func_append old_deplibs " $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - func_append dlfiles " $func_resolve_sysroot_result" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - func_append dlprefiles " $func_resolve_sysroot_result" - prev= - else - func_append deplibs " $func_resolve_sysroot_result" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - done # argument parsing loop - - test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" - func_to_tool_file "$output_objdir/" - tool_output_objdir=$func_to_tool_file_result - # Create the object directory. - func_mkdir_p "$output_objdir" - - # Determine the type of output - case $output in - "") - func_fatal_help "you must specify an output file" - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then - case "$libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append libs " $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if $opt_duplicate_compiler_generated_deps; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; - esac - func_append pre_post_deps " $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - - case $linkmode in - lib) - passes="conv dlpreopen link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - - for pass in $passes; do - # The preopen pass in lib mode reverses $deplibs; put it back here - # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then - ## FIXME: Find the place where the list is rebuilt in the wrong - ## order, and fix it there properly - tmp_deplibs= - for deplib in $deplibs; do - tmp_deplibs="$deplib $tmp_deplibs" - done - deplibs="$tmp_deplibs" - fi - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; - esac - fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then - # Collect and forward deplibs of preopened libtool libs - for lib in $dlprefiles; do - # Ignore non-libtool-libs - dependency_libs= - func_resolve_sysroot "$lib" - case $lib in - *.la) func_source "$func_resolve_sysroot_result" ;; - esac - - # Collect preopened libtool deplibs, except any this library - # has declared as weak libs - for deplib in $dependency_libs; do - func_basename "$deplib" - deplib_base=$func_basename_result - case " $weak_libs " in - *" $deplib_base "*) ;; - *) func_append deplibs " $deplib" ;; - esac - done - done - libs="$dlprefiles" - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" - continue - fi - func_stripname '-l' '' "$deplib" - name=$func_stripname_result - if test "$linkmode" = lib; then - searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" - else - searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" - fi - for searchdir in $searchdirs; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if func_lalib_p "$lib"; then - library_names= - old_library= - func_source "$lib" - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - *) - func_warning "\`-L' is ignored for archives/objects" - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - func_stripname '-R' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) - func_resolve_sysroot "$deplib" - lib=$func_resolve_sysroot_result - ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. - case " $dlpreconveniencelibs " in - *" $deplib "*) ;; - *) - valid_a_lib=no - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes - fi - ;; - pass_all) - valid_a_lib=yes - ;; - esac - if test "$valid_a_lib" != yes; then - echo - $ECHO "*** Warning: Trying to link with static lib archive $deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because the file extensions .$libext of this argument makes me believe" - echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - ;; - esac - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - func_append newdlprefiles " $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append newdlfiles " $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" - - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - inherited_linker_flags= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - func_source "$lib" - - # Convert "-framework foo" to "foo.ltframework" - if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` - for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do - case " $new_inherited_linker_flags " in - *" $tmp_inherited_linker_flag "*) ;; - *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; - esac - done - fi - dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && func_append dlfiles " $dlopen" - test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - # It is a libtool convenience library, so add in its objects. - func_append convenience " $ladir/$objdir/$old_library" - func_append old_convenience " $ladir/$objdir/$old_library" - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" - fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then - linklib=$old_library - else - for l in $old_library $library_names; do - linklib="$l" - done - fi - if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi - if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - func_append dlprefiles " $lib $dependency_libs" - else - func_append newdlfiles " $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" - func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" - fi - ;; - esac - func_basename "$lib" - laname="$func_basename_result" - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" - fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - fi - fi # $installed = yes - func_stripname 'lib' '.la' "$laname" - name=$func_stripname_result - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" - fi - case "$host" in - # special handling for platforms with PE-DLLs. - *cygwin* | *mingw* | *cegcc* ) - # Linker will automatically link against shared library if both - # static and shared are present. Therefore, ensure we extract - # symbols from the import library if a shared library is present - # (otherwise, the dlopen module name will be incorrect). We do - # this by putting the import library name into $newdlprefiles. - # We recover the dlopen module name by 'saving' the la file - # name in a special purpose variable, and (later) extracting the - # dlname from the la file. - if test -n "$dlname"; then - func_tr_sh "$dir/$linklib" - eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" - func_append newdlprefiles " $dir/$linklib" - else - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - fi - ;; - * ) - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - func_append newdlprefiles " $dir/$dlname" - else - func_append newdlprefiles " $dir/$linklib" - fi - ;; - esac - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - func_append newlib_search_path " $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in - *"$absdir:"*) ;; - *) func_append temp_rpath "$absdir:" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then - use_static_libs=no - fi - if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then - case $host in - *cygwin* | *mingw* | *cegcc*) - # No point in relinking DLLs because paths are not encoded - func_append notinst_deplibs " $lib" - need_relink=no - ;; - *) - if test "$installed" = no; then - func_append notinst_deplibs " $lib" - need_relink=yes - fi - ;; - esac - # This is a shared library - - # Warn about portability, can't link against -module's on some - # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" - for dlpremoduletest in $dlprefiles; do - if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" - break - fi - done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then - echo - if test "$linkmode" = prog; then - $ECHO "*** Warning: Linking the executable $output against the loadable module" - else - $ECHO "*** Warning: Linking the shared library $output against the loadable module" - fi - $ECHO "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - shift - realname="$1" - shift - libname=`eval "\\$ECHO \"$libname_spec\""` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw* | *cegcc*) - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - func_basename "$soroot" - soname="$func_basename_result" - func_stripname 'lib' '.dll' "$soname" - newlib=libimp-$func_stripname_result.a - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - func_verbose "extracting exported symbol list from \`$soname'" - func_execute_cmds "$extract_expsyms_cmds" 'exit $?' - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" - func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$opt_mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not - # link against it, someone is ignoring the earlier warnings - if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then - if test "X$dlopenmodule" != "X$lib"; then - $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - echo - echo "*** And there doesn't seem to be a static archive available" - echo "*** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - elif test -n "$old_library"; then - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - func_fatal_configuration "unsupported hardcode properties" - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) func_append compile_shlibpath "$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$opt_mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - echo "*** But as you try to build a module library, libtool will still create " - echo "*** a static module, that should work as long as the dlopening application" - echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) func_stripname '-R' '' "$libdir" - temp_xrpath=$func_stripname_result - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) func_append xrpath " $temp_xrpath";; - esac;; - *) func_append temp_deplibs " $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - func_append newlib_search_path " $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result";; - *) func_resolve_sysroot "$deplib" ;; - esac - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $func_resolve_sysroot_result "*) - func_append specialdeplibs " $func_resolve_sysroot_result" ;; - esac - fi - func_append tmp_libs " $func_resolve_sysroot_result" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - path= - case $deplib in - -L*) path="$deplib" ;; - *.la) - func_resolve_sysroot "$deplib" - deplib=$func_resolve_sysroot_result - func_dirname "$deplib" "" "." - dir=$func_dirname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" - fi - ;; - esac - if $GREP "^installed=no" $deplib > /dev/null; then - case $host in - *-*-darwin*) - depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" - path= - fi - fi - ;; - *) - path="-L$absdir/$objdir" - ;; - esac - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - test "$absdir" != "$libdir" && \ - func_warning "\`$deplib' seems to be moved" - - path="-L$absdir" - fi - ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then - compile_deplibs="$new_inherited_linker_flags $compile_deplibs" - finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" - else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - fi - fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) func_append lib_search_path " $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) func_append tmp_libs " $deplib" ;; - esac - ;; - *) func_append tmp_libs " $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - func_append tmp_libs " $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" - - test -n "$release" && \ - func_warning "\`-release' is ignored for archives" - - test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - func_append objs "$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - func_stripname 'lib' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" - - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - func_stripname '' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - func_stripname '' '.la' "$outputname" - libname=$func_stripname_result - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" - else - echo - $ECHO "*** Warning: Linking the shared library $output against the non-libtool" - $ECHO "*** objects $objs is not portable!" - func_append libobjs " $objs" - fi - fi - - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" - - set dummy $rpath - shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" - - install_libdir="$1" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" - - test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - shift - IFS="$save_ifs" - - test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$1" - number_minor="$2" - number_revision="$3" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_minor" - lt_irix_increment=no - ;; - esac - ;; - no) - current="$1" - revision="$2" - age="$3" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - func_arith $current + 1 - minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current" - ;; - - irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then - func_arith $current - $age - else - func_arith $current - $age + 1 - fi - major=$func_arith_result - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - func_arith $revision - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) # correct to gnu/linux during the next big refactor - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - ;; - - osf) - func_arith $current - $age - major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - func_arith $current - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - func_append verstring ":${current}.0" - ;; - - qnx) - major=".$current" - versuffix=".$current" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - - *) - func_fatal_configuration "unknown library version type \`$version_type'" - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - - fi - - func_generate_dlsyms "$libname" "$libname" "yes" - func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= - - if test "$opt_mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$ECHO "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext | *.gcno) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then - if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - func_append removelist " $p" - ;; - *) ;; - esac - done - test -n "$removelist" && \ - func_show_eval "${RM}r \$removelist" - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - func_append oldlibs " $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` - # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` - # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - func_replace_sysroot "$libdir" - func_append temp_xrpath " -R$func_replace_sysroot_result" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) func_append dlfiles " $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) func_append dlprefiles " $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - func_append deplibs " System.ltframework" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - func_append deplibs " -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $opt_dry_run || $RM conftest.c - cat > conftest.c </dev/null` - $nocaseglob - else - potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` - fi - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null | - $GREP " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | - $SED -e 10q | - $EGREP "$file_magic_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for file magic test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a file magic. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - for a_deplib in $deplibs; do - case $a_deplib in - -l*) - func_stripname -l '' "$a_deplib" - name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - func_append newdeplibs " $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval "\\$ECHO \"$libname_spec\""` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ - $EGREP "$match_pattern_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a regex pattern. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` - done - fi - case $tmp_deplibs in - *[!\ \ ]*) - echo - if test "X$deplibs_check_method" = "Xnone"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - ;; - esac - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - echo - echo "*** Since this library must not contain undefined symbols," - echo "*** because either the platform does not support them or" - echo "*** it was explicitly requested with -no-undefined," - echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - case $host in - *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - deplibs="$new_libs" - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. - # FIXME: should test the right _cmds variable. - case $archive_cmds in - *\$LD\ *) wl= ;; - esac - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - func_replace_sysroot "$libdir" - libdir=$func_replace_sysroot_result - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append dep_rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - shift - realname="$1" - shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - linknames= - for link - do - func_append linknames " $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` - test "X$libobjs" = "X " && libobjs= - - delfiles= - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" - func_append delfiles " $export_symbols" - fi - - orig_export_symbols= - case $host_os in - cygwin* | mingw* | cegcc*) - if test -n "$export_symbols" && test -z "$export_symbols_regex"; then - # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then - # and it's NOT already a .def file. Must figure out - # which of the given symbols are data symbols and tag - # them as such. So, trigger use of export_symbols_cmds. - # export_symbols gets reassigned inside the "prepare - # the list of exported symbols" if statement, so the - # include_expsyms logic still works. - orig_export_symbols="$export_symbols" - export_symbols= - always_export_symbols=yes - fi - fi - ;; - esac - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd1 in $cmds; do - IFS="$save_ifs" - # Take the normal branch if the nm_file_list_spec branch - # doesn't work or if tool conversion is not needed. - case $nm_file_list_spec~$to_tool_file_cmd in - *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) - try_normal_branch=yes - eval cmd=\"$cmd1\" - func_len " $cmd" - len=$func_len_result - ;; - *) - try_normal_branch=no - ;; - esac - if test "$try_normal_branch" = yes \ - && { test "$len" -lt "$max_cmd_len" \ - || test "$max_cmd_len" -le -1; } - then - func_show_eval "$cmd" 'exit $?' - skipped_export=false - elif test -n "$nm_file_list_spec"; then - func_basename "$output" - output_la=$func_basename_result - save_libobjs=$libobjs - save_output=$output - output=${output_objdir}/${output_la}.nm - func_to_tool_file "$output" - libobjs=$nm_file_list_spec$func_to_tool_file_result - func_append delfiles " $output" - func_verbose "creating $NM input file list: $output" - for obj in $save_libobjs; do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > "$output" - eval cmd=\"$cmd1\" - func_show_eval "$cmd" 'exit $?' - output=$save_output - libobjs=$save_libobjs - skipped_export=false - else - # The command line is too long to execute in one step. - func_verbose "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - func_append tmp_deplibs " $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && - test -z "$libobjs"; then - # extract the archives, so we have objects to list. - # TODO: could optimize this to just extract one archive. - whole_archive_flag_spec= - fi - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - else - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - func_append linker_flags " $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && - func_len " $test_cmds" && - len=$func_len_result && - test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise - # or, if using GNU ld and skipped_export is not :, use a linker - # script. - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - func_basename "$output" - output_la=$func_basename_result - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - last_robj= - k=1 - - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript - func_verbose "creating GNU ld script: $output" - echo 'INPUT (' > $output - for obj in $save_libobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - echo ')' >> $output - func_append delfiles " $output" - func_to_tool_file "$output" - output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk - func_verbose "creating linker input file list: $output" - : > $output - set x $save_libobjs - shift - firstobj= - if test "$compiler_needs_object" = yes; then - firstobj="$1 " - shift - fi - for obj - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - func_append delfiles " $output" - func_to_tool_file "$output" - output=$firstobj\"$file_list_spec$func_to_tool_file_result\" - else - if test -n "$save_libobjs"; then - func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext - eval test_cmds=\"$reload_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - if test "X$objlist" = X || - test "$len" -lt "$max_cmd_len"; then - func_append objlist " $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - reload_objs=$objlist - eval concat_cmds=\"$reload_cmds\" - else - # All subsequent reloadable object files will link in - # the last one created. - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - func_arith $k + 1 - k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext - objlist=" $obj" - func_len " $last_robj" - func_arith $len0 + $func_len_result - len=$func_arith_result - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" - fi - func_append delfiles " $output" - - else - output= - fi - - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - libobjs=$output - # Append the command to create the export file. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - fi - - test -n "$save_libobjs" && - func_verbose "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - if test -n "$export_symbols_regex" && ${skipped_export-false}; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - - if ${skipped_export-false}; then - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - fi - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - fi - - if test -n "$delfiles"; then - # Append the command to remove temporary files to $cmds. - eval cmds=\"\$cmds~\$RM $delfiles\" - fi - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - func_show_eval '${RM}r "$gentop"' - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" - - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" - - test -n "$release" && \ - func_warning "\`-release' is ignored for objects" - - case $output in - *.lo) - test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" - - libobj=$output - func_lo2o "$libobj" - obj=$func_lo2o_result - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $opt_dry_run || $RM $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - else - gentop="$output_objdir/${obj}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - func_execute_cmds "$reload_cmds" 'exit $?' - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - func_execute_cmds "$reload_cmds" 'exit $?' - fi - - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) func_stripname '' '.exe' "$output" - output=$func_stripname_result.exe;; - esac - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" - - test -n "$release" && \ - func_warning "\`-release' is ignored for programs" - - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - case $host in - *-*-darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then - case ${MACOSX_DEPLOYMENT_TARGET-10.0} in - 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" - ;; - esac - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - compile_deplibs="$new_libs" - - - func_append compile_command " $compile_deplibs" - func_append finalize_command " $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - ::) dllsearchpath=$libdir;; - *) func_append dllsearchpath ":$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) func_append finalize_perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - fi - - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" - - # template prelinking step - if test -n "$prelink_cmds"; then - func_execute_cmds "$prelink_cmds" 'exit $?' - fi - - wrappers_required=yes - case $host in - *cegcc* | *mingw32ce*) - # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no - ;; - *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - esac - if test "$wrappers_required" = no; then - # Replace the output file specification. - compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - exit_status=0 - func_show_eval "$link_command" 'exit_status=$?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' - fi - - exit $exit_status - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - func_append rpath "$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $opt_dry_run || $RM $output - # Link the executable and exit - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - exit $EXIT_SUCCESS - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname - - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output_objdir/$outputname" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Now create the wrapper script. - func_verbose "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - fi - - # Only actually do things if not in dry run mode. - $opt_dry_run || { - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) func_stripname '' '.exe' "$output" - output=$func_stripname_result ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - func_stripname '' '.exe' "$outputname" - outputname=$func_stripname_result ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - func_dirname_and_basename "$output" "" "." - output_name=$func_basename_result - output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" - $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - func_emit_cwrapperexe_src > $cwrappersource - - # The wrapper executable is built using the $host compiler, - # because it contains $host paths and files. If cross- - # compiling, it, like the target executable, must be - # executed on the $host or under an emulation environment. - $opt_dry_run || { - $LTCC $LTCFLAGS -o $cwrapper $cwrappersource - $STRIP $cwrapper - } - - # Now, create the wrapper script for func_source use: - func_ltwrapper_scriptname $cwrapper - $RM $func_ltwrapper_scriptname_result - trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 - $opt_dry_run || { - # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then - $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result - else - func_emit_wrapper no > $func_ltwrapper_scriptname_result - fi - } - ;; - * ) - $RM $output - trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 - - func_emit_wrapper no > $output - chmod +x $output - ;; - esac - } - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $addlibs - func_append oldobjs " $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append oldobjs " $func_extract_archives_result" - fi - - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else - echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - func_basename "$obj" - objbase="$func_basename_result" - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - func_arith $counter + 1 - counter=$func_arith_result - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - func_append oldobjs " $gentop/$newobj" - ;; - *) func_append oldobjs " $obj" ;; - esac - done - fi - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - eval cmds=\"$old_archive_cmds\" - - func_len " $cmds" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - elif test -n "$archiver_list_spec"; then - func_verbose "using command file archive linking..." - for obj in $oldobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > $output_objdir/$libname.libcmd - func_to_tool_file "$output_objdir/$libname.libcmd" - oldobjs=" $archiver_list_spec$func_to_tool_file_result" - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - func_verbose "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - oldobjs= - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - eval test_cmds=\"$old_archive_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - for obj in $save_oldobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - func_append objlist " $obj" - if test "$len" -lt "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - len=$len0 - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - func_execute_cmds "$cmds" 'exit $?' - done - - test -n "$generated" && \ - func_show_eval "${RM}r$generated" - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - func_verbose "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - - # Only create the output if not a dry run. - $opt_dry_run || { - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - func_basename "$deplib" - name="$func_basename_result" - func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" - ;; - -L*) - func_stripname -L '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -L$func_replace_sysroot_result" - ;; - -R*) - func_stripname -R '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -R$func_replace_sysroot_result" - ;; - *) func_append newdependency_libs " $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - - for lib in $dlfiles; do - case $lib in - *.la) - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" - ;; - *) func_append newdlfiles " $lib" ;; - esac - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - *.la) - # Only pass preopened files to the pseudo-archive (for - # eventual linking with the app. that links it) if we - # didn't already link the preopened objects directly into - # the library: - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" - ;; - esac - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlfiles " $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlprefiles " $abs" - done - dlprefiles="$newdlprefiles" - fi - $RM $output - # place dlname in correct position for cygwin - # In fact, it would be nice if we could use this code for all target - # systems that can't hard-code library paths into their executables - # and that have no shared library path variable independent of PATH, - # but it turns out we can't easily determine that from inspecting - # libtool variables, so we have to hard-code the OSs to which it - # applies here; at the moment, that means platforms that use the PE - # object format with DLL files. See the long comment at the top of - # tests/bindir.at for full details. - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) - # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then - func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname - else - # Otherwise fall back on heuristic. - tdlname=../bin/$dlname - fi - ;; - esac - $ECHO > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Linker flags that can not go in dependency_libs. -inherited_linker_flags='$new_inherited_linker_flags' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Names of additional weak libraries provided by this library -weak_library_names='$weak_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $ECHO >> $output "\ -relink_command=\"$relink_command\"" - fi - done - } - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' - ;; - esac - exit $EXIT_SUCCESS -} - -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} - - -# func_mode_uninstall arg... -func_mode_uninstall () -{ - $opt_debug - RM="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; - -*) func_append RM " $arg" ;; - *) func_append files " $arg" ;; - esac - done - - test -z "$RM" && \ - func_fatal_help "you must specify an RM program" - - rmdirs= - - for file in $files; do - func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" - else - odir="$dir/$objdir" - fi - func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" - - # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then - case " $rmdirs " in - *" $odir "*) ;; - *) func_append rmdirs " $odir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if { test -L "$file"; } >/dev/null 2>&1 || - { test -h "$file"; } >/dev/null 2>&1 || - test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if func_lalib_p "$file"; then - func_source $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - func_append rmfiles " $odir/$n" - done - test -n "$old_library" && func_append rmfiles " $odir/$old_library" - - case "$opt_mode" in - clean) - case " $library_names " in - *" $dlname "*) ;; - *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; - esac - test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if func_lalib_p "$file"; then - - # Read the .lo file - func_source $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then - func_append rmfiles " $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then - func_append rmfiles " $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$opt_mode" = clean ; then - noexename=$name - case $file in - *.exe) - func_stripname '' '.exe' "$file" - file=$func_stripname_result - func_stripname '' '.exe' "$name" - noexename=$func_stripname_result - # $file with .exe has already been added to rmfiles, - # add $file without .exe - func_append rmfiles " $file" - ;; - esac - # Do a test to see if this is a libtool program. - if func_ltwrapper_p "$file"; then - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - relink_command= - func_source $func_ltwrapper_scriptname_result - func_append rmfiles " $func_ltwrapper_scriptname_result" - else - relink_command= - func_source $dir/$noexename - fi - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - func_show_eval "$RM $rmfiles" 'exit_status=1' - done - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - func_show_eval "rmdir $dir >/dev/null 2>&1" - fi - done - - exit $exit_status -} - -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} - -test -z "$opt_mode" && { - help="$generic_help" - func_fatal_help "you must specify a MODE" -} - -test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" - -if test -n "$exec_cmd"; then - eval exec "$exec_cmd" - exit $EXIT_FAILURE -fi - -exit $exit_status - - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: -# vi:sw=2 - diff --git a/build-aux/missing b/build-aux/missing deleted file mode 100755 index cdea514931..0000000000 --- a/build-aux/missing +++ /dev/null @@ -1,215 +0,0 @@ -#! /bin/sh -# Common wrapper for a few potentially missing GNU programs. - -scriptversion=2012-06-26.16; # UTC - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# Originally written by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try '$0 --help' for more information" - exit 1 -fi - -case $1 in - - --is-lightweight) - # Used by our autoconf macros to check whether the available missing - # script is modern enough. - exit 0 - ;; - - --run) - # Back-compat with the calling convention used by older automake. - shift - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due -to PROGRAM being missing or too old. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man - -Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and -'g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: unknown '$1' option" - echo 1>&2 "Try '$0 --help' for more information" - exit 1 - ;; - -esac - -# Run the given program, remember its exit status. -"$@"; st=$? - -# If it succeeded, we are done. -test $st -eq 0 && exit 0 - -# Also exit now if we it failed (or wasn't found), and '--version' was -# passed; such an option is passed most likely to detect whether the -# program is present and works. -case $2 in --version|--help) exit $st;; esac - -# Exit code 63 means version mismatch. This often happens when the user -# tries to use an ancient version of a tool on a file that requires a -# minimum version. -if test $st -eq 63; then - msg="probably too old" -elif test $st -eq 127; then - # Program was missing. - msg="missing on your system" -else - # Program was found and executed, but failed. Give up. - exit $st -fi - -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software - -program_details () -{ - case $1 in - aclocal|automake) - echo "The '$1' program is part of the GNU Automake package:" - echo "<$gnu_software_URL/automake>" - echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/autoconf>" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - autoconf|autom4te|autoheader) - echo "The '$1' program is part of the GNU Autoconf package:" - echo "<$gnu_software_URL/autoconf/>" - echo "It also requires GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - esac -} - -give_advice () -{ - # Normalize program name to check for. - normalized_program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - - printf '%s\n' "'$1' is $msg." - - configure_deps="'configure.ac' or m4 files included by 'configure.ac'" - case $normalized_program in - autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' - ;; - autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" - echo "$configure_deps." - program_details 'autoheader' - ;; - automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" - echo "$configure_deps." - program_details 'aclocal' - ;; - autom4te*) - echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." - program_details 'autom4te' - ;; - bison*|yacc*) - echo "You should only need it if you modified a '.y' file." - echo "You may want to install the GNU Bison package:" - echo "<$gnu_software_URL/bison/>" - ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; - help2man*) - echo "You should only need it if you modified a dependency" \ - "of a man page." - echo "You may want to install the GNU Help2man package:" - echo "<$gnu_software_URL/help2man/>" - ;; - makeinfo*) - echo "You should only need it if you modified a '.texi' file, or" - echo "any other file indirectly affecting the aspect of the manual." - echo "You might want to install the Texinfo package:" - echo "<$gnu_software_URL/texinfo/>" - echo "The spurious makeinfo call might also be the consequence of" - echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" - echo "want to install GNU make:" - echo "<$gnu_software_URL/make/>" - ;; - *) - echo "You might have modified some files without having the proper" - echo "tools for further handling them. Check the 'README' file, it" - echo "often tells you about the needed prerequisites for installing" - echo "this package. You may also peek at any GNU archive site, in" - echo "case some other package contains this missing '$1' program." - ;; - esac -} - -give_advice "$1" | sed -e '1s/^/WARNING: /' \ - -e '2,$s/^/ /' >&2 - -# Propagate the correct exit status (expected to be 127 for a program -# not found, 63 for a program that failed due to version mismatch). -exit $st - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/cmake-format.yaml b/cmake-format.yaml new file mode 100644 index 0000000000..082e7b5ef1 --- /dev/null +++ b/cmake-format.yaml @@ -0,0 +1,48 @@ +parse: + additional_commands: + bout_add_example: + pargs: 1 + kwargs: + CONFLICTS: '*' + DATA_DIRS: '*' + EXTRA_FILES: '*' + REQUIRES: '*' + SOURCES: '*' + bout_add_integrated_test: + pargs: 1 + flags: [USE_DATA_BOUT_INP, USE_RUNTEST] + kwargs: + CONFLICTS: '*' + DOWNLOAD: 1 + DOWNLOAD_NAME: 1 + EXECUTABLE_NAME: 1 + EXTRA_DEPENDS: '*' + EXTRA_FILES: '*' + PROCESSORS: 1 + REQUIRES: '*' + SOURCES: '*' + TESTARGS: '*' + bout_add_mms_test: + pargs: 1 + flags: [USE_DATA_BOUT_INP, USE_RUNTEST] + kwargs: + CONFLICTS: '*' + DOWNLOAD: 1 + DOWNLOAD_NAME: 1 + EXECUTABLE_NAME: 1 + EXTRA_DEPENDS: '*' + EXTRA_FILES: '*' + PROCESSORS: 1 + REQUIRES: '*' + SOURCES: '*' + TESTARGS: '*' + bout_handle_requires_conflicts: + pargs: 2 + kwargs: + CONFLICTS: '*' + REQUIRES: '*' +format: + dangle_parens: true +markup: + # markup messes up comments - disable it + enable_markup: false \ No newline at end of file diff --git a/cmake/BOUT++functions.cmake b/cmake/BOUT++functions.cmake index 40e45f99be..c5abb1169c 100644 --- a/cmake/BOUT++functions.cmake +++ b/cmake/BOUT++functions.cmake @@ -3,9 +3,9 @@ # Copy FILENAME from source directory to build directory macro(bout_copy_file FILENAME) configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME} - ${CMAKE_CURRENT_BINARY_DIR}/${FILENAME} - COPYONLY) + ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME} + ${CMAKE_CURRENT_BINARY_DIR}/${FILENAME} COPYONLY + ) endmacro() # Handle the REQUIRES and CONFLICTS arguments for models, examples, @@ -15,16 +15,22 @@ macro(bout_handle_requires_conflicts TYPENAME TYPEVAR) set(multiValueArgs REQUIRES CONFLICTS) cmake_parse_arguments(BOUT_HANDLE_OPTIONS "" "" "${multiValueArgs}" ${ARGN}) - foreach (REQUIREMENT IN LISTS BOUT_HANDLE_OPTIONS_REQUIRES) - if (NOT ${REQUIREMENT}) - message(STATUS "Not building ${TYPENAME} ${TYPEVAR}, requirement not met: ${REQUIREMENT}") + foreach(REQUIREMENT IN LISTS BOUT_HANDLE_OPTIONS_REQUIRES) + if(NOT ${REQUIREMENT}) + message( + STATUS + "Not building ${TYPENAME} ${TYPEVAR}, requirement not met: ${REQUIREMENT}" + ) return() endif() endforeach() - foreach (CONFLICT IN LISTS BOUT_HANDLE_OPTIONS_CONFLICTS) - if (${CONFLICT}) - message(STATUS "Not building ${TYPENAME} ${TYPEVAR}, conflicts with: ${CONFLICT}") + foreach(CONFLICT IN LISTS BOUT_HANDLE_OPTIONS_CONFLICTS) + if(${CONFLICT}) + message( + STATUS + "Not building ${TYPENAME} ${TYPEVAR}, conflicts with: ${CONFLICT}" + ) return() endif() endforeach() @@ -46,25 +52,29 @@ function(bout_add_model MODEL) set(multiValueArgs SOURCES REQUIRES CONFLICTS) cmake_parse_arguments(BOUT_MODEL_OPTIONS "" "" "${multiValueArgs}" ${ARGN}) - bout_handle_requires_conflicts("model" MODEL + bout_handle_requires_conflicts( + "model" MODEL REQUIRES ${BOUT_MODEL_OPTIONS_REQUIRES} CONFLICTS ${BOUT_MODEL_OPTIONS_CONFLICTS} - ) + ) - if (NOT BOUT_MODEL_OPTIONS_SOURCES) - message(FATAL_ERROR "Required argument SOURCES missing from 'bout_add_model'") + if(NOT BOUT_MODEL_OPTIONS_SOURCES) + message( + FATAL_ERROR "Required argument SOURCES missing from 'bout_add_model'" + ) endif() - if ("SOURCES" IN_LIST BOUT_MODEL_OPTIONS_KEYWORDS_MISSING_VALUES) + if("SOURCES" IN_LIST BOUT_MODEL_OPTIONS_KEYWORDS_MISSING_VALUES) message(FATAL_ERROR "SOURCES missing values from 'bout_add_model'") endif() add_executable(${MODEL} ${BOUT_MODEL_OPTIONS_SOURCES}) target_link_libraries(${MODEL} bout++::bout++) - target_include_directories(${MODEL} PRIVATE $) + target_include_directories( + ${MODEL} PRIVATE $ + ) endfunction() - # Build a BOUT++ example # # If called from a standalone project, just builds the example as a @@ -85,37 +95,38 @@ function(bout_add_example EXAMPLENAME) set(multiValueArgs SOURCES REQUIRES CONFLICTS DATA_DIRS EXTRA_FILES) cmake_parse_arguments(BOUT_EXAMPLE_OPTIONS "" "" "${multiValueArgs}" ${ARGN}) - bout_handle_requires_conflicts("example" ${EXAMPLENAME} + bout_handle_requires_conflicts( + "example" ${EXAMPLENAME} REQUIRES ${BOUT_EXAMPLE_OPTIONS_REQUIRES} CONFLICTS ${BOUT_EXAMPLE_OPTIONS_CONFLICTS} - ) + ) bout_add_model(${EXAMPLENAME} SOURCES ${BOUT_EXAMPLE_OPTIONS_SOURCES}) # If this is a standalone project, we can stop here. Otherwise, we # need to copy the various input files to the build directory get_directory_property(HAS_PARENT PARENT_DIRECTORY) - if (NOT HAS_PARENT) + if(NOT HAS_PARENT) return() endif() # Copy the documentation if it exists - if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/README.md) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/README.md) bout_copy_file(README.md) endif() # Copy the input file - if (NOT BOUT_EXAMPLE_OPTIONS_DATA_DIRS) + if(NOT BOUT_EXAMPLE_OPTIONS_DATA_DIRS) bout_copy_file(data/BOUT.inp) else() - foreach (DATA_DIR IN LISTS BOUT_EXAMPLE_OPTIONS_DATA_DIRS) + foreach(DATA_DIR IN LISTS BOUT_EXAMPLE_OPTIONS_DATA_DIRS) bout_copy_file(${DATA_DIR}/BOUT.inp) endforeach() endif() # Copy any other needed files - if (BOUT_EXAMPLE_OPTIONS_EXTRA_FILES) - foreach (FILE ${BOUT_EXAMPLE_OPTIONS_EXTRA_FILES}) + if(BOUT_EXAMPLE_OPTIONS_EXTRA_FILES) + foreach(FILE ${BOUT_EXAMPLE_OPTIONS_EXTRA_FILES}) bout_copy_file("${FILE}") endforeach() endif() @@ -125,7 +136,6 @@ function(bout_add_example EXAMPLENAME) add_dependencies(build-all-examples ${EXAMPLENAME}) endfunction() - # Add a new integrated or MMS test. By default, the executable is # named like the first source, stripped of its file extension. If no # sources are given, then you probably at least want to set @@ -162,38 +172,54 @@ endfunction() # function(bout_add_integrated_or_mms_test BUILD_CHECK_TARGET TESTNAME) set(options USE_RUNTEST USE_DATA_BOUT_INP) - set(oneValueArgs EXECUTABLE_NAME PROCESSORS) - set(multiValueArgs SOURCES EXTRA_FILES REQUIRES CONFLICTS TESTARGS EXTRA_DEPENDS) - cmake_parse_arguments(BOUT_TEST_OPTIONS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(oneValueArgs EXECUTABLE_NAME PROCESSORS DOWNLOAD DOWNLOAD_NAME + PYTHON_TEST_FILE + ) + set(multiValueArgs SOURCES EXTRA_FILES REQUIRES CONFLICTS TESTARGS + EXTRA_DEPENDS + ) + cmake_parse_arguments( + BOUT_TEST_OPTIONS "${options}" "${oneValueArgs}" "${multiValueArgs}" + ${ARGN} + ) - bout_handle_requires_conflicts("test" ${TESTNAME} + bout_handle_requires_conflicts( + "test" ${TESTNAME} REQUIRES ${BOUT_TEST_OPTIONS_REQUIRES} CONFLICTS ${BOUT_TEST_OPTIONS_CONFLICTS} - ) + ) - if (BOUT_TEST_OPTIONS_SOURCES) + if(BOUT_TEST_OPTIONS_SOURCES) # We've got some sources, so compile them into an executable and # link against BOUT++ add_executable(${TESTNAME} ${BOUT_TEST_OPTIONS_SOURCES}) target_link_libraries(${TESTNAME} bout++) - target_include_directories(${TESTNAME} PRIVATE $) + target_include_directories( + ${TESTNAME} PRIVATE $ + ) set_target_properties(${TESTNAME} PROPERTIES FOLDER tests/integrated) # Set the name of the executable. We either take it as an option, # or use the first source file, stripping the file suffix - if (BOUT_TEST_OPTIONS_EXECUTABLE_NAME) - set_target_properties(${TESTNAME} PROPERTIES OUTPUT_NAME ${BOUT_TEST_OPTIONS_EXECUTABLE_NAME}) + if(BOUT_TEST_OPTIONS_EXECUTABLE_NAME) + set_target_properties( + ${TESTNAME} PROPERTIES OUTPUT_NAME ${BOUT_TEST_OPTIONS_EXECUTABLE_NAME} + ) else() # If more than one source file, just get the first one list(LENGTH ${BOUT_TEST_OPTIONS_SOURCES} BOUT_SOURCES_LENGTH) - if (BOUT_SOURCES_LENGTH GREATER 0) + if(BOUT_SOURCES_LENGTH GREATER 0) list(GET ${BOUT_TEST_OPTIONS_SOURCES} 0 BOUT_TEST_FIRST_SOURCE) else() set(BOUT_TEST_FIRST_SOURCE ${BOUT_TEST_OPTIONS_SOURCES}) endif() # Strip the directory and file extension from the source file - get_filename_component(BOUT_TEST_EXECUTABLE_NAME ${BOUT_TEST_FIRST_SOURCE} NAME_WE) - set_target_properties(${TESTNAME} PROPERTIES OUTPUT_NAME ${BOUT_TEST_EXECUTABLE_NAME}) + get_filename_component( + BOUT_TEST_EXECUTABLE_NAME ${BOUT_TEST_FIRST_SOURCE} NAME_WE + ) + set_target_properties( + ${TESTNAME} PROPERTIES OUTPUT_NAME ${BOUT_TEST_EXECUTABLE_NAME} + ) endif() # Add the test to the build-check-integrated-tests target @@ -202,40 +228,72 @@ function(bout_add_integrated_or_mms_test BUILD_CHECK_TARGET TESTNAME) add_custom_target(${TESTNAME}) endif() - if (BOUT_TEST_OPTIONS_EXTRA_DEPENDS) + if(BOUT_TEST_OPTIONS_DOWNLOAD) + if(NOT BOUT_TEST_OPTIONS_DOWNLOAD_NAME) + message(FATAL_ERROR "We need DOWNLOAD_NAME if we should DOWNLOAD!") + endif() + set(output) + add_custom_command( + OUTPUT ${BOUT_TEST_OPTIONS_DOWNLOAD_NAME} + COMMAND + wget ${BOUT_TEST_OPTIONS_DOWNLOAD} -O ${BOUT_TEST_OPTIONS_DOWNLOAD_NAME} + $ENV{BOUT_TEST_DOWNLOAD_FLAGS} || curl ${BOUT_TEST_OPTIONS_DOWNLOAD} -o + ${BOUT_TEST_OPTIONS_DOWNLOAD_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Downloading ${BOUT_TEST_OPTIONS_DOWNLOAD_NAME}" + ) + add_custom_target( + download_test_data DEPENDS ${BOUT_TEST_OPTIONS_DOWNLOAD_NAME} + ) + add_dependencies(${TESTNAME} download_test_data) + endif() + + if(BOUT_TEST_OPTIONS_EXTRA_DEPENDS) add_dependencies(${TESTNAME} ${BOUT_TEST_OPTIONS_EXTRA_DEPENDS}) endif() - if (NOT BOUT_TEST_OPTIONS_PROCESSORS) + if(NOT BOUT_TEST_OPTIONS_PROCESSORS) set(BOUT_TEST_OPTIONS_PROCESSORS 1) endif() # Set the actual test command - if (BOUT_TEST_OPTIONS_USE_RUNTEST) - add_test(NAME ${TESTNAME} - COMMAND ./runtest ${BOUT_TEST_OPTIONS_TESTARGS} - ) - set_tests_properties(${TESTNAME} PROPERTIES - ENVIRONMENT PYTHONPATH=${BOUT_PYTHONPATH}:$ENV{PYTHONPATH} + if(BOUT_TEST_OPTIONS_USE_RUNTEST) + if(BOUT_TEST_OPTIONS_PYTHON_TEST_FILE) + # It's an integrated test with a specific python file + add_test(NAME ${TESTNAME} + COMMAND pytest ${BOUT_TEST_OPTIONS_PYTHON_TEST_FILE} + ${BOUT_TEST_OPTIONS_TESTARGS} ) - bout_copy_file(runtest) + else() + # It's an MMS test still using the 'runtest' script + add_test(NAME ${TESTNAME} COMMAND ./runtest ${BOUT_TEST_OPTIONS_TESTARGS}) + endif() + + set_tests_properties( + ${TESTNAME} PROPERTIES ENVIRONMENT + PYTHONPATH=${BOUT_PYTHONPATH}:$ENV{PYTHONPATH} + ) else() add_test(NAME ${TESTNAME} COMMAND ${TESTNAME} ${BOUT_TEST_OPTIONS_TESTARGS}) endif() - set_tests_properties(${TESTNAME} PROPERTIES - PROCESSORS ${BOUT_TEST_OPTIONS_PROCESSORS} - PROCESSOR_AFFINITY ON - ) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/runtest) + bout_copy_file(runtest) + endif() + + set_tests_properties( + ${TESTNAME} PROPERTIES PROCESSORS ${BOUT_TEST_OPTIONS_PROCESSORS} + PROCESSOR_AFFINITY ON + ) # Copy the input file if needed - if (BOUT_TEST_OPTIONS_USE_DATA_BOUT_INP) + if(BOUT_TEST_OPTIONS_USE_DATA_BOUT_INP) bout_copy_file(data/BOUT.inp) endif() # Copy any other needed files - if (BOUT_TEST_OPTIONS_EXTRA_FILES) - foreach (FILE ${BOUT_TEST_OPTIONS_EXTRA_FILES}) + if(BOUT_TEST_OPTIONS_EXTRA_FILES) + foreach(FILE ${BOUT_TEST_OPTIONS_EXTRA_FILES}) bout_copy_file("${FILE}") endforeach() endif() @@ -243,9 +301,23 @@ endfunction() # Add a new integrated test. See `bout_add_integrated_or_mms_test` for arguments function(bout_add_integrated_test TESTNAME) - bout_add_integrated_or_mms_test(build-check-integrated-tests ${TESTNAME} ${ARGV}) -endfunction() + # Construct the Python test filename + string(REGEX REPLACE "^(test-)?(.+)$" "test_\\2.py" TEST_FILENAME + "${TESTNAME}" + ) + string(REPLACE "-" "_" TEST_FILENAME "${TEST_FILENAME}") + string(REPLACE "test_test_" "test_" TEST_FILENAME "${TEST_FILENAME}") + bout_add_integrated_or_mms_test( + build-check-integrated-tests ${TESTNAME} PYTHON_TEST_FILE ${TEST_FILENAME} + ${ARGV} + ) + + # Only copy the file if the test wasn't skipped due to missing requirements + if(TARGET ${TESTNAME}) + bout_copy_file(${TEST_FILENAME}) + endif() +endfunction() # Add a new MMS test. See `bout_add_integrated_or_mms_test` for arguments function(bout_add_mms_test TESTNAME) bout_add_integrated_or_mms_test(build-check-mms-tests ${TESTNAME} ${ARGV}) @@ -256,13 +328,18 @@ endfunction() # Taken from https://github.com/conan-io/conan/issues/2125#issuecomment-351176653 function(bout_add_library_alias dst src) add_library(${dst} INTERFACE IMPORTED) - foreach(name INTERFACE_LINK_LIBRARIES INTERFACE_INCLUDE_DIRECTORIES INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_OPTIONS) - get_property(value TARGET ${src} PROPERTY ${name} ) + foreach(name INTERFACE_LINK_LIBRARIES INTERFACE_INCLUDE_DIRECTORIES + INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_OPTIONS + ) + get_property( + value + TARGET ${src} + PROPERTY ${name} + ) set_property(TARGET ${dst} PROPERTY ${name} ${value}) endforeach() endfunction() - # Call nx-config with an argument, and append the resulting path to a list # Taken from https://github.com/LiamBindle/geos-chem/blob/feature/CMake/CMakeScripts/FindNetCDF.cmake function(bout_inspect_netcdf_config VAR NX_CONFIG ARG) @@ -271,7 +348,10 @@ function(bout_inspect_netcdf_config VAR NX_CONFIG ARG) OUTPUT_VARIABLE NX_CONFIG_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ) - if (NX_CONFIG_OUTPUT) - set(${VAR} ${NX_CONFIG_OUTPUT} PARENT_SCOPE) + if(NX_CONFIG_OUTPUT) + set(${VAR} + ${NX_CONFIG_OUTPUT} + PARENT_SCOPE + ) endif() endfunction() diff --git a/cmake/BuildType.cmake b/cmake/BuildType.cmake index c4dd7ff73d..7aced6d8ad 100644 --- a/cmake/BuildType.cmake +++ b/cmake/BuildType.cmake @@ -12,10 +12,17 @@ set(default_build_type "RelWithDebInfo") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to '${default_build_type}' as none was specified.") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE - STRING "Choose the type of build." FORCE) + message( + STATUS + "Setting build type to '${default_build_type}' as none was specified." + ) + set(CMAKE_BUILD_TYPE + "${default_build_type}" + CACHE STRING "Choose the type of build." FORCE + ) # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") + set_property( + CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" + "RelWithDebInfo" + ) endif() diff --git a/cmake/CorrectWindowsPaths.cmake b/cmake/CorrectWindowsPaths.cmake index 09bcdd67dc..cd2ac529ca 100644 --- a/cmake/CorrectWindowsPaths.cmake +++ b/cmake/CorrectWindowsPaths.cmake @@ -4,11 +4,9 @@ # This uses the command cygpath (provided by cygwin) to convert # unix-style paths into paths useable by cmake on windows -macro (CONVERT_CYGWIN_PATH _path) - if (WIN32) - EXECUTE_PROCESS(COMMAND cygpath.exe -m ${${_path}} - OUTPUT_VARIABLE ${_path}) - string (STRIP ${${_path}} ${_path}) - endif (WIN32) -endmacro (CONVERT_CYGWIN_PATH) - +macro(CONVERT_CYGWIN_PATH _path) + if(WIN32) + execute_process(COMMAND cygpath.exe -m ${${_path}} OUTPUT_VARIABLE ${_path}) + string(STRIP ${${_path}} ${_path}) + endif(WIN32) +endmacro(CONVERT_CYGWIN_PATH) diff --git a/cmake/EnableCXXWarningIfSupport.cmake b/cmake/EnableCXXWarningIfSupport.cmake index 6d7a64265f..9b9ae52af5 100644 --- a/cmake/EnableCXXWarningIfSupport.cmake +++ b/cmake/EnableCXXWarningIfSupport.cmake @@ -5,7 +5,7 @@ function(target_enable_cxx_warning_if_supported TARGET) set(multiValueArgs FLAGS) cmake_parse_arguments(TARGET_ENABLE_WARNING "" "" "${multiValueArgs}" ${ARGN}) - foreach (WARNING_FLAG IN LISTS TARGET_ENABLE_WARNING_FLAGS) + foreach(WARNING_FLAG IN LISTS TARGET_ENABLE_WARNING_FLAGS) string(REPLACE "-" "_" WARNING_FLAG_STRIPPED ${WARNING_FLAG}) # Note that gcc ignores unknown flags of the form "-Wno-warning" @@ -13,31 +13,33 @@ function(target_enable_cxx_warning_if_supported TARGET) # positive form as an additional flag which it will choke on (if # it doesn't exist). See: https://gcc.gnu.org/wiki/FAQ#wnowarning string(FIND ${WARNING_FLAG} "Wno-" NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED}) - if (NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED} EQUAL -1) + if(NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED} EQUAL -1) set(IS_NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED} FALSE) else() set(IS_NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED} TRUE) endif() - if (IS_NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED}) + if(IS_NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED}) set(ORIGINAL_FLAG ${WARNING_FLAG}) string(REPLACE "no-" "" WARNING_FLAG ${WARNING_FLAG}) message(STATUS "Found negative flag: ${ORIGINAL_FLAG}\n" - " replaced with ${WARNING_FLAG}") + " replaced with ${WARNING_FLAG}" + ) endif() check_cxx_compiler_flag(${WARNING_FLAG} HAS_FLAG_${WARNING_FLAG_STRIPPED}) - if (IS_NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED}) + if(IS_NEGATIVE_FLAG_${WARNING_FLAG_STRIPPED}) set(WARNING_FLAG ${ORIGINAL_FLAG}) endif() - if (HAS_FLAG_${WARNING_FLAG_STRIPPED}) - message(STATUS "Warning flag is supported by compiler: ${WARNING_FLAG}") + if(HAS_FLAG_${WARNING_FLAG_STRIPPED}) + message(STATUS "Warning flag is supported by compiler: ${WARNING_FLAG}") - target_compile_options(${TARGET} PRIVATE - $<$>:${WARNING_FLAG} > - $<$:-Xcompiler=${WARNING_FLAG} > + target_compile_options( + ${TARGET} + PRIVATE $<$>:${WARNING_FLAG} > + $<$:-Xcompiler=${WARNING_FLAG} > ) else() message(STATUS "Warning flag not supported by compiler: ${WARNING_FLAG}") diff --git a/cmake/FindBash.cmake b/cmake/FindBash.cmake index feb195f9f1..faa5303646 100644 --- a/cmake/FindBash.cmake +++ b/cmake/FindBash.cmake @@ -11,27 +11,30 @@ # Bash_VERSION - Bash version # Bash_EXECUTABLE - Path to bash executable -find_program(Bash_EXECUTABLE - bash - ) +find_program(Bash_EXECUTABLE bash) mark_as_advanced(Bash_EXECUTABLE) -if (Bash_EXECUTABLE) - execute_process(COMMAND "${Bash_EXECUTABLE}" --version +if(Bash_EXECUTABLE) + execute_process( + COMMAND "${Bash_EXECUTABLE}" --version RESULT_VARIABLE _bash_runs OUTPUT_VARIABLE _bash_stdout OUTPUT_STRIP_TRAILING_WHITESPACE - ) + ) if(_bash_stdout MATCHES "version ([0-9]+\\.[0-9]+\\.[0-9]+)") set(Bash_VERSION "${CMAKE_MATCH_1}") else() - message (WARNING "Failed to determine version of Bash interpreter (${Bash_EXECUTABLE})! Error:\n${_Bash_STDERR}") + message( + WARNING + "Failed to determine version of Bash interpreter (${Bash_EXECUTABLE})! Error:\n${_Bash_STDERR}" + ) endif() endif() include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Bash +find_package_handle_standard_args( + Bash VERSION_VAR Bash_VERSION REQUIRED_VARS Bash_EXECUTABLE - ) +) diff --git a/cmake/FindClangFormat.cmake b/cmake/FindClangFormat.cmake index c940002c3b..cd5ca5865b 100644 --- a/cmake/FindClangFormat.cmake +++ b/cmake/FindClangFormat.cmake @@ -3,27 +3,23 @@ # Taken from https://github.com/ttroy50/cmake-examples commit 64bd54a # This file is under MIT Licence -if (NOT ClangFormat_BIN_NAME) +if(NOT ClangFormat_BIN_NAME) set(ClangFormat_BIN_NAME clang-format) endif() # if custom path check there first -if (ClangFormat_ROOT_DIR) - find_program(ClangFormat_BIN - NAMES - ${ClangFormat_BIN_NAME} - PATHS - "${ClangFormat_ROOT_DIR}" - NO_DEFAULT_PATH) +if(ClangFormat_ROOT_DIR) + find_program( + ClangFormat_BIN + NAMES ${ClangFormat_BIN_NAME} + PATHS "${ClangFormat_ROOT_DIR}" + NO_DEFAULT_PATH + ) endif() find_program(ClangFormat_BIN NAMES ${ClangFormat_BIN_NAME}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - ClangFormat - DEFAULT_MSG - ClangFormat_BIN) +find_package_handle_standard_args(ClangFormat DEFAULT_MSG ClangFormat_BIN) -mark_as_advanced( - ClangFormat_BIN) +mark_as_advanced(ClangFormat_BIN) diff --git a/cmake/FindCython.cmake b/cmake/FindCython.cmake index 3b98cde89e..5a58cf4335 100644 --- a/cmake/FindCython.cmake +++ b/cmake/FindCython.cmake @@ -10,20 +10,22 @@ # CYTHON_FOUND - true if Cython was found # CYTHON_VERSION - Cython version -execute_process(COMMAND ${Python3_EXECUTABLE} -c "import cython ; print(cython.__version__)" +execute_process( + COMMAND ${Python3_EXECUTABLE} -c "import cython ; print(cython.__version__)" RESULT_VARIABLE _cython_runs OUTPUT_VARIABLE CYTHON_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE - ) +) -if (${_cython_runs} EQUAL 0) +if(${_cython_runs} EQUAL 0) set(CYTHON_RUNS TRUE) else() set(CYTHON_RUNS FALSE) endif() include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Cython +find_package_handle_standard_args( + Cython VERSION_VAR CYTHON_VERSION REQUIRED_VARS CYTHON_RUNS - ) +) diff --git a/cmake/FindFFTW.cmake b/cmake/FindFFTW.cmake index e1940c687d..7ca5518a6f 100644 --- a/cmake/FindFFTW.cmake +++ b/cmake/FindFFTW.cmake @@ -24,72 +24,78 @@ # ``FFTW_DEBUG`` # Set to TRUE to get extra debugging output -if (FFTW_INCLUDE_DIRS) +if(FFTW_INCLUDE_DIRS) # Already in cache, be silent - set (FFTW_FIND_QUIETLY TRUE) -endif (FFTW_INCLUDE_DIRS) + set(FFTW_FIND_QUIETLY TRUE) +endif(FFTW_INCLUDE_DIRS) -if (EXISTS ${FFTW_ROOT}) +if(EXISTS ${FFTW_ROOT}) # Make sure FFTW_ROOT is an absolute path by setting it as a 'FILEPATH' - set (FFTW_ROOT "" CACHE FILEPATH "Location of the FFTW library") + set(FFTW_ROOT + "" + CACHE FILEPATH "Location of the FFTW library" + ) endif() -find_program(FFTW_WISDOM "fftw-wisdom" +find_program( + FFTW_WISDOM "fftw-wisdom" PATHS "${FFTW_ROOT}" PATH_SUFFIXES bin NO_DEFAULT_PATH DOC "Path to fftw-wisdom executable" - ) +) -find_program(FFTW_WISDOM "fftw-wisdom" - DOC "Path to fftw-wisdom executable" - ) -if (FFTW_DEBUG) +find_program(FFTW_WISDOM "fftw-wisdom" DOC "Path to fftw-wisdom executable") +if(FFTW_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " FFTW_WISDOM = ${FFTW_WISDOM}" - ) + " FFTW_WISDOM = ${FFTW_WISDOM}" + ) endif() get_filename_component(FFTW_WISDOM_TMP "${FFTW_WISDOM}" DIRECTORY) get_filename_component(FFTW_HINT_DIR "${FFTW_WISDOM_TMP}" DIRECTORY) -find_path(FFTW_INCLUDE_DIRS +find_path( + FFTW_INCLUDE_DIRS NAMES fftw3.h DOC "FFTW include directory" HINTS "${FFTW_HINT_DIR}" PATH_SUFFIXES "include" - ) -if (FFTW_DEBUG) +) +if(FFTW_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " FFTW_INCLUDE_DIRS = ${FFTW_INCLUDE_DIRS}" - " FFTW_HINT_DIR = ${FFTW_HINT_DIR}" - ) + " FFTW_INCLUDE_DIRS = ${FFTW_INCLUDE_DIRS}" + " FFTW_HINT_DIR = ${FFTW_HINT_DIR}" + ) endif() -find_library (FFTW_LIBRARIES +find_library( + FFTW_LIBRARIES NAMES fftw3 DOC "FFTW library location" HINTS "${FFTW_HINT_DIR}" PATH_SUFFIXES "lib" "lib64" - ) -if (FFTW_DEBUG) +) +if(FFTW_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " FFTW_LIBRARIES = ${FFTW_LIBRARIES}" - " FFTW_HINT_DIR = ${FFTW_HINT_DIR}" - ) + " FFTW_LIBRARIES = ${FFTW_LIBRARIES}" + " FFTW_HINT_DIR = ${FFTW_HINT_DIR}" + ) endif() # handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if # all listed variables are TRUE -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args (FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDE_DIRS) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDE_DIRS +) -mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDE_DIRS) +mark_as_advanced(FFTW_LIBRARIES FFTW_INCLUDE_DIRS) -if (FFTW_FOUND AND NOT TARGET FFTW::FFTW) +if(FFTW_FOUND AND NOT TARGET FFTW::FFTW) add_library(FFTW::FFTW UNKNOWN IMPORTED) - set_target_properties(FFTW::FFTW PROPERTIES - IMPORTED_LOCATION "${FFTW_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - ) + set_target_properties( + FFTW::FFTW PROPERTIES IMPORTED_LOCATION "${FFTW_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + ) endif() diff --git a/cmake/FindHYPRE.cmake b/cmake/FindHYPRE.cmake index 1b9a5ca6f9..d2a1b4746c 100644 --- a/cmake/FindHYPRE.cmake +++ b/cmake/FindHYPRE.cmake @@ -6,54 +6,62 @@ include(FindPackageHandleStandardArgs) find_package(HYPRE CONFIG QUIET) -if (HYPRE_FOUND) +if(HYPRE_FOUND) message(STATUS "Found HYPRE: ${HYPRE_VERSION}") return() endif() -find_path(HYPRE_INCLUDE_DIR +find_path( + HYPRE_INCLUDE_DIR NAMES HYPRE.h - DOC "HYPRE include directories" - REQUIRED + DOC "HYPRE include directories" REQUIRED PATH_SUFFIXES include include/hypre ) -find_library(HYPRE_LIBRARY +find_library( + HYPRE_LIBRARY NAMES HYPRE - DOC "HYPRE library" - REQUIRED + DOC "HYPRE library" REQUIRED PATH_SUFFIXES lib64 lib - ) +) -if (HYPRE_INCLUDE_DIR) +if(HYPRE_INCLUDE_DIR) file(READ "${HYPRE_INCLUDE_DIR}/HYPRE_config.h" HYPRE_CONFIG_FILE) - string(REGEX MATCH ".*#define HYPRE_RELEASE_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*" - _ "${HYPRE_CONFIG_FILE}") + string( + REGEX MATCH + ".*#define HYPRE_RELEASE_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*" + _ "${HYPRE_CONFIG_FILE}" + ) set(HYPRE_VERSION_MAJOR ${CMAKE_MATCH_1}) set(HYPRE_VERSION_MINOR ${CMAKE_MATCH_2}) set(HYPRE_VERSION_PATCH ${CMAKE_MATCH_3}) - set(HYPRE_VERSION "${HYPRE_VERSION_MAJOR}.${HYPRE_VERSION_MINOR}.${HYPRE_VERSION_PATCH}") + set(HYPRE_VERSION + "${HYPRE_VERSION_MAJOR}.${HYPRE_VERSION_MINOR}.${HYPRE_VERSION_PATCH}" + ) endif() -if (HYPRE_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ]" - " HYPRE_ROOT = ${HYPRE_ROOT}" - " HYPRE_INCLUDE_DIR = ${HYPRE_INCLUDE_DIR}" - " HYPRE_LIBRARY = ${HYPRE_LIBRARY}" - ) +if(HYPRE_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ]" + " HYPRE_ROOT = ${HYPRE_ROOT}" + " HYPRE_INCLUDE_DIR = ${HYPRE_INCLUDE_DIR}" + " HYPRE_LIBRARY = ${HYPRE_LIBRARY}" + ) endif() mark_as_advanced(HYPRE_INCLUDE_DIR HYPRE_LIBRARY) -find_package_handle_standard_args(HYPRE +find_package_handle_standard_args( + HYPRE REQUIRED_VARS HYPRE_LIBRARY HYPRE_INCLUDE_DIR VERSION_VAR HYPRE_VERSION - ) +) -if (HYPRE_FOUND AND NOT TARGET HYPRE::HYPRE) +if(HYPRE_FOUND AND NOT TARGET HYPRE::HYPRE) add_library(HYPRE::HYPRE UNKNOWN IMPORTED) - set_target_properties(HYPRE::HYPRE PROPERTIES - IMPORTED_LOCATION "${HYPRE_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${HYPRE_INCLUDE_DIR}" - ) + set_target_properties( + HYPRE::HYPRE + PROPERTIES IMPORTED_LOCATION "${HYPRE_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${HYPRE_INCLUDE_DIR}" + ) endif() diff --git a/cmake/FindLibuuid.cmake b/cmake/FindLibuuid.cmake index 91880487a2..2492388b32 100644 --- a/cmake/FindLibuuid.cmake +++ b/cmake/FindLibuuid.cmake @@ -21,38 +21,41 @@ # ``Libuuid_DEBUG`` # Set to TRUE to get extra debugging output -include (FindPackageHandleStandardArgs) +include(FindPackageHandleStandardArgs) -if (WIN32) +if(WIN32) find_package_handle_standard_args(Libuuid DEFAULT_MSG) return() endif() -if (APPLE) +if(APPLE) find_library(CFLIB CoreFoundation) find_package_handle_standard_args(Libuuid DEFAULT_MSG CFLIB) mark_as_advanced(${CFLIB}) - if (Libuuid_FOUND AND NOT TARGET Libuuid::libuuid) + if(Libuuid_FOUND AND NOT TARGET Libuuid::libuuid) add_library(Libuuid::libuuid UNKNOWN IMPORTED) - set_target_properties(Libuuid::libuuid PROPERTIES - IMPORTED_LOCATION ${CFLIB} - ) + set_target_properties( + Libuuid::libuuid PROPERTIES IMPORTED_LOCATION ${CFLIB} + ) endif() return() -endif () +endif() find_path(Libuuid_INCLUDE_DIRS uuid/uuid.h) find_library(Libuuid_LIBRARIES uuid) -find_package_handle_standard_args(Libuuid DEFAULT_MSG Libuuid_LIBRARIES Libuuid_INCLUDE_DIRS) +find_package_handle_standard_args( + Libuuid DEFAULT_MSG Libuuid_LIBRARIES Libuuid_INCLUDE_DIRS +) mark_as_advanced(Libuuid_LIBRARIES Libuuid_INCLUDE_DIRS) -if (Libuuid_FOUND AND NOT TARGET Libuuid::libuuid) +if(Libuuid_FOUND AND NOT TARGET Libuuid::libuuid) add_library(Libuuid::libuuid UNKNOWN IMPORTED) - set_target_properties(Libuuid::libuuid PROPERTIES - IMPORTED_LOCATION "${Libuuid_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${Libuuid_INCLUDE_DIRS}" - ) + set_target_properties( + Libuuid::libuuid + PROPERTIES IMPORTED_LOCATION "${Libuuid_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${Libuuid_INCLUDE_DIRS}" + ) endif() diff --git a/cmake/FindNumpy.cmake b/cmake/FindNumpy.cmake index b6de6e3e35..cfdbdcc96c 100644 --- a/cmake/FindNumpy.cmake +++ b/cmake/FindNumpy.cmake @@ -11,46 +11,57 @@ # Numpy_VERSION # Numpy_INCLUDE_DIR - find_package(Python3 3.6 COMPONENTS Interpreter Development) -if (NOT Python3_FOUND) - message(STATUS "Could not find numpy as python was not found. Maybe the developement package is missing?") +if(NOT Python3_FOUND) + message( + STATUS + "Could not find numpy as python was not found. Maybe the developement package is missing?" + ) set(Numpy_FOUND ${Python3_FOUND}) return() endif() -if (NOT Numpy_FOUND) - execute_process(COMMAND ${Python3_EXECUTABLE} -c "import numpy ; print(numpy.__version__)" +if(NOT Numpy_FOUND) + execute_process( + COMMAND ${Python3_EXECUTABLE} -c "import numpy ; print(numpy.__version__)" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE Numpy_VERSION - ) - execute_process(COMMAND ${Python3_EXECUTABLE} -c "import numpy ; print(numpy.get_include())" + ) + execute_process( + COMMAND ${Python3_EXECUTABLE} -c "import numpy ; print(numpy.get_include())" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _numpy_include_dirs - ) + ) endif() -if (Numpy_DEBUG) - message(STATUS "Looking for numpy headers in: ${_numpy_include_dirs} ${Python3_INCLUDE_DIRS}") +if(Numpy_DEBUG) + message( + STATUS + "Looking for numpy headers in: ${_numpy_include_dirs} ${Python3_INCLUDE_DIRS}" + ) endif() -find_path(Numpy_INCLUDE_DIR - numpy/arrayobject.h +find_path( + Numpy_INCLUDE_DIR numpy/arrayobject.h PATHS "${_numpy_include_dirs}" "${Python3_INCLUDE_DIRS}" PATH_SUFFIXES numpy/core/include - ) +) -if (NOT Numpy_INCLUDE_DIR) - message(STATUS "Numpy headers not found -- do you need to install the development package?") +if(NOT Numpy_INCLUDE_DIR) + message( + STATUS + "Numpy headers not found -- do you need to install the development package?" + ) endif() set(Numpy_INCLUDE_DIRS ${Numpy_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Numpy +find_package_handle_standard_args( + Numpy VERSION_VAR Numpy_VERSION REQUIRED_VARS Numpy_INCLUDE_DIR - ) +) mark_as_advanced(Numpy_INCLUDE_DIR) diff --git a/cmake/FindPETSc.cmake b/cmake/FindPETSc.cmake index c93d464673..f0595a7a68 100644 --- a/cmake/FindPETSc.cmake +++ b/cmake/FindPETSc.cmake @@ -25,23 +25,23 @@ find_package(MPI REQUIRED) -set(PETSC_VALID_COMPONENTS - C - CXX) +set(PETSC_VALID_COMPONENTS C CXX) if(NOT PETSc_FIND_COMPONENTS) - get_property (_enabled_langs GLOBAL PROPERTY ENABLED_LANGUAGES) - if ("C" IN_LIST _enabled_langs) + get_property(_enabled_langs GLOBAL PROPERTY ENABLED_LANGUAGES) + if("C" IN_LIST _enabled_langs) set(PETSC_LANGUAGE_BINDINGS "C") - else () + else() set(PETSC_LANGUAGE_BINDINGS "CXX") - endif () + endif() else() # Right now, this is designed for compatability with the --with-clanguage option, so # only allow one item in the components list. list(LENGTH ${PETSc_FIND_COMPONENTS} components_length) if(${components_length} GREATER 1) - message(FATAL_ERROR "Only one component for PETSc is allowed to be specified") + message( + FATAL_ERROR "Only one component for PETSc is allowed to be specified" + ) endif() # This is a stub for allowing multiple components should that time ever come. Perhaps # to also test Fortran bindings? @@ -61,218 +61,328 @@ if(NOT PETSC_DIR) endif() endif() -function (petsc_get_version) - if (EXISTS "${PETSC_DIR}/include/petscversion.h") - file (STRINGS "${PETSC_DIR}/include/petscversion.h" vstrings REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) ") - foreach (line ${vstrings}) - string (REGEX REPLACE " +" ";" fields ${line}) # break line into three fields (the first is always "#define") - list (GET fields 1 var) - list (GET fields 2 val) - set (${var} ${val} PARENT_SCOPE) - set (${var} ${val}) # Also in local scope so we have access below - endforeach () - if (PETSC_VERSION_RELEASE) - if ($(PETSC_VERSION_PATCH) GREATER 0) - set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" CACHE INTERNAL "PETSc version") - else () - set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}" CACHE INTERNAL "PETSc version") - endif () - else () +function(petsc_get_version) + if(EXISTS "${PETSC_DIR}/include/petscversion.h") + file(STRINGS "${PETSC_DIR}/include/petscversion.h" vstrings + REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) " + ) + foreach(line ${vstrings}) + string(REGEX REPLACE " +" ";" fields ${line} + )# break line into three fields (the first is always "#define") + list(GET fields 1 var) + list(GET fields 2 val) + set(${var} + ${val} + PARENT_SCOPE + ) + set(${var} ${val}) # Also in local scope so we have access below + endforeach() + if(PETSC_VERSION_RELEASE) + if($(PETSC_VERSION_PATCH) GREATER 0) + set(PETSC_VERSION + "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" + CACHE INTERNAL "PETSc version" + ) + else() + set(PETSC_VERSION + "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}" + CACHE INTERNAL "PETSc version" + ) + endif() + else() # make dev version compare higher than any patch level of a released version - set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" CACHE INTERNAL "PETSc version") - endif () - else () - message (SEND_ERROR "PETSC_DIR can not be used, ${PETSC_DIR}/include/petscversion.h does not exist") - endif () -endfunction () + set(PETSC_VERSION + "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" + CACHE INTERNAL "PETSc version" + ) + endif() + else() + message( + SEND_ERROR + "PETSC_DIR can not be used, ${PETSC_DIR}/include/petscversion.h does not exist" + ) + endif() +endfunction() # Debian uses versioned paths e.g /usr/lib/petscdir/3.5/ -file (GLOB DEB_PATHS "/usr/lib/petscdir/*") +file(GLOB DEB_PATHS "/usr/lib/petscdir/*") -find_path (PETSC_DIR include/petsc.h +find_path( + PETSC_DIR include/petsc.h HINTS ENV PETSC_DIR - PATHS - /usr/lib/petsc - # Debian paths - ${DEB_PATHS} - # Arch Linux path - /opt/petsc/linux-c-opt - # MacPorts path - /opt/local/lib/petsc - $ENV{HOME}/petsc - DOC "PETSc Directory") - -find_program (MAKE_EXECUTABLE NAMES make gmake) - -if (PETSC_DIR AND NOT PETSC_ARCH) - set (_petsc_arches - $ENV{PETSC_ARCH} # If set, use environment variable first - linux-gnu-c-debug linux-gnu-c-opt # Debian defaults - x86_64-unknown-linux-gnu i386-unknown-linux-gnu) - set (petscconf "NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - foreach (arch ${_petsc_arches}) - if (NOT PETSC_ARCH) - find_path (petscconf petscconf.h + PATHS /usr/lib/petsc + # Debian paths + ${DEB_PATHS} + # Arch Linux path + /opt/petsc/linux-c-opt + # MacPorts path + /opt/local/lib/petsc + $ENV{HOME}/petsc + DOC "PETSc Directory" +) + +find_program(MAKE_EXECUTABLE NAMES make gmake) + +if(PETSC_DIR AND NOT PETSC_ARCH) + set(_petsc_arches + $ENV{PETSC_ARCH} # If set, use environment variable first + linux-gnu-c-debug linux-gnu-c-opt # Debian defaults + x86_64-unknown-linux-gnu i386-unknown-linux-gnu + ) + set(petscconf + "NOTFOUND" + CACHE FILEPATH "Cleared" FORCE + ) + foreach(arch ${_petsc_arches}) + if(NOT PETSC_ARCH) + find_path( + petscconf petscconf.h HINTS ${PETSC_DIR} PATH_SUFFIXES ${arch}/include bmake/${arch} - NO_DEFAULT_PATH) - if (petscconf) - set (PETSC_ARCH "${arch}" CACHE STRING "PETSc build architecture") - endif (petscconf) - endif (NOT PETSC_ARCH) - endforeach (arch) - set (petscconf "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE) -endif (PETSC_DIR AND NOT PETSC_ARCH) - -set (petsc_slaves LIBRARIES_SYS LIBRARIES_VEC LIBRARIES_MAT LIBRARIES_DM LIBRARIES_KSP LIBRARIES_SNES LIBRARIES_TS - INCLUDE_DIR INCLUDE_CONF) -include (FindPackageMultipass) -find_package_multipass (PETSc petsc_config_current - STATES DIR ARCH - DEPENDENTS INCLUDES LIBRARIES COMPILER MPIEXEC ${petsc_slaves}) + NO_DEFAULT_PATH + ) + if(petscconf) + set(PETSC_ARCH + "${arch}" + CACHE STRING "PETSc build architecture" + ) + endif(petscconf) + endif(NOT PETSC_ARCH) + endforeach(arch) + set(petscconf + "NOTFOUND" + CACHE INTERNAL "Scratch variable" FORCE + ) +endif(PETSC_DIR AND NOT PETSC_ARCH) + +set(petsc_slaves + LIBRARIES_SYS + LIBRARIES_VEC + LIBRARIES_MAT + LIBRARIES_DM + LIBRARIES_KSP + LIBRARIES_SNES + LIBRARIES_TS + INCLUDE_DIR + INCLUDE_CONF +) +include(FindPackageMultipass) +find_package_multipass( + PETSc + petsc_config_current + STATES + DIR + ARCH + DEPENDENTS + INCLUDES + LIBRARIES + COMPILER + MPIEXEC + ${petsc_slaves} +) # Determine whether the PETSc layout is old-style (through 2.3.3) or # new-style (>= 3.0.0) -if (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/lib/petsc/conf/petscvariables") # > 3.5 - set (petsc_conf_rules "${PETSC_DIR}/lib/petsc/conf/rules") - set (petsc_conf_variables "${PETSC_DIR}/lib/petsc/conf/variables") -elseif (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscconf.h") # > 2.3.3 - set (petsc_conf_rules "${PETSC_DIR}/conf/rules") - set (petsc_conf_variables "${PETSC_DIR}/conf/variables") -elseif (EXISTS "${PETSC_DIR}/bmake/${PETSC_ARCH}/petscconf.h") # <= 2.3.3 - set (petsc_conf_rules "${PETSC_DIR}/bmake/common/rules") - set (petsc_conf_variables "${PETSC_DIR}/bmake/common/variables") -elseif (PETSC_DIR) - message (SEND_ERROR "The pair PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} do not specify a valid PETSc installation") -endif () - -if (petsc_conf_rules AND petsc_conf_variables AND NOT petsc_config_current) +if(EXISTS "${PETSC_DIR}/${PETSC_ARCH}/lib/petsc/conf/petscvariables") # > 3.5 + set(petsc_conf_rules "${PETSC_DIR}/lib/petsc/conf/rules") + set(petsc_conf_variables "${PETSC_DIR}/lib/petsc/conf/variables") +elseif(EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscconf.h") # > 2.3.3 + set(petsc_conf_rules "${PETSC_DIR}/conf/rules") + set(petsc_conf_variables "${PETSC_DIR}/conf/variables") +elseif(EXISTS "${PETSC_DIR}/bmake/${PETSC_ARCH}/petscconf.h") # <= 2.3.3 + set(petsc_conf_rules "${PETSC_DIR}/bmake/common/rules") + set(petsc_conf_variables "${PETSC_DIR}/bmake/common/variables") +elseif(PETSC_DIR) + message( + SEND_ERROR + "The pair PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} do not specify a valid PETSc installation" + ) +endif() + +if(petsc_conf_rules + AND petsc_conf_variables + AND NOT petsc_config_current +) petsc_get_version() # Put variables into environment since they are needed to get # configuration (petscvariables) in the PETSc makefile - set (ENV{PETSC_DIR} "${PETSC_DIR}") - set (ENV{PETSC_ARCH} "${PETSC_ARCH}") + set(ENV{PETSC_DIR} "${PETSC_DIR}") + set(ENV{PETSC_ARCH} "${PETSC_ARCH}") # A temporary makefile to probe the PETSc configuration - set (petsc_config_makefile "${PROJECT_BINARY_DIR}/Makefile.petsc") - file (WRITE "${petsc_config_makefile}" -"## This file was autogenerated by FindPETSc.cmake + set(petsc_config_makefile "${PROJECT_BINARY_DIR}/Makefile.petsc") + file( + WRITE "${petsc_config_makefile}" + "## This file was autogenerated by FindPETSc.cmake # PETSC_DIR = ${PETSC_DIR} # PETSC_ARCH = ${PETSC_ARCH} include ${petsc_conf_rules} include ${petsc_conf_variables} show : \t-@echo -n \${\${VARIABLE}} -") - - macro (PETSC_GET_VARIABLE name var) - set (${var} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) - execute_process (COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f ${petsc_config_makefile} show VARIABLE=${name} +" + ) + + macro(PETSC_GET_VARIABLE name var) + set(${var} + "NOTFOUND" + CACHE INTERNAL "Cleared" FORCE + ) + execute_process( + COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f + ${petsc_config_makefile} show VARIABLE=${name} OUTPUT_VARIABLE ${var} - RESULT_VARIABLE petsc_return) - endmacro (PETSC_GET_VARIABLE) - petsc_get_variable (PETSC_LIB_DIR petsc_lib_dir) - petsc_get_variable (PETSC_EXTERNAL_LIB_BASIC petsc_libs_external) - petsc_get_variable (PETSC_CCPPFLAGS petsc_cpp_line) - petsc_get_variable (PETSC_INCLUDE petsc_include) - petsc_get_variable (PCC petsc_cc) - petsc_get_variable (PCC_FLAGS petsc_cc_flags) - petsc_get_variable (MPIEXEC petsc_mpiexec) + RESULT_VARIABLE petsc_return + ) + endmacro(PETSC_GET_VARIABLE) + petsc_get_variable(PETSC_LIB_DIR petsc_lib_dir) + petsc_get_variable(PETSC_EXTERNAL_LIB_BASIC petsc_libs_external) + petsc_get_variable(PETSC_CCPPFLAGS petsc_cpp_line) + petsc_get_variable(PETSC_INCLUDE petsc_include) + petsc_get_variable(PCC petsc_cc) + petsc_get_variable(PCC_FLAGS petsc_cc_flags) + petsc_get_variable(MPIEXEC petsc_mpiexec) # We are done with the temporary Makefile, calling PETSC_GET_VARIABLE after this point is invalid! - file (REMOVE ${petsc_config_makefile}) + file(REMOVE ${petsc_config_makefile}) - include (ResolveCompilerPaths) + include(ResolveCompilerPaths) # Extract include paths and libraries from compile command line - resolve_includes (petsc_includes_all "${petsc_cpp_line}") + resolve_includes(petsc_includes_all "${petsc_cpp_line}") #on windows we need to make sure we're linking against the right #runtime library - if (WIN32) - if (petsc_cc_flags MATCHES "-MT") + if(WIN32) + if(petsc_cc_flags MATCHES "-MT") set(using_md False) - foreach(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + foreach( + flag_var + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO + ) if(${flag_var} MATCHES "/MD") set(using_md True) endif(${flag_var} MATCHES "/MD") endforeach(flag_var) if(${using_md} MATCHES "True") - message(WARNING "PETSc was built with /MT, but /MD is currently set. - See http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F") + message( + WARNING + "PETSc was built with /MT, but /MD is currently set. + See http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F" + ) endif(${using_md} MATCHES "True") - endif (petsc_cc_flags MATCHES "-MT") - endif (WIN32) + endif(petsc_cc_flags MATCHES "-MT") + endif(WIN32) - include (CorrectWindowsPaths) + include(CorrectWindowsPaths) convert_cygwin_path(petsc_lib_dir) - message (STATUS "petsc_lib_dir ${petsc_lib_dir}") - - macro (PETSC_FIND_LIBRARY suffix name) - set (PETSC_LIBRARY_${suffix} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # Clear any stale value, if we got here, we need to find it again - if (WIN32) - set (libname lib${name}) #windows expects "libfoo", linux expects "foo" - else (WIN32) - set (libname ${name}) - endif (WIN32) - find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} HINTS ${petsc_lib_dir} NO_DEFAULT_PATH) - set (PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}") - mark_as_advanced (PETSC_LIBRARY_${suffix}) - endmacro (PETSC_FIND_LIBRARY suffix name) + message(STATUS "petsc_lib_dir ${petsc_lib_dir}") + + macro(PETSC_FIND_LIBRARY suffix name) + set(PETSC_LIBRARY_${suffix} + "NOTFOUND" + CACHE INTERNAL "Cleared" FORCE + ) # Clear any stale value, if we got here, we need to find it again + if(WIN32) + set(libname lib${name}) #windows expects "libfoo", linux expects "foo" + else(WIN32) + set(libname ${name}) + endif(WIN32) + find_library( + PETSC_LIBRARY_${suffix} + NAMES ${libname} + HINTS ${petsc_lib_dir} + NO_DEFAULT_PATH + ) + set(PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}") + mark_as_advanced(PETSC_LIBRARY_${suffix}) + endmacro( + PETSC_FIND_LIBRARY + suffix + name + ) # Look for petscvec first, if it doesn't exist, we must be using single-library - petsc_find_library (VEC petscvec) - if (PETSC_LIBRARY_VEC) - petsc_find_library (SYS "petscsys;petsc") # libpetscsys is called libpetsc prior to 3.1 (when single-library was introduced) - petsc_find_library (MAT petscmat) - petsc_find_library (DM petscdm) - petsc_find_library (KSP petscksp) - petsc_find_library (SNES petscsnes) - petsc_find_library (TS petscts) - macro (PETSC_JOIN libs deps) - list (APPEND PETSC_LIBRARIES_${libs} ${PETSC_LIBRARIES_${deps}}) - endmacro (PETSC_JOIN libs deps) - petsc_join (VEC SYS) - petsc_join (MAT VEC) - petsc_join (DM MAT) - petsc_join (KSP DM) - petsc_join (SNES KSP) - petsc_join (TS SNES) - petsc_join (ALL TS) - else () - set (PETSC_LIBRARY_VEC "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # There is no libpetscvec - petsc_find_library (SINGLE petsc) + petsc_find_library(VEC petscvec) + if(PETSC_LIBRARY_VEC) + petsc_find_library(SYS "petscsys;petsc") + # libpetscsys is called libpetsc prior to 3.1 (when single-library was introduced) + petsc_find_library(MAT petscmat) + petsc_find_library(DM petscdm) + petsc_find_library(KSP petscksp) + petsc_find_library(SNES petscsnes) + petsc_find_library(TS petscts) + macro(PETSC_JOIN libs deps) + list(APPEND PETSC_LIBRARIES_${libs} ${PETSC_LIBRARIES_${deps}}) + endmacro( + PETSC_JOIN + libs + deps + ) + petsc_join(VEC SYS) + petsc_join(MAT VEC) + petsc_join(DM MAT) + petsc_join(KSP DM) + petsc_join(SNES KSP) + petsc_join(TS SNES) + petsc_join(ALL TS) + else() + set(PETSC_LIBRARY_VEC + "NOTFOUND" + CACHE INTERNAL "Cleared" FORCE + ) # There is no libpetscvec + petsc_find_library(SINGLE petsc) # Debian 9/Ubuntu 16.04 uses _real and _complex extensions when using libraries in /usr/lib/petsc. - if (NOT PETSC_LIBRARY_SINGLE) - petsc_find_library (SINGLE petsc_real) + if(NOT PETSC_LIBRARY_SINGLE) + petsc_find_library(SINGLE petsc_real) endif() - if (NOT PETSC_LIBRARY_SINGLE) - petsc_find_library (SINGLE petsc_complex) + if(NOT PETSC_LIBRARY_SINGLE) + petsc_find_library(SINGLE petsc_complex) endif() - foreach (pkg SYS VEC MAT DM KSP SNES TS ALL) - set (PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}") - endforeach () - endif () - if (PETSC_LIBRARY_TS) - message (STATUS "Recognized PETSc install with separate libraries for each package") - else () - message (STATUS "Recognized PETSc install with single library for all packages") - endif () + foreach( + pkg + SYS + VEC + MAT + DM + KSP + SNES + TS + ALL + ) + set(PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}") + endforeach() + endif() + if(PETSC_LIBRARY_TS) + message( + STATUS "Recognized PETSc install with separate libraries for each package" + ) + else() + message( + STATUS "Recognized PETSc install with single library for all packages" + ) + endif() include(Check${PETSC_LANGUAGE_BINDINGS}SourceRuns) - macro (petsc_test_compiles includes libraries runs) - message(STATUS "PETSc test with : ${includes} ${libraries}" ) - if (PETSC_VERSION VERSION_GREATER 3.1) - set (_PETSC_TSDestroy "TSDestroy(&ts)") - else () - set (_PETSC_TSDestroy "TSDestroy(ts)") - endif () + macro(petsc_test_compiles includes libraries runs) + message(STATUS "PETSc test with : ${includes} ${libraries}") + if(PETSC_VERSION VERSION_GREATER 3.1) + set(_PETSC_TSDestroy "TSDestroy(&ts)") + else() + set(_PETSC_TSDestroy "TSDestroy(ts)") + endif() - set(_PETSC_TEST_SOURCE " + set(_PETSC_TEST_SOURCE + " static const char help[] = \"PETSc test program.\"; #include int main(int argc,char *argv[]) { @@ -286,116 +396,197 @@ int main(int argc,char *argv[]) { ierr = PetscFinalize();CHKERRQ(ierr); return 0; } -") - multipass_source_compiles ("${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}") - if (${${runs}}) - set (PETSC_EXECUTABLE_COMPILES "YES" CACHE BOOL - "Can the system successfully run a PETSc executable? This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build. If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." FORCE) - endif (${${runs}}) - endmacro () - +" + ) + multipass_source_compiles( + "${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} + "${PETSC_LANGUAGE_BINDINGS}" + ) + if(${${runs}}) + set(PETSC_EXECUTABLE_COMPILES + "YES" + CACHE + BOOL + "Can the system successfully run a PETSc executable? This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build. If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." + FORCE + ) + endif(${${runs}}) + endmacro() - find_path (PETSC_INCLUDE_DIR petscts.h + find_path( + PETSC_INCLUDE_DIR petscts.h HINTS "${PETSC_DIR}" PATH_SUFFIXES include - NO_DEFAULT_PATH) - find_path (PETSC_INCLUDE_CONF petscconf.h + NO_DEFAULT_PATH + ) + find_path( + PETSC_INCLUDE_CONF petscconf.h HINTS "${PETSC_DIR}" PATH_SUFFIXES "${PETSC_ARCH}/include" "bmake/${PETSC_ARCH}" - NO_DEFAULT_PATH) - mark_as_advanced (PETSC_INCLUDE_DIR PETSC_INCLUDE_CONF) - set (petsc_includes_minimal ${PETSC_INCLUDE_CONF} ${PETSC_INCLUDE_DIR}) - - file (STRINGS "${PETSC_INCLUDE_CONF}/petscconf.h" PETSC_HAS_OPENMP REGEX "#define PETSC_HAVE_OPENMP 1") - if (PETSC_HAS_OPENMP) + NO_DEFAULT_PATH + ) + mark_as_advanced(PETSC_INCLUDE_DIR PETSC_INCLUDE_CONF) + set(petsc_includes_minimal ${PETSC_INCLUDE_CONF} ${PETSC_INCLUDE_DIR}) + + file(STRINGS "${PETSC_INCLUDE_CONF}/petscconf.h" PETSC_HAS_OPENMP + REGEX "#define PETSC_HAVE_OPENMP 1" + ) + if(PETSC_HAS_OPENMP) find_package(OpenMP REQUIRED) - set (petsc_openmp_library ";OpenMP::OpenMP_${PETSC_LANGUAGE_BINDINGS}") + set(petsc_openmp_library ";OpenMP::OpenMP_${PETSC_LANGUAGE_BINDINGS}") endif() - set (petsc_mpi_include_dirs "${MPI_${PETSC_LANGUAGE_BINDINGS}_INCLUDE_DIRS}") + set(petsc_mpi_include_dirs "${MPI_${PETSC_LANGUAGE_BINDINGS}_INCLUDE_DIRS}") #set (petsc_additional_libraries "MPI::MPI_${PETSC_LANGUAGE_BINDINGS}${petsc_openmp_library}") - petsc_test_compiles ("${petsc_includes_minimal};${petsc_mpi_include_dirs}" - "${PETSC_LIBRARIES_TS};${petsc_additional_libraries}" - petsc_works_minimal) - if (petsc_works_minimal) - message (STATUS "Minimal PETSc includes and libraries work. This probably means we are building with shared libs.") - set (petsc_includes_needed "${petsc_includes_minimal}") - else (petsc_works_minimal) # Minimal includes fail, see if just adding full includes fixes it - petsc_test_compiles ("${petsc_includes_all};${petsc_mpi_include_dirs}" + petsc_test_compiles( + "${petsc_includes_minimal};${petsc_mpi_include_dirs}" + "${PETSC_LIBRARIES_TS};${petsc_additional_libraries}" petsc_works_minimal + ) + if(petsc_works_minimal) + message( + STATUS + "Minimal PETSc includes and libraries work. This probably means we are building with shared libs." + ) + set(petsc_includes_needed "${petsc_includes_minimal}") + else(petsc_works_minimal + )# Minimal includes fail, see if just adding full includes fixes it + petsc_test_compiles( + "${petsc_includes_all};${petsc_mpi_include_dirs}" "${PETSC_LIBRARIES_TS};${petsc_additional_libraries}" - petsc_works_allincludes) - if (petsc_works_allincludes) # It does, we just need all the includes ( - message (STATUS "PETSc requires extra include paths, but links correctly with only interface libraries. This is an unexpected configuration (but it seems to work fine).") - set (petsc_includes_needed ${petsc_includes_all}) - else (petsc_works_allincludes) # We are going to need to link the external libs explicitly - resolve_libraries (petsc_libraries_external "${petsc_libs_external}") - foreach (pkg SYS VEC MAT DM KSP SNES TS ALL) - list (APPEND PETSC_LIBRARIES_${pkg} ${petsc_libraries_external}) - endforeach (pkg) - petsc_test_compiles ("${petsc_includes_minimal};${petsc_mpi_include_dirs}" + petsc_works_allincludes + ) + if(petsc_works_allincludes) # It does, we just need all the includes ( + message( + STATUS + "PETSc requires extra include paths, but links correctly with only interface libraries. This is an unexpected configuration (but it seems to work fine)." + ) + set(petsc_includes_needed ${petsc_includes_all}) + else(petsc_works_allincludes + )# We are going to need to link the external libs explicitly + resolve_libraries(petsc_libraries_external "${petsc_libs_external}") + foreach( + pkg + SYS + VEC + MAT + DM + KSP + SNES + TS + ALL + ) + list(APPEND PETSC_LIBRARIES_${pkg} ${petsc_libraries_external}) + endforeach(pkg) + petsc_test_compiles( + "${petsc_includes_minimal};${petsc_mpi_include_dirs}" "${PETSC_LIBRARIES_TS};${petsc_additional_libraries}" - petsc_works_alllibraries) - if (petsc_works_alllibraries) - message (STATUS "PETSc only need minimal includes, but requires explicit linking to all dependencies. This is expected when PETSc is built with static libraries.") - set (petsc_includes_needed ${petsc_includes_minimal}) - else (petsc_works_alllibraries) + petsc_works_alllibraries + ) + if(petsc_works_alllibraries) + message( + STATUS + "PETSc only need minimal includes, but requires explicit linking to all dependencies. This is expected when PETSc is built with static libraries." + ) + set(petsc_includes_needed ${petsc_includes_minimal}) + else(petsc_works_alllibraries) # It looks like we really need everything, should have listened to Matt - set (petsc_includes_needed ${petsc_includes_all}) - petsc_test_compiles ("${petsc_includes_all};${petsc_mpi_include_dirs}" - "${PETSC_LIBRARIES_TS};${petsc_additional_libraries}" - petsc_works_all) - if (petsc_works_all) # We fail anyways - message (STATUS "PETSc requires extra include paths and explicit linking to all dependencies. This probably means you have static libraries and something unexpected in PETSc headers.") - else (petsc_works_all) # We fail anyways - message (STATUS "PETSc could not be used, maybe the install is broken.") - endif (petsc_works_all) - endif (petsc_works_alllibraries) - endif (petsc_works_allincludes) - endif (petsc_works_minimal) + set(petsc_includes_needed ${petsc_includes_all}) + petsc_test_compiles( + "${petsc_includes_all};${petsc_mpi_include_dirs}" + "${PETSC_LIBRARIES_TS};${petsc_additional_libraries}" petsc_works_all + ) + if(petsc_works_all) # We fail anyways + message( + STATUS + "PETSc requires extra include paths and explicit linking to all dependencies. This probably means you have static libraries and something unexpected in PETSc headers." + ) + else(petsc_works_all) # We fail anyways + message( + STATUS "PETSc could not be used, maybe the install is broken." + ) + endif(petsc_works_all) + endif(petsc_works_alllibraries) + endif(petsc_works_allincludes) + endif(petsc_works_minimal) # We do an out-of-source build so __FILE__ will be an absolute path, hence __INSDIR__ is superfluous - if (${PETSC_VERSION} VERSION_LESS 3.1) - set (PETSC_DEFINITIONS "-D__SDIR__=\"\"" CACHE STRING "PETSc definitions" FORCE) - else () - set (PETSC_DEFINITIONS "-D__INSDIR__=" CACHE STRING "PETSc definitions" FORCE) - endif () + if(${PETSC_VERSION} VERSION_LESS 3.1) + set(PETSC_DEFINITIONS + "-D__SDIR__=\"\"" + CACHE STRING "PETSc definitions" FORCE + ) + else() + set(PETSC_DEFINITIONS + "-D__INSDIR__=" + CACHE STRING "PETSc definitions" FORCE + ) + endif() # Sometimes this can be used to assist FindMPI.cmake - set (PETSC_MPIEXEC ${petsc_mpiexec} CACHE FILEPATH "Executable for running PETSc MPI programs" FORCE) - set (PETSC_INCLUDES ${petsc_includes_needed} CACHE STRING "PETSc include path" FORCE) - set (PETSC_LIBRARIES ${PETSC_LIBRARIES_ALL} CACHE STRING "PETSc libraries" FORCE) - set (PETSC_COMPILER ${petsc_cc} CACHE FILEPATH "PETSc compiler" FORCE) -endif () + set(PETSC_MPIEXEC + ${petsc_mpiexec} + CACHE FILEPATH "Executable for running PETSc MPI programs" FORCE + ) + set(PETSC_INCLUDES + ${petsc_includes_needed} + CACHE STRING "PETSc include path" FORCE + ) + set(PETSC_LIBRARIES + ${PETSC_LIBRARIES_ALL} + CACHE STRING "PETSc libraries" FORCE + ) + set(PETSC_COMPILER + ${petsc_cc} + CACHE FILEPATH "PETSc compiler" FORCE + ) +endif() -if (NOT PETSC_INCLUDES AND NOT TARGET PETSc::PETSc) +if(NOT PETSC_INCLUDES AND NOT TARGET PETSc::PETSc) find_package(PkgConfig) - if (PkgConfig_FOUND) + if(PkgConfig_FOUND) pkg_search_module(PkgPETSC PETSc>3.4.0 petsc>3.4.0) - set (PETSC_LIBRARIES ${PkgPETSC_LINK_LIBRARIES} CACHE STRING "PETSc libraries" FORCE) - set (PETSC_INCLUDES ${PkgPETSC_INCLUDE_DIRS} CACHE STRING "PETSc include path" FORCE) - set (PETSC_EXECUTABLE_COMPILES "YES" CACHE BOOL - "Can the system successfully run a PETSc executable? This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build. If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." FORCE) + set(PETSC_LIBRARIES + ${PkgPETSC_LINK_LIBRARIES} + CACHE STRING "PETSc libraries" FORCE + ) + set(PETSC_INCLUDES + ${PkgPETSC_INCLUDE_DIRS} + CACHE STRING "PETSc include path" FORCE + ) + set(PETSC_EXECUTABLE_COMPILES + "YES" + CACHE + BOOL + "Can the system successfully run a PETSc executable? This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build. If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." + FORCE + ) endif() endif() # Note that we have forced values for all these choices. If you # change these, you are telling the system to trust you that they # work. It is likely that you will end up with a broken build. -mark_as_advanced (PETSC_INCLUDES PETSC_LIBRARIES PETSC_COMPILER PETSC_DEFINITIONS PETSC_MPIEXEC PETSC_EXECUTABLE_COMPILES) - -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args (PETSc +mark_as_advanced( + PETSC_INCLUDES PETSC_LIBRARIES PETSC_COMPILER PETSC_DEFINITIONS PETSC_MPIEXEC + PETSC_EXECUTABLE_COMPILES +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + PETSc REQUIRED_VARS PETSC_INCLUDES PETSC_LIBRARIES VERSION_VAR PETSC_VERSION - FAIL_MESSAGE "PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH.") + FAIL_MESSAGE + "PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH." +) -if (PETSC_FOUND) - if (NOT TARGET PETSc::PETSc) +if(PETSC_FOUND) + if(NOT TARGET PETSc::PETSc) add_library(PETSc::PETSc UNKNOWN IMPORTED) list(GET PETSC_LIBRARIES 0 PETSC_LIBRARY) target_link_libraries(PETSc::PETSc INTERFACE "${PETSC_LIBRARIES}") - set_target_properties(PETSc::PETSc PROPERTIES - IMPORTED_LOCATION "${PETSC_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${PETSC_INCLUDES}" - ) + set_target_properties( + PETSc::PETSc PROPERTIES IMPORTED_LOCATION "${PETSC_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${PETSC_INCLUDES}" + ) endif() endif() diff --git a/cmake/FindPackageMultipass.cmake b/cmake/FindPackageMultipass.cmake index 99bbace448..b2762f5d28 100644 --- a/cmake/FindPackageMultipass.cmake +++ b/cmake/FindPackageMultipass.cmake @@ -34,99 +34,124 @@ include(CheckCXXSourceCompiles) -macro (FIND_PACKAGE_MULTIPASS _name _current) - string (TOUPPER ${_name} _NAME) - set (_args ${ARGV}) - list (REMOVE_AT _args 0 1) +macro(FIND_PACKAGE_MULTIPASS _name _current) + string(TOUPPER ${_name} _NAME) + set(_args ${ARGV}) + list(REMOVE_AT _args 0 1) - set (_states_current "YES") - list (GET _args 0 _cmd) - if (_cmd STREQUAL "STATES") - list (REMOVE_AT _args 0) - list (GET _args 0 _state) - while (_state AND NOT _state STREQUAL "DEPENDENTS") + set(_states_current "YES") + list(GET _args 0 _cmd) + if(_cmd STREQUAL "STATES") + list(REMOVE_AT _args 0) + list(GET _args 0 _state) + while(_state AND NOT _state STREQUAL "DEPENDENTS") # The name of the stored value for the given state - set (_stored_var PACKAGE_MULTIPASS_${_NAME}_${_state}) - if (NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") - set (_states_current "NO") - endif (NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") - set (${_stored_var} "${${_NAME}_${_state}}" CACHE INTERNAL "Stored state for ${_name}." FORCE) - list (REMOVE_AT _args 0) - list (GET _args 0 _state) - endwhile (_state AND NOT _state STREQUAL "DEPENDENTS") - endif (_cmd STREQUAL "STATES") + set(_stored_var PACKAGE_MULTIPASS_${_NAME}_${_state}) + if(NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") + set(_states_current "NO") + endif(NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") + set(${_stored_var} + "${${_NAME}_${_state}}" + CACHE INTERNAL "Stored state for ${_name}." FORCE + ) + list(REMOVE_AT _args 0) + list(GET _args 0 _state) + endwhile(_state AND NOT _state STREQUAL "DEPENDENTS") + endif(_cmd STREQUAL "STATES") - set (_stored ${_NAME}_CURRENT) - if (NOT ${_stored}) - set (${_stored} "YES" CACHE BOOL "Is the configuration for ${_name} current? Set to \"NO\" to reconfigure." FORCE) - set (_states_current "NO") - endif (NOT ${_stored}) + set(_stored ${_NAME}_CURRENT) + if(NOT ${_stored}) + set(${_stored} + "YES" + CACHE + BOOL + "Is the configuration for ${_name} current? Set to \"NO\" to reconfigure." + FORCE + ) + set(_states_current "NO") + endif(NOT ${_stored}) - set (${_current} ${_states_current}) - if (NOT ${_current} AND PACKAGE_MULTIPASS_${_name}_CALLED) - message (STATUS "Clearing ${_name} dependent variables") + set(${_current} ${_states_current}) + if(NOT ${_current} AND PACKAGE_MULTIPASS_${_name}_CALLED) + message(STATUS "Clearing ${_name} dependent variables") # Clear all the dependent variables so that the module can reset them - list (GET _args 0 _cmd) - if (_cmd STREQUAL "DEPENDENTS") - list (REMOVE_AT _args 0) - foreach (dep ${_args}) - set (${_NAME}_${dep} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) - endforeach (dep) - endif (_cmd STREQUAL "DEPENDENTS") - set (${_NAME}_FOUND "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) - endif () - set (PACKAGE_MULTIPASS_${name}_CALLED YES CACHE INTERNAL "Private" FORCE) -endmacro (FIND_PACKAGE_MULTIPASS) - + list(GET _args 0 _cmd) + if(_cmd STREQUAL "DEPENDENTS") + list(REMOVE_AT _args 0) + foreach(dep ${_args}) + set(${_NAME}_${dep} + "NOTFOUND" + CACHE INTERNAL "Cleared" FORCE + ) + endforeach(dep) + endif(_cmd STREQUAL "DEPENDENTS") + set(${_NAME}_FOUND + "NOTFOUND" + CACHE INTERNAL "Cleared" FORCE + ) + endif() + set(PACKAGE_MULTIPASS_${name}_CALLED + YES + CACHE INTERNAL "Private" FORCE + ) +endmacro(FIND_PACKAGE_MULTIPASS) -macro (MULTIPASS_SOURCE_RUNS includes libraries source runs language) - include (Check${language}SourceRuns) +macro(MULTIPASS_SOURCE_RUNS includes libraries source runs language) + include(Check${language}SourceRuns) # This is a ridiculous hack. CHECK_${language}_SOURCE_* thinks that if the # *name* of the return variable doesn't change, then the test does # not need to be re-run. We keep an internal count which we # increment to guarantee that every test name is unique. If we've # gotten here, then the configuration has changed enough that the # test *needs* to be rerun. - if (NOT MULTIPASS_TEST_COUNT) - set (MULTIPASS_TEST_COUNT 00) - endif (NOT MULTIPASS_TEST_COUNT) - math (EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1") # Why can't I add to a cache variable? - set (MULTIPASS_TEST_COUNT ${_tmp} CACHE INTERNAL "Unique test ID") - set (testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs}) - set (CMAKE_REQUIRED_INCLUDES ${includes}) - set (CMAKE_REQUIRED_LIBRARIES ${libraries}) + if(NOT MULTIPASS_TEST_COUNT) + set(MULTIPASS_TEST_COUNT 00) + endif(NOT MULTIPASS_TEST_COUNT) + math(EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1" + )# Why can't I add to a cache variable? + set(MULTIPASS_TEST_COUNT + ${_tmp} + CACHE INTERNAL "Unique test ID" + ) + set(testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs}) + set(CMAKE_REQUIRED_INCLUDES ${includes}) + set(CMAKE_REQUIRED_LIBRARIES ${libraries}) if(${language} STREQUAL "C") - check_c_source_runs ("${source}" ${testname}) + check_c_source_runs("${source}" ${testname}) elseif(${language} STREQUAL "CXX") - check_cxx_source_runs ("${source}" ${testname}) + check_cxx_source_runs("${source}" ${testname}) endif() - set (${runs} "${${testname}}") -endmacro (MULTIPASS_SOURCE_RUNS) + set(${runs} "${${testname}}") +endmacro(MULTIPASS_SOURCE_RUNS) -macro (MULTIPASS_C_SOURCE_RUNS includes libraries source runs) +macro(MULTIPASS_C_SOURCE_RUNS includes libraries source runs) multipass_source_runs("${includes}" "${libraries}" "${source}" ${runs} "C") -endmacro (MULTIPASS_C_SOURCE_RUNS) +endmacro(MULTIPASS_C_SOURCE_RUNS) -macro (MULTIPASS_SOURCE_COMPILES includes libraries source runs language) - include (Check${language}SourceCompiles) +macro(MULTIPASS_SOURCE_COMPILES includes libraries source runs language) + include(Check${language}SourceCompiles) # This is a ridiculous hack. CHECK_${language}_SOURCE_* thinks that if the # *name* of the return variable doesn't change, then the test does # not need to be re-run. We keep an internal count which we # increment to guarantee that every test name is unique. If we've # gotten here, then the configuration has changed enough that the # test *needs* to be rerun. - if (NOT MULTIPASS_TEST_COUNT) - set (MULTIPASS_TEST_COUNT 00) - endif (NOT MULTIPASS_TEST_COUNT) - math (EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1") # Why can't I add to a cache variable? - set (MULTIPASS_TEST_COUNT ${_tmp} CACHE INTERNAL "Unique test ID") - set (testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs}) - set (CMAKE_REQUIRED_INCLUDES ${includes}) - set (CMAKE_REQUIRED_LIBRARIES ${libraries}) + if(NOT MULTIPASS_TEST_COUNT) + set(MULTIPASS_TEST_COUNT 00) + endif(NOT MULTIPASS_TEST_COUNT) + math(EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1" + )# Why can't I add to a cache variable? + set(MULTIPASS_TEST_COUNT + ${_tmp} + CACHE INTERNAL "Unique test ID" + ) + set(testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs}) + set(CMAKE_REQUIRED_INCLUDES ${includes}) + set(CMAKE_REQUIRED_LIBRARIES ${libraries}) if(${language} STREQUAL "C") - check_c_source_compiles ("${source}" ${testname}) + check_c_source_compiles("${source}" ${testname}) elseif(${language} STREQUAL "CXX") - check_cxx_source_compiles ("${source}" ${testname}) + check_cxx_source_compiles("${source}" ${testname}) endif() - set (${runs} "${${testname}}") -endmacro () + set(${runs} "${${testname}}") +endmacro() diff --git a/cmake/FindSLEPc.cmake b/cmake/FindSLEPc.cmake index 3add8eba8b..4df855569b 100644 --- a/cmake/FindSLEPc.cmake +++ b/cmake/FindSLEPc.cmake @@ -48,74 +48,92 @@ find_package(PETSc REQUIRED) find_package(MPI REQUIRED) # Set debian_arches (PETSC_ARCH for Debian-style installations) -foreach (debian_arches linux kfreebsd) - if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(DEBIAN_FLAVORS ${debian_arches}-gnu-c-debug ${debian_arches}-gnu-c-opt ${DEBIAN_FLAVORS}) +foreach(debian_arches linux kfreebsd) + if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(DEBIAN_FLAVORS ${debian_arches}-gnu-c-debug ${debian_arches}-gnu-c-opt + ${DEBIAN_FLAVORS} + ) else() - set(DEBIAN_FLAVORS ${debian_arches}-gnu-c-opt ${debian_arches}-gnu-c-debug ${DEBIAN_FLAVORS}) + set(DEBIAN_FLAVORS ${debian_arches}-gnu-c-opt ${debian_arches}-gnu-c-debug + ${DEBIAN_FLAVORS} + ) endif() endforeach() # List of possible locations for SLEPC_DIR set(slepc_dir_locations "") list(APPEND slepc_dir_locations "/usr/lib/slepc") -list(APPEND slepc_dir_locations "/opt/local/lib/petsc") # Macports +list(APPEND slepc_dir_locations "/opt/local/lib/petsc") # Macports list(APPEND slepc_dir_locations "/usr/local/lib/slepc") list(APPEND slepc_dir_locations "$ENV{HOME}/slepc") # Try to figure out SLEPC_DIR by finding slepc.h -find_path(SLEPC_DIR include/slepc.h +find_path( + SLEPC_DIR include/slepc.h HINTS ${SLEPC_DIR} $ENV{SLEPC_DIR} PATHS ${slepc_dir_locations} - DOC "SLEPc directory") + DOC "SLEPc directory" +) # Report result of search for SLEPC_DIR -if (DEFINED SLEPC_DIR) +if(DEFINED SLEPC_DIR) message(STATUS "SLEPC_DIR is ${SLEPC_DIR}") else() message(STATUS "SLEPC_DIR is empty") endif() # Get variables from SLEPc configuration -if (SLEPC_DIR) +if(SLEPC_DIR) - find_library(SLEPC_LIBRARY + find_library( + SLEPC_LIBRARY NAMES slepc - HINTS - ${SLEPC_DIR}/lib - $ENV{SLEPC_DIR}/lib - ${SLEPC_DIR}/${PETSC_ARCH}/lib - $ENV{SLEPC_DIR}/$ENV{PETSC_ARCH}/lib + HINTS ${SLEPC_DIR}/lib $ENV{SLEPC_DIR}/lib ${SLEPC_DIR}/${PETSC_ARCH}/lib + $ENV{SLEPC_DIR}/$ENV{PETSC_ARCH}/lib NO_DEFAULT_PATH - DOC "The SLEPc library") - find_library(SLEPC_LIBRARY + DOC "The SLEPc library" + ) + find_library( + SLEPC_LIBRARY NAMES slepc - DOC "The SLEPc library") + DOC "The SLEPc library" + ) mark_as_advanced(SLEPC_LIBRARY) # Find SLEPc config file - find_file(SLEPC_CONFIG_FILE NAMES slepc_common PATHS - ${SLEPC_DIR}/lib/slepc/conf - ${SLEPC_DIR}/lib/slepc-conf ${SLEPC_DIR}/conf) + find_file( + SLEPC_CONFIG_FILE + NAMES slepc_common + PATHS ${SLEPC_DIR}/lib/slepc/conf ${SLEPC_DIR}/lib/slepc-conf + ${SLEPC_DIR}/conf + ) # Create a temporary Makefile to probe the SLEPc configuration set(slepc_config_makefile ${PROJECT_BINARY_DIR}/Makefile.slepc) - file(WRITE ${slepc_config_makefile} -"# This file was autogenerated by FindSLEPc.cmake + file( + WRITE ${slepc_config_makefile} + "# This file was autogenerated by FindSLEPc.cmake SLEPC_DIR = ${SLEPC_DIR} PETSC_ARCH = ${PETSC_ARCH} PETSC_DIR = ${PETSC_DIR} include ${SLEPC_CONFIG_FILE} show : -@echo -n \${\${VARIABLE}} -") +" + ) # Define macro for getting SLEPc variables from Makefile macro(SLEPC_GET_VARIABLE var name) - set(${var} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) - execute_process(COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f ${slepc_config_makefile} show VARIABLE=${name} + set(${var} + "NOTFOUND" + CACHE INTERNAL "Cleared" FORCE + ) + execute_process( + COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f + ${slepc_config_makefile} show VARIABLE=${name} OUTPUT_VARIABLE ${var} - RESULT_VARIABLE slepc_return) + RESULT_VARIABLE slepc_return + ) endmacro() # Call macro to get the SLEPc variables @@ -131,15 +149,21 @@ show : resolve_libraries(SLEPC_EXTERNAL_LIBRARIES "${SLEPC_EXTERNAL_LIB}") # Add variables to CMake cache and mark as advanced - set(SLEPC_INCLUDE_DIRS ${SLEPC_INCLUDE_DIRS} CACHE STRING "SLEPc include paths." FORCE) - set(SLEPC_LIBRARIES ${SLEPC_LIBRARY} CACHE STRING "SLEPc libraries." FORCE) + set(SLEPC_INCLUDE_DIRS + ${SLEPC_INCLUDE_DIRS} + CACHE STRING "SLEPc include paths." FORCE + ) + set(SLEPC_LIBRARIES + ${SLEPC_LIBRARY} + CACHE STRING "SLEPc libraries." FORCE + ) mark_as_advanced(SLEPC_INCLUDE_DIRS SLEPC_LIBRARIES) endif() -if (SLEPC_SKIP_BUILD_TESTS) +if(SLEPC_SKIP_BUILD_TESTS) set(SLEPC_VERSION "UNKNOWN") set(SLEPC_VERSION_OK TRUE) -elseif (SLEPC_LIBRARIES AND SLEPC_INCLUDE_DIRS) +elseif(SLEPC_LIBRARIES AND SLEPC_INCLUDE_DIRS) # Set flags for building test program set(CMAKE_REQUIRED_INCLUDES ${SLEPC_INCLUDE_DIRS}) @@ -147,8 +171,11 @@ elseif (SLEPC_LIBRARIES AND SLEPC_INCLUDE_DIRS) # Check SLEPc version set(SLEPC_CONFIG_TEST_VERSION_CPP - "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/slepc_config_test_version.cpp") - file(WRITE ${SLEPC_CONFIG_TEST_VERSION_CPP} " + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/slepc_config_test_version.cpp" + ) + file( + WRITE ${SLEPC_CONFIG_TEST_VERSION_CPP} + " #include #include \"slepcversion.h\" @@ -158,56 +185,69 @@ int main() { << SLEPC_VERSION_SUBMINOR; return 0; } -") +" + ) try_run( - SLEPC_CONFIG_TEST_VERSION_EXITCODE - SLEPC_CONFIG_TEST_VERSION_COMPILED - ${CMAKE_CURRENT_BINARY_DIR} - ${SLEPC_CONFIG_TEST_VERSION_CPP} - CMAKE_FLAGS - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}" + SLEPC_CONFIG_TEST_VERSION_EXITCODE SLEPC_CONFIG_TEST_VERSION_COMPILED + ${CMAKE_CURRENT_BINARY_DIR} ${SLEPC_CONFIG_TEST_VERSION_CPP} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}" COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT RUN_OUTPUT_VARIABLE OUTPUT - ) + ) - if (SLEPC_CONFIG_TEST_VERSION_EXITCODE EQUAL 0) - set(SLEPC_VERSION "${OUTPUT}" CACHE STRING "SLEPC version number") + if(SLEPC_CONFIG_TEST_VERSION_EXITCODE EQUAL 0) + set(SLEPC_VERSION + "${OUTPUT}" + CACHE STRING "SLEPC version number" + ) string(REPLACE "." ";" SLEPC_VERSION_LIST ${SLEPC_VERSION}) list(GET SLEPC_VERSION_LIST 0 SLEPC_VERSION_MAJOR) list(GET SLEPC_VERSION_LIST 1 SLEPC_VERSION_MINOR) list(GET SLEPC_VERSION_LIST 2 SLEPC_VERSION_SUBMINOR) mark_as_advanced(SLEPC_VERSION) - mark_as_advanced(SLEPC_VERSION_MAJOR SLEPC_VERSION_MINOR SLEPC_VERSION_SUBMINOR) + mark_as_advanced( + SLEPC_VERSION_MAJOR SLEPC_VERSION_MINOR SLEPC_VERSION_SUBMINOR + ) endif() - if (SLEPc_FIND_VERSION) + if(SLEPc_FIND_VERSION) # Check if version found is >= required version - if (NOT "${SLEPC_VERSION}" VERSION_LESS "${SLEPc_FIND_VERSION}") - set(SLEPC_VERSION_OK TRUE CACHE BOOL "") + if(NOT "${SLEPC_VERSION}" VERSION_LESS "${SLEPc_FIND_VERSION}") + set(SLEPC_VERSION_OK + TRUE + CACHE BOOL "" + ) endif() else() # No specific version requested - set(SLEPC_VERSION_OK TRUE CACHE BOOL "") + set(SLEPC_VERSION_OK + TRUE + CACHE BOOL "" + ) endif() mark_as_advanced(SLEPC_VERSION_OK) endif() # Standard package handling include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SLEPc +find_package_handle_standard_args( + SLEPc FOUND_VAR SLEPC_FOUND - FAIL_MESSAGE "SLEPc could not be found. Be sure to set SLEPC_DIR, PETSC_DIR, and PETSC_ARCH." + FAIL_MESSAGE + "SLEPc could not be found. Be sure to set SLEPC_DIR, PETSC_DIR, and PETSC_ARCH." VERSION_VAR SLEPC_VERSION - REQUIRED_VARS SLEPC_LIBRARIES SLEPC_DIR SLEPC_INCLUDE_DIRS SLEPC_VERSION_OK) + REQUIRED_VARS SLEPC_LIBRARIES SLEPC_DIR SLEPC_INCLUDE_DIRS SLEPC_VERSION_OK +) -if (SLEPC_FOUND) - if (NOT TARGET SLEPc::SLEPc) +if(SLEPC_FOUND) + if(NOT TARGET SLEPc::SLEPc) add_library(SLEPc::SLEPc UNKNOWN IMPORTED) - set_target_properties(SLEPc::SLEPc PROPERTIES - IMPORTED_LOCATION "${SLEPC_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${SLEPC_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES PETSc::PETSc - ) + set_target_properties( + SLEPc::SLEPc + PROPERTIES IMPORTED_LOCATION "${SLEPC_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${SLEPC_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES PETSc::PETSc + ) endif() endif() diff --git a/cmake/FindSUNDIALS.cmake b/cmake/FindSUNDIALS.cmake index 15b266d06a..e5cec34510 100644 --- a/cmake/FindSUNDIALS.cmake +++ b/cmake/FindSUNDIALS.cmake @@ -33,47 +33,48 @@ include(FindPackageHandleStandardArgs) find_package(SUNDIALS CONFIG QUIET) -if (SUNDIALS_FOUND) - if (TARGET SUNDIALS::nvecparallel) +if(SUNDIALS_FOUND) + if(TARGET SUNDIALS::nvecparallel) return() else() message(STATUS "SUNDIALS found but not SUNDIALS::nvecparallel") endif() endif() -find_path(SUNDIALS_INCLUDE_DIR - sundials_config.h - HINTS - "${SUNDIALS_ROOT}" - ENV SUNDIALS_DIR +find_path( + SUNDIALS_INCLUDE_DIR sundials_config.h + HINTS "${SUNDIALS_ROOT}" ENV SUNDIALS_DIR PATH_SUFFIXES include include/sundials - DOC "SUNDIALS Directory") + DOC "SUNDIALS Directory" +) -if (SUNDIALS_DEBUG) +if(SUNDIALS_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " SUNDIALS_INCLUDE_DIR = ${SUNDIALS_INCLUDE_DIR}" - " SUNDIALS_ROOT = ${SUNDIALS_ROOT}") + " SUNDIALS_INCLUDE_DIR = ${SUNDIALS_INCLUDE_DIR}" + " SUNDIALS_ROOT = ${SUNDIALS_ROOT}" + ) endif() set(SUNDIALS_INCLUDE_DIRS - "${SUNDIALS_INCLUDE_DIR}" - "${SUNDIALS_INCLUDE_DIR}/.." - CACHE STRING "SUNDIALS include directories") + "${SUNDIALS_INCLUDE_DIR}" "${SUNDIALS_INCLUDE_DIR}/.." + CACHE STRING "SUNDIALS include directories" +) -find_library(SUNDIALS_nvecparallel_LIBRARY +find_library( + SUNDIALS_nvecparallel_LIBRARY NAMES sundials_nvecparallel - HINTS - "${SUNDIALS_INCLUDE_DIR}/.." - "${SUNDIALS_INCLUDE_DIR}/../.." + HINTS "${SUNDIALS_INCLUDE_DIR}/.." "${SUNDIALS_INCLUDE_DIR}/../.." PATH_SUFFIXES lib lib64 - ) +) -if (SUNDIALS_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " SUNDIALS_nvecparallel_LIBRARY = ${SUNDIALS_nvecparallel_LIBRARY}") +if(SUNDIALS_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " SUNDIALS_nvecparallel_LIBRARY = ${SUNDIALS_nvecparallel_LIBRARY}" + ) endif() -if (NOT SUNDIALS_nvecparallel_LIBRARY) +if(NOT SUNDIALS_nvecparallel_LIBRARY) message(FATAL_ERROR "Sundials requested but SUNDIALS nvecparallel not found.") endif() list(APPEND SUNDIALS_LIBRARIES "${SUNDIALS_nvecparallel_LIBRARY}") @@ -81,62 +82,86 @@ mark_as_advanced(SUNDIALS_nvecparallel_LIBRARY) set(SUNDIALS_COMPONENTS arkode cvode ida) -foreach (LIB ${SUNDIALS_COMPONENTS}) - find_library(SUNDIALS_${LIB}_LIBRARY +foreach(LIB ${SUNDIALS_COMPONENTS}) + find_library( + SUNDIALS_${LIB}_LIBRARY NAMES sundials_${LIB} - HINTS - "${SUNDIALS_INCLUDE_DIR}/.." - "${SUNDIALS_INCLUDE_DIR}/../.." + HINTS "${SUNDIALS_INCLUDE_DIR}/.." "${SUNDIALS_INCLUDE_DIR}/../.." PATH_SUFFIXES lib lib64 - ) + ) - if (SUNDIALS_DEBUG) + if(SUNDIALS_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " SUNDIALS_${LIB}_LIBRARY = ${SUNDIALS_${LIB}_LIBRARY}") + " SUNDIALS_${LIB}_LIBRARY = ${SUNDIALS_${LIB}_LIBRARY}" + ) endif() - if (NOT SUNDIALS_${LIB}_LIBRARY) + if(NOT SUNDIALS_${LIB}_LIBRARY) message(FATAL_ERROR "Sundials requested but SUNDIALS ${LIB} not found.") endif() list(APPEND SUNDIALS_LIBRARIES "${SUNDIALS_${LIB}_LIBRARY}") mark_as_advanced(SUNDIALS_${LIB}_LIBRARY) endforeach() -if (SUNDIALS_INCLUDE_DIR) +if(SUNDIALS_INCLUDE_DIR) file(READ "${SUNDIALS_INCLUDE_DIR}/sundials_config.h" SUNDIALS_CONFIG_FILE) set(SUNDIALS_VERSION_REGEX_PATTERN - ".*#define SUNDIALS_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*") - string(REGEX MATCH ${SUNDIALS_VERSION_REGEX_PATTERN} _ "${SUNDIALS_CONFIG_FILE}") - set(SUNDIALS_VERSION_MAJOR ${CMAKE_MATCH_1} CACHE STRING "") - set(SUNDIALS_VERSION_MINOR ${CMAKE_MATCH_2} CACHE STRING "") - set(SUNDIALS_VERSION_PATCH ${CMAKE_MATCH_3} CACHE STRING "") - set(SUNDIALS_VERSION "${SUNDIALS_VERSION_MAJOR}.${SUNDIALS_VERSION_MINOR}.${SUNDIALS_VERSION_PATCH}" CACHE STRING "SUNDIALS version") + ".*#define SUNDIALS_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*" + ) + string(REGEX MATCH ${SUNDIALS_VERSION_REGEX_PATTERN} _ + "${SUNDIALS_CONFIG_FILE}" + ) + set(SUNDIALS_VERSION_MAJOR + ${CMAKE_MATCH_1} + CACHE STRING "" + ) + set(SUNDIALS_VERSION_MINOR + ${CMAKE_MATCH_2} + CACHE STRING "" + ) + set(SUNDIALS_VERSION_PATCH + ${CMAKE_MATCH_3} + CACHE STRING "" + ) + set(SUNDIALS_VERSION + "${SUNDIALS_VERSION_MAJOR}.${SUNDIALS_VERSION_MINOR}.${SUNDIALS_VERSION_PATCH}" + CACHE STRING "SUNDIALS version" + ) endif() -if (SUNDIALS_DEBUG) +if(SUNDIALS_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " SUNDIALS_VERSION = ${SUNDIALS_VERSION}") + " SUNDIALS_VERSION = ${SUNDIALS_VERSION}" + ) endif() -find_package_handle_standard_args(SUNDIALS +find_package_handle_standard_args( + SUNDIALS REQUIRED_VARS SUNDIALS_LIBRARIES SUNDIALS_INCLUDE_DIR SUNDIALS_INCLUDE_DIRS VERSION_VAR SUNDIALS_VERSION - ) +) -set(SUNDIALS_LIBRARIES "${SUNDIALS_LIBRARIES}" CACHE STRING "SUNDIALS libraries") +set(SUNDIALS_LIBRARIES + "${SUNDIALS_LIBRARIES}" + CACHE STRING "SUNDIALS libraries" +) mark_as_advanced(SUNDIALS_LIBRARIES SUNDIALS_INCLUDE_DIR SUNDIALS_INCLUDE_DIRS) -if (SUNDIALS_FOUND AND NOT TARGET SUNDIALS::SUNDIALS) +if(SUNDIALS_FOUND AND NOT TARGET SUNDIALS::SUNDIALS) add_library(SUNDIALS::nvecparallel UNKNOWN IMPORTED) - set_target_properties(SUNDIALS::nvecparallel PROPERTIES - IMPORTED_LOCATION "${SUNDIALS_nvecparallel_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${SUNDIALS_INCLUDE_DIRS}") + set_target_properties( + SUNDIALS::nvecparallel + PROPERTIES IMPORTED_LOCATION "${SUNDIALS_nvecparallel_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${SUNDIALS_INCLUDE_DIRS}" + ) - foreach (LIB ${SUNDIALS_COMPONENTS}) + foreach(LIB ${SUNDIALS_COMPONENTS}) add_library(SUNDIALS::${LIB} UNKNOWN IMPORTED) - set_target_properties(SUNDIALS::${LIB} PROPERTIES - IMPORTED_LOCATION "${SUNDIALS_${LIB}_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${SUNDIALS_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES SUNDIALS::nvecparallel) + set_target_properties( + SUNDIALS::${LIB} + PROPERTIES IMPORTED_LOCATION "${SUNDIALS_${LIB}_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${SUNDIALS_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES SUNDIALS::nvecparallel + ) endforeach() endif() diff --git a/cmake/FindScoreP.cmake b/cmake/FindScoreP.cmake index dd119545e8..80fe102749 100644 --- a/cmake/FindScoreP.cmake +++ b/cmake/FindScoreP.cmake @@ -61,76 +61,90 @@ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - find_program(ScoreP_CONFIG scorep-config) mark_as_advanced(ScoreP_CONFIG) get_filename_component(ScoreP_TMP "${ScoreP_CONFIG}" DIRECTORY) get_filename_component(ScoreP_EXEC_LOCATION "${ScoreP_TMP}" DIRECTORY) -if (ScoreP_DEBUG) +if(ScoreP_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " ScoreP_CONFIG = ${ScoreP_CONFIG}" - " ScoreP_EXEC_LOCATION = ${ScoreP_EXEC_LOCATION}") + " ScoreP_CONFIG = ${ScoreP_CONFIG}" + " ScoreP_EXEC_LOCATION = ${ScoreP_EXEC_LOCATION}" + ) endif() if(ScoreP_CONFIG) message(STATUS "SCOREP library found. (using ${ScoreP_CONFIG})") - execute_process(COMMAND ${ScoreP_CONFIG} "--user" "--nocompiler" "--cppflags" - OUTPUT_VARIABLE ScoreP_CONFIG_FLAGS) + execute_process( + COMMAND ${ScoreP_CONFIG} "--user" "--nocompiler" "--cppflags" + OUTPUT_VARIABLE ScoreP_CONFIG_FLAGS + ) - string(REGEX MATCHALL "-I[^ ]*" ScoreP_CONFIG_INCLUDES "${ScoreP_CONFIG_FLAGS}") + string(REGEX MATCHALL "-I[^ ]*" ScoreP_CONFIG_INCLUDES + "${ScoreP_CONFIG_FLAGS}" + ) foreach(inc ${ScoreP_CONFIG_INCLUDES}) string(SUBSTRING ${inc} 2 -1 inc) list(APPEND ScoreP_INCLUDE_DIRS ${inc}) endforeach() - if (ScoreP_DEBUG) + if(ScoreP_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " ScoreP_INCLUDE_DIRS = ${ScoreP_INCLUDE_DIRS}") + " ScoreP_INCLUDE_DIRS = ${ScoreP_INCLUDE_DIRS}" + ) endif() - string(REGEX MATCHALL "(^| +)-[^I][^ ]*" ScoreP_CONFIG_CXXFLAGS "${ScoreP_CONFIG_FLAGS}") + string(REGEX MATCHALL "(^| +)-[^I][^ ]*" ScoreP_CONFIG_CXXFLAGS + "${ScoreP_CONFIG_FLAGS}" + ) foreach(flag ${ScoreP_CONFIG_CXXFLAGS}) string(STRIP ${flag} flag) list(APPEND ScoreP_CXX_FLAGS ${flag}) endforeach() - if (ScoreP_DEBUG) + if(ScoreP_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " ScoreP_CXX_FLAGS = ${ScoreP_CXX_FLAGS}") + " ScoreP_CXX_FLAGS = ${ScoreP_CXX_FLAGS}" + ) endif() unset(ScoreP_CONFIG_FLAGS) unset(ScoreP_CONFIG_INCLUDES) unset(ScoreP_CONFIG_CXXFLAGS) - execute_process(COMMAND ${ScoreP_CONFIG} "--user" "--nocompiler" "--ldflags" - OUTPUT_VARIABLE _LINK_LD_ARGS) - string( REPLACE " " ";" _LINK_LD_ARGS ${_LINK_LD_ARGS} ) - foreach( _ARG ${_LINK_LD_ARGS} ) + execute_process( + COMMAND ${ScoreP_CONFIG} "--user" "--nocompiler" "--ldflags" + OUTPUT_VARIABLE _LINK_LD_ARGS + ) + string(REPLACE " " ";" _LINK_LD_ARGS ${_LINK_LD_ARGS}) + foreach(_ARG ${_LINK_LD_ARGS}) if(${_ARG} MATCHES "^-L") - STRING(REGEX REPLACE "^-L" "" _ARG ${_ARG}) - SET(ScoreP_LINK_DIRS ${ScoreP_LINK_DIRS} ${_ARG}) + string(REGEX REPLACE "^-L" "" _ARG ${_ARG}) + set(ScoreP_LINK_DIRS ${ScoreP_LINK_DIRS} ${_ARG}) endif() endforeach() - if (ScoreP_DEBUG) + if(ScoreP_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " ScoreP_LINK_DIRS = ${ScoreP_LINK_DIRS}") + " ScoreP_LINK_DIRS = ${ScoreP_LINK_DIRS}" + ) endif() - execute_process(COMMAND ${ScoreP_CONFIG} "--user" "--nocompiler" "--libs" - OUTPUT_VARIABLE _LINK_LD_ARGS) - string( REPLACE " " ";" _LINK_LD_ARGS ${_LINK_LD_ARGS} ) - foreach( _ARG ${_LINK_LD_ARGS} ) + execute_process( + COMMAND ${ScoreP_CONFIG} "--user" "--nocompiler" "--libs" + OUTPUT_VARIABLE _LINK_LD_ARGS + ) + string(REPLACE " " ";" _LINK_LD_ARGS ${_LINK_LD_ARGS}) + foreach(_ARG ${_LINK_LD_ARGS}) if(${_ARG} MATCHES "^-l") string(REGEX REPLACE "^-l" "" _ARG ${_ARG}) - find_library(_SCOREP_LIB_FROM_ARG NAMES ${_ARG} - PATHS - ${ScoreP_LINK_DIRS} - ) + find_library( + _SCOREP_LIB_FROM_ARG + NAMES ${_ARG} + PATHS ${ScoreP_LINK_DIRS} + ) if(_SCOREP_LIB_FROM_ARG) set(ScoreP_LIBRARIES ${ScoreP_LIBRARIES} ${_SCOREP_LIB_FROM_ARG}) endif() @@ -138,26 +152,26 @@ if(ScoreP_CONFIG) endif() endforeach() - if (ScoreP_DEBUG) + if(ScoreP_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " ScoreP_LIBRARIES = ${ScoreP_LIBRARIES}") + " ScoreP_LIBRARIES = ${ScoreP_LIBRARIES}" + ) endif() endif() -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args(ScoreP DEFAULT_MSG - ScoreP_CONFIG - ScoreP_LIBRARIES - ScoreP_INCLUDE_DIRS - ) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + ScoreP DEFAULT_MSG ScoreP_CONFIG ScoreP_LIBRARIES ScoreP_INCLUDE_DIRS +) -if (ScoreP_FOUND AND NOT TARGET ScoreP::ScoreP) +if(ScoreP_FOUND AND NOT TARGET ScoreP::ScoreP) add_library(ScoreP::ScoreP UNKNOWN IMPORTED) - set_target_properties(ScoreP::ScoreP PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${ScoreP_INCLUDE_DIRS}" - IMPORTED_LINK_INTERFACE_LIBRARIES "${ScoreP_LIBRARIES}" - INTERFACE_INCLUDE_DEFINITIONS "${ScoreP_CXX_FLAGS}" - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - ) + set_target_properties( + ScoreP::ScoreP + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ScoreP_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LIBRARIES "${ScoreP_LIBRARIES}" + INTERFACE_INCLUDE_DEFINITIONS "${ScoreP_CXX_FLAGS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + ) endif() diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake index fd377d0d00..a15ae8d6f9 100644 --- a/cmake/FindSphinx.cmake +++ b/cmake/FindSphinx.cmake @@ -14,13 +14,15 @@ # https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/ #Look for an executable called sphinx-build -find_program(SPHINX_EXECUTABLE - NAMES sphinx-build sphinx-build-3 - DOC "Path to sphinx-build executable") +find_program( + SPHINX_EXECUTABLE + NAMES sphinx-build sphinx-build-3 + DOC "Path to sphinx-build executable" +) include(FindPackageHandleStandardArgs) #Handle standard arguments to find_package like REQUIRED and QUIET -find_package_handle_standard_args(Sphinx - "Failed to find sphinx-build executable" - SPHINX_EXECUTABLE) +find_package_handle_standard_args( + Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE +) diff --git a/cmake/FindnetCDF.cmake b/cmake/FindnetCDF.cmake index 361095954e..ca6eff8d75 100644 --- a/cmake/FindnetCDF.cmake +++ b/cmake/FindnetCDF.cmake @@ -28,119 +28,129 @@ include(BOUT++functions) include(CMakePrintHelpers) -if (NOT netCDF_ROOT AND EXISTS "${BOUT_USE_NETCDF}") +if(NOT netCDF_ROOT AND EXISTS "${BOUT_USE_NETCDF}") set(netCDF_ROOT "${BOUT_USE_NETCDF}") endif() enable_language(C) find_package(netCDF QUIET CONFIG) -if (netCDF_FOUND) +if(netCDF_FOUND) message(STATUS "netCDF CONFIG found") set(netCDF_FOUND TRUE) - if (NOT TARGET netCDF::netcdf) + if(NOT TARGET netCDF::netcdf) bout_add_library_alias(netCDF::netcdf netcdf) endif() - if (netCDF_DEBUG) - cmake_print_properties(TARGETS netcdf PROPERTIES LOCATION VERSION) - endif (netCDF_DEBUG) + if(netCDF_DEBUG) + cmake_print_properties(TARGETS netcdf PROPERTIES LOCATION VERSION) + endif(netCDF_DEBUG) return() endif() -find_program(NC_CONFIG "nc-config" +find_program( + NC_CONFIG "nc-config" PATHS "${netCDF_ROOT}" PATH_SUFFIXES bin DOC "Path to netCDF C config helper" NO_DEFAULT_PATH - ) +) -find_program(NC_CONFIG "nc-config" - DOC "Path to netCDF C config helper" - ) +find_program(NC_CONFIG "nc-config" DOC "Path to netCDF C config helper") get_filename_component(NC_CONFIG_TMP "${NC_CONFIG}" DIRECTORY) get_filename_component(NC_CONFIG_LOCATION "${NC_CONFIG_TMP}" DIRECTORY) -if (netCDF_DEBUG) +if(netCDF_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " NC_CONFIG_LOCATION = ${NC_CONFIG_LOCATION}" - " netCDF_ROOT = ${netCDF_ROOT}") + " NC_CONFIG_LOCATION = ${NC_CONFIG_LOCATION}" + " netCDF_ROOT = ${netCDF_ROOT}" + ) endif() bout_inspect_netcdf_config(NC_HINTS_INCLUDE_DIR "${NC_CONFIG}" "--includedir") bout_inspect_netcdf_config(NC_HINTS_PREFIX "${NC_CONFIG}" "--prefix") -find_path(netCDF_C_INCLUDE_DIR +find_path( + netCDF_C_INCLUDE_DIR NAMES netcdf.h DOC "netCDF C include directories" - HINTS - "${NC_HINTS_INCLUDE_DIR}" - "${NC_HINTS_PREFIX}" - "${NC_CONFIG_LOCATION}" - PATH_SUFFIXES - "include" + HINTS "${NC_HINTS_INCLUDE_DIR}" "${NC_HINTS_PREFIX}" "${NC_CONFIG_LOCATION}" + PATH_SUFFIXES "include" +) +if(netCDF_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " netCDF_C_INCLUDE_DIR = ${netCDF_C_INCLUDE_DIR}" + " NC_HINTS_INCLUDE_DIR = ${NC_HINTS_INCLUDE_DIR}" + " NC_HINTS_PREFIX = ${NC_HINTS_PREFIX}" ) -if (netCDF_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " netCDF_C_INCLUDE_DIR = ${netCDF_C_INCLUDE_DIR}" - " NC_HINTS_INCLUDE_DIR = ${NC_HINTS_INCLUDE_DIR}" - " NC_HINTS_PREFIX = ${NC_HINTS_PREFIX}" - ) endif() mark_as_advanced(netCDF_C_INCLUDE_DIR) -find_library(netCDF_C_LIBRARY +find_library( + netCDF_C_LIBRARY NAMES netcdf DOC "netCDF C library" - HINTS - "${NC_HINTS_INCLUDE_DIR}" - "${NC_HINTS_PREFIX}" - "${NC_CONFIG_LOCATION}" - PATH_SUFFIXES - "lib" "lib64" - ) -if (netCDF_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " netCDF_C_LIBRARY = ${netCDF_C_LIBRARY}" - " NC_HINTS_INCLUDE_DIR = ${NC_HINTS_INCLUDE_DIR}" - " NC_HINTS_PREFIX = ${NC_HINTS_PREFIX}" - ) + HINTS "${NC_HINTS_INCLUDE_DIR}" "${NC_HINTS_PREFIX}" "${NC_CONFIG_LOCATION}" + PATH_SUFFIXES "lib" "lib64" +) +if(netCDF_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " netCDF_C_LIBRARY = ${netCDF_C_LIBRARY}" + " NC_HINTS_INCLUDE_DIR = ${NC_HINTS_INCLUDE_DIR}" + " NC_HINTS_PREFIX = ${NC_HINTS_PREFIX}" + ) endif() mark_as_advanced(netCDF_C_LIBRARY) -if (netCDF_C_INCLUDE_DIR) +if(netCDF_C_INCLUDE_DIR) file(STRINGS "${netCDF_C_INCLUDE_DIR}/netcdf_meta.h" _netcdf_version_lines - REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)") - string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" _netcdf_version_major "${_netcdf_version_lines}") - string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" _netcdf_version_minor "${_netcdf_version_lines}") - string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" _netcdf_version_patch "${_netcdf_version_lines}") - string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" _netcdf_version_note "${_netcdf_version_lines}") - if (NOT _netcdf_version_note STREQUAL "") + REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)" + ) + string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" + _netcdf_version_major "${_netcdf_version_lines}" + ) + string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" + _netcdf_version_minor "${_netcdf_version_lines}" + ) + string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" + _netcdf_version_patch "${_netcdf_version_lines}" + ) + string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" + _netcdf_version_note "${_netcdf_version_lines}" + ) + if(NOT _netcdf_version_note STREQUAL "") # Make development version compare higher than any patch level set(_netcdf_version_note ".99") endif() - set(netCDF_VERSION "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}") + set(netCDF_VERSION + "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}" + ) unset(_netcdf_version_major) unset(_netcdf_version_minor) unset(_netcdf_version_patch) unset(_netcdf_version_note) unset(_netcdf_version_lines) -endif () +endif() include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(netCDF +find_package_handle_standard_args( + netCDF REQUIRED_VARS netCDF_C_LIBRARY netCDF_C_INCLUDE_DIR - VERSION_VAR netCDF_VERSION) + VERSION_VAR netCDF_VERSION +) -if (netCDF_FOUND) +if(netCDF_FOUND) set(netCDF_INCLUDE_DIR "${netCDF_C_INCLUDE_DIR}") set(netCDF_INCLUDE_DIRS "${netCDF_C_INCLUDE_DIR}") set(netCDF_LIBRARIES "${netCDF_C_LIBRARY}") - if (NOT TARGET netCDF::netcdf) + if(NOT TARGET netCDF::netcdf) add_library(netCDF::netcdf UNKNOWN IMPORTED) - set_target_properties(netCDF::netcdf PROPERTIES - IMPORTED_LOCATION "${netCDF_C_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${netCDF_C_INCLUDE_DIR}" - ) - endif () -endif () + set_target_properties( + netCDF::netcdf + PROPERTIES IMPORTED_LOCATION "${netCDF_C_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${netCDF_C_INCLUDE_DIR}" + ) + endif() +endif() diff --git a/cmake/FindnetCDFCxx.cmake b/cmake/FindnetCDFCxx.cmake index d4155dc760..78bd93851e 100644 --- a/cmake/FindnetCDFCxx.cmake +++ b/cmake/FindnetCDFCxx.cmake @@ -27,16 +27,16 @@ include(BOUT++functions) -if (NOT netCDFCxx_ROOT AND EXISTS "${BOUT_USE_NETCDF}") +if(NOT netCDFCxx_ROOT AND EXISTS "${BOUT_USE_NETCDF}") set(netCDFCxx_ROOT "${BOUT_USE_NETCDF}") endif() -if (NOT EXISTS ${NCXX4_CONFIG}) +if(NOT EXISTS ${NCXX4_CONFIG}) # Only search if NCXX4_CONFIG was not set explicitly find_package(netCDFCxx QUIET CONFIG) - if (netCDFCxx_FOUND) + if(netCDFCxx_FOUND) set(netCDFCxx_FOUND TRUE) - if (NOT TARGET netCDF::netcdf-cxx4) + if(NOT TARGET netCDF::netcdf-cxx4) bout_add_library_alias(netCDF::netcdf-cxx4 netcdf-cxx4) endif() return() @@ -45,73 +45,74 @@ endif() find_package(netCDF REQUIRED) -find_program(NCXX4_CONFIG "ncxx4-config" +find_program( + NCXX4_CONFIG "ncxx4-config" PATHS "${netCDFCxx_ROOT}" PATH_SUFFIXES bin DOC "Path to netCDF C++ config helper" NO_DEFAULT_PATH - ) +) -find_program(NCXX4_CONFIG "ncxx4-config" - DOC "Path to netCDF C++ config helper" - ) +find_program(NCXX4_CONFIG "ncxx4-config" DOC "Path to netCDF C++ config helper") get_filename_component(NCXX4_CONFIG_TMP "${NCXX4_CONFIG}" DIRECTORY) get_filename_component(NCXX4_CONFIG_LOCATION "${NCXX4_CONFIG_TMP}" DIRECTORY) -if (netCDFCxx_DEBUG) +if(netCDFCxx_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " NCXX4_CONFIG_LOCATION = ${NCXX4_CONFIG_LOCATION}") + " NCXX4_CONFIG_LOCATION = ${NCXX4_CONFIG_LOCATION}" + ) endif() -bout_inspect_netcdf_config(NCXX4_HINTS_INCLUDE_DIR "${NCXX4_CONFIG}" "--includedir") +bout_inspect_netcdf_config( + NCXX4_HINTS_INCLUDE_DIR "${NCXX4_CONFIG}" "--includedir" +) bout_inspect_netcdf_config(NCXX4_HINTS_PREFIX "${NCXX4_CONFIG}" "--prefix") -find_path(netCDF_CXX_INCLUDE_DIR +find_path( + netCDF_CXX_INCLUDE_DIR NAMES netcdf DOC "netCDF C++ include directories" - HINTS - "${netCDF_C_INCLUDE_DIR}" - "${NCXX4_HINTS_INCLUDE_DIR}" - "${NCXX4_HINTS_PREFIX}" - "${NCXX4_CONFIG_LOCATION}" - PATH_SUFFIXES - "include" + HINTS "${netCDF_C_INCLUDE_DIR}" "${NCXX4_HINTS_INCLUDE_DIR}" + "${NCXX4_HINTS_PREFIX}" "${NCXX4_CONFIG_LOCATION}" + PATH_SUFFIXES "include" +) +if(netCDFCxx_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " netCDF_CXX_INCLUDE_DIR = ${netCDF_CXX_INCLUDE_DIR}" + " NCXX4_HINTS_INCLUDE_DIR = ${NCXX4_HINTS_INCLUDE_DIR}" + " NCXX4_HINTS_PREFIX = ${NCXX4_HINTS_PREFIX}" ) -if (netCDFCxx_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " netCDF_CXX_INCLUDE_DIR = ${netCDF_CXX_INCLUDE_DIR}" - " NCXX4_HINTS_INCLUDE_DIR = ${NCXX4_HINTS_INCLUDE_DIR}" - " NCXX4_HINTS_PREFIX = ${NCXX4_HINTS_PREFIX}" - ) endif() mark_as_advanced(netCDF_CXX_INCLUDE_DIR) -find_library(netCDF_CXX_LIBRARY +find_library( + netCDF_CXX_LIBRARY NAMES netcdf_c++4 netcdf-cxx4 DOC "netCDF C++ library" - HINTS - "${NCXX4_HINTS_INCLUDE_DIR}" - "${NCXX4_HINTS_PREFIX}" - "${NCXX4_CONFIG_LOCATION}" - PATH_SUFFIXES - "lib" "lib64" + HINTS "${NCXX4_HINTS_INCLUDE_DIR}" "${NCXX4_HINTS_PREFIX}" + "${NCXX4_CONFIG_LOCATION}" + PATH_SUFFIXES "lib" "lib64" +) +if(netCDFCxx_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " netCDF_CXX_LIBRARY = ${netCDF_CXX_LIBRARY}" + " NCXX4_HINTS_INCLUDE_DIR = ${NCXX4_HINTS_INCLUDE_DIR}" + " NCXX4_HINTS_PREFIX = ${NCXX4_HINTS_PREFIX}" ) -if (netCDFCxx_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " netCDF_CXX_LIBRARY = ${netCDF_CXX_LIBRARY}" - " NCXX4_HINTS_INCLUDE_DIR = ${NCXX4_HINTS_INCLUDE_DIR}" - " NCXX4_HINTS_PREFIX = ${NCXX4_HINTS_PREFIX}" - ) endif() mark_as_advanced(netCDF_CXX_LIBRARY) bout_inspect_netcdf_config(_ncxx4_version "${NCXX4_CONFIG}" "--version") -if (_ncxx4_version) +if(_ncxx4_version) # Change to lower case before matching, to avoid case problems string(TOLOWER "${_ncxx4_version}" _ncxx4_version_lower) - string(REGEX REPLACE "netcdf-cxx4 \([0-9]+\\.[0-9]+\\.[0-9]+\).*" "\\1" netCDFCxx_VERSION "${_ncxx4_version_lower}") + string(REGEX REPLACE "netcdf-cxx4 \([0-9]+\\.[0-9]+\\.[0-9]+\).*" "\\1" + netCDFCxx_VERSION "${_ncxx4_version_lower}" + ) message(STATUS "Found netCDFCxx version ${netCDFCxx_VERSION}") -else () +else() message(WARNING "Couldn't get NetCDF version") endif() @@ -121,19 +122,23 @@ unset(_netcdf_version_minor) unset(_netcdf_version_patch) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(netCDFCxx +find_package_handle_standard_args( + netCDFCxx REQUIRED_VARS netCDF_CXX_LIBRARY netCDF_CXX_INCLUDE_DIR - VERSION_VAR netCDFCxx_VERSION) + VERSION_VAR netCDFCxx_VERSION +) -if (netCDFCxx_FOUND) +if(netCDFCxx_FOUND) set(netCDFCxx_INCLUDE_DIRS "${netCDF_CXX_INCLUDE_DIR}") set(netCDFCxx_LIBRARIES "${netCDF_CXX_LIBRARY}") - if (NOT TARGET netCDF::netcdf-cxx4) + if(NOT TARGET netCDF::netcdf-cxx4) add_library(netCDF::netcdf-cxx4 UNKNOWN IMPORTED) - set_target_properties(netCDF::netcdf-cxx4 PROPERTIES - IMPORTED_LINK_INTERFACE_LIBRARIES netCDF::netcdf - IMPORTED_LOCATION "${netCDF_CXX_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${netCDF_CXX_INCLUDE_DIR}") - endif () -endif () + set_target_properties( + netCDF::netcdf-cxx4 + PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES netCDF::netcdf + IMPORTED_LOCATION "${netCDF_CXX_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${netCDF_CXX_INCLUDE_DIR}" + ) + endif() +endif() diff --git a/cmake/GenerateDateTimeFile.cmake b/cmake/GenerateDateTimeFile.cmake index ef48fc4638..8ed742b31a 100644 --- a/cmake/GenerateDateTimeFile.cmake +++ b/cmake/GenerateDateTimeFile.cmake @@ -2,6 +2,9 @@ # compilation date and time as variables set(bout_date_time_file - "const char* boutcompiledate{__DATE__}; const char* boutcompiletime{__TIME__};") + "const char* boutcompiledate{__DATE__}; const char* boutcompiletime{__TIME__};" +) -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bout++-time.cxx" "${bout_date_time_file}") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bout++-time.cxx" + "${bout_date_time_file}" +) diff --git a/cmake/GenerateGitMetadata.cmake b/cmake/GenerateGitMetadata.cmake new file mode 100644 index 0000000000..f38bde80ae --- /dev/null +++ b/cmake/GenerateGitMetadata.cmake @@ -0,0 +1,106 @@ +function(escape_cxx_string input output) + set(value "${input}") + string(REPLACE "\\" "\\\\" value "${value}") + string(REPLACE "\"" "\\\"" value "${value}") + string(REPLACE "\r" "" value "${value}") + string(REPLACE "\n" "\\n\"\n\"" value "${value}") + set(${output} + "${value}" + PARENT_SCOPE + ) +endfunction() + +set(git_metadata_available false) +set(git_dirty false) +set(git_diff "") + +if(NOT DEFINED OUTPUT_FILE) + message(FATAL_ERROR "OUTPUT_FILE must be set") +endif() +if(NOT DEFINED SOURCE_DIR) + message(FATAL_ERROR "SOURCE_DIR must be set") +endif() + +if(NOT DEFINED GIT_EXECUTABLE OR GIT_EXECUTABLE STREQUAL "") + find_program(GIT_EXECUTABLE git) +endif() + +if(GIT_EXECUTABLE) + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse --is-inside-work-tree + WORKING_DIRECTORY "${SOURCE_DIR}" + RESULT_VARIABLE git_repo_result + OUTPUT_VARIABLE git_repo_output + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(git_repo_result EQUAL 0 AND git_repo_output STREQUAL "true") + set(git_metadata_available true) + + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse --verify HEAD + WORKING_DIRECTORY "${SOURCE_DIR}" + RESULT_VARIABLE git_head_result + OUTPUT_QUIET ERROR_QUIET + ) + + if(git_head_result EQUAL 0) + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff --no-ext-diff --binary HEAD -- + WORKING_DIRECTORY "${SOURCE_DIR}" + RESULT_VARIABLE git_diff_result + OUTPUT_VARIABLE git_diff + ERROR_QUIET + ) + if(NOT git_diff_result EQUAL 0) + set(git_diff "") + endif() + else() + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff --no-ext-diff --binary --cached -- + WORKING_DIRECTORY "${SOURCE_DIR}" + RESULT_VARIABLE git_cached_diff_result + OUTPUT_VARIABLE git_cached_diff + ERROR_QUIET + ) + if(NOT git_cached_diff_result EQUAL 0) + set(git_cached_diff "git diff unavailable") + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff --no-ext-diff --binary -- + WORKING_DIRECTORY "${SOURCE_DIR}" + RESULT_VARIABLE git_worktree_diff_result + OUTPUT_VARIABLE git_worktree_diff + ERROR_QUIET + ) + if(NOT git_worktree_diff_result EQUAL 0) + set(git_worktree_diff "") + endif() + + set(git_diff "${git_cached_diff}") + if(NOT git_cached_diff STREQUAL "" AND NOT git_worktree_diff STREQUAL "") + string(APPEND git_diff "\n") + endif() + string(APPEND git_diff "${git_worktree_diff}") + endif() + + if(NOT git_diff STREQUAL "") + set(git_dirty true) + endif() + endif() +endif() + +escape_cxx_string("${git_diff}" git_diff_escaped) + +set(output_tmp "${OUTPUT_FILE}.tmp") + +configure_file( + "${CMAKE_CURRENT_LIST_DIR}/git_metadata.cxx.in" "${output_tmp}" @ONLY +) + +execute_process( + COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${output_tmp}" + "${OUTPUT_FILE}" +) +execute_process(COMMAND "${CMAKE_COMMAND}" -E rm -f "${output_tmp}") diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake index 8ab03bc5f0..33f95dd589 100644 --- a/cmake/GetGitRevisionDescription.cmake +++ b/cmake/GetGitRevisionDescription.cmake @@ -37,7 +37,7 @@ # http://www.boost.org/LICENSE_1_0.txt) if(__get_git_revision_description) - return() + return() endif() set(__get_git_revision_description YES) @@ -46,123 +46,152 @@ set(__get_git_revision_description YES) get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) function(get_git_head_revision _refspecvar _hashvar) - set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories - set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") - get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) - if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) - # We have reached the root directory, we are not in git - set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - return() - endif() - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - endwhile() - # check if this is a submodule - if(NOT IS_DIRECTORY ${GIT_DIR}) - file(READ ${GIT_DIR} submodule) - string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) - get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) - get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) - endif() - set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") - if(NOT EXISTS "${GIT_DATA}") - file(MAKE_DIRECTORY "${GIT_DATA}") - endif() + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE + ) + set(${_hashvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE + ) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component( + GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE + ) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() - if(NOT EXISTS "${GIT_DIR}/HEAD") - return() - endif() - set(HEAD_FILE "${GIT_DATA}/HEAD") - configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) - configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" - "${GIT_DATA}/grabRef.cmake" - @ONLY) - include("${GIT_DATA}/grabRef.cmake") + configure_file( + "${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" @ONLY + ) + include("${GIT_DATA}/grabRef.cmake") - set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) - set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) + set(${_refspecvar} + "${HEAD_REF}" + PARENT_SCOPE + ) + set(${_hashvar} + "${HEAD_HASH}" + PARENT_SCOPE + ) endfunction() function(git_describe _var) - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - get_git_head_revision(refspec hash) - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - if(NOT hash) - set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - return() - endif() + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE + ) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE + ) + return() + endif() - # TODO sanitize - #if((${ARGN}" MATCHES "&&") OR - # (ARGN MATCHES "||") OR - # (ARGN MATCHES "\\;")) - # message("Please report the following error to the project!") - # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") - #endif() + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() - #message(STATUS "Arguments to execute_process: ${ARGN}") + #message(STATUS "Arguments to execute_process: ${ARGN}") - execute_process(COMMAND - "${GIT_EXECUTABLE}" - describe - ${hash} - ${ARGN} - WORKING_DIRECTORY - "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT res EQUAL 0) - set(out "${out}-${res}-NOTFOUND") - endif() + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe ${hash} ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() - set(${_var} "${out}" PARENT_SCOPE) + set(${_var} + "${out}" + PARENT_SCOPE + ) endfunction() function(git_get_exact_tag _var) - git_describe(out --exact-match ${ARGN}) - set(${_var} "${out}" PARENT_SCOPE) + git_describe(out --exact-match ${ARGN}) + set(${_var} + "${out}" + PARENT_SCOPE + ) endfunction() function(git_local_changes _var) - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - get_git_head_revision(refspec hash) - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - if(NOT hash) - set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - return() - endif() + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE + ) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE + ) + return() + endif() - execute_process(COMMAND - "${GIT_EXECUTABLE}" - diff-index --quiet HEAD -- - WORKING_DIRECTORY - "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(res EQUAL 0) - set(${_var} "CLEAN" PARENT_SCOPE) - else() - set(${_var} "DIRTY" PARENT_SCOPE) - endif() + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD -- + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(res EQUAL 0) + set(${_var} + "CLEAN" + PARENT_SCOPE + ) + else() + set(${_var} + "DIRTY" + PARENT_SCOPE + ) + endif() endfunction() diff --git a/cmake/ResolveCompilerPaths.cmake b/cmake/ResolveCompilerPaths.cmake index 54787fa38f..d4274496df 100644 --- a/cmake/ResolveCompilerPaths.cmake +++ b/cmake/ResolveCompilerPaths.cmake @@ -38,68 +38,77 @@ # # assuming both directories exist. # Note: as currently implemented, the -I/string will be picked up mistakenly (cry, cry) -include (CorrectWindowsPaths) +include(CorrectWindowsPaths) -macro (RESOLVE_LIBRARIES LIBS LINK_LINE) - string (REGEX MATCHALL "((-L|-l|-Wl)([^\" ]+|\"[^\"]+\")|[^\" ]+\\.(a|so|dll|lib))" _all_tokens "${LINK_LINE}") - set (_libs_found "") - set (_directory_list "") - foreach (token ${_all_tokens}) - if (token MATCHES "-L([^\" ]+|\"[^\"]+\")") +macro(RESOLVE_LIBRARIES LIBS LINK_LINE) + string(REGEX MATCHALL + "((-L|-l|-Wl)([^\" ]+|\"[^\"]+\")|[^\" ]+\\.(a|so|dll|lib))" + _all_tokens "${LINK_LINE}" + ) + set(_libs_found "") + set(_directory_list "") + foreach(token ${_all_tokens}) + if(token MATCHES "-L([^\" ]+|\"[^\"]+\")") # If it's a library path, add it to the list - string (REGEX REPLACE "^-L" "" token ${token}) - string (REGEX REPLACE "//" "/" token ${token}) + string(REGEX REPLACE "^-L" "" token ${token}) + string(REGEX REPLACE "//" "/" token ${token}) convert_cygwin_path(token) - list (APPEND _directory_list ${token}) - elseif (token MATCHES "^(-l([^\" ]+|\"[^\"]+\")|[^\" ]+\\.(a|so|dll|lib))") + list(APPEND _directory_list ${token}) + elseif(token MATCHES "^(-l([^\" ]+|\"[^\"]+\")|[^\" ]+\\.(a|so|dll|lib))") # It's a library, resolve the path by looking in the list and then (by default) in system directories - if (WIN32) #windows expects "libfoo", linux expects "foo" - string (REGEX REPLACE "^-l" "lib" token ${token}) - else (WIN32) - string (REGEX REPLACE "^-l" "" token ${token}) - endif (WIN32) - set (_root "") - if (token MATCHES "^/") # We have an absolute path + if(WIN32) #windows expects "libfoo", linux expects "foo" + string(REGEX REPLACE "^-l" "lib" token ${token}) + else(WIN32) + string(REGEX REPLACE "^-l" "" token ${token}) + endif(WIN32) + set(_root "") + if(token MATCHES "^/") # We have an absolute path #separate into a path and a library name: - string (REGEX MATCH "[^/]*\\.(a|so|dll|lib)$" libname ${token}) - string (REGEX MATCH ".*[^${libname}$]" libpath ${token}) + string(REGEX MATCH "[^/]*\\.(a|so|dll|lib)$" libname ${token}) + string(REGEX MATCH ".*[^${libname}$]" libpath ${token}) convert_cygwin_path(libpath) - set (_directory_list ${_directory_list} ${libpath}) - set (token ${libname}) - endif (token MATCHES "^/") - set (_lib "NOTFOUND" CACHE FILEPATH "Cleared" FORCE) - find_library (_lib ${token} HINTS ${_directory_list} ${_root}) - if (_lib) - string (REPLACE "//" "/" _lib ${_lib}) - list (APPEND _libs_found ${_lib}) - else (_lib) - message (STATUS "Unable to find library ${token}") - endif (_lib) - endif (token MATCHES "-L([^\" ]+|\"[^\"]+\")") - endforeach (token) - set (_lib "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE) + set(_directory_list ${_directory_list} ${libpath}) + set(token ${libname}) + endif(token MATCHES "^/") + set(_lib + "NOTFOUND" + CACHE FILEPATH "Cleared" FORCE + ) + find_library(_lib ${token} HINTS ${_directory_list} ${_root}) + if(_lib) + string(REPLACE "//" "/" _lib ${_lib}) + list(APPEND _libs_found ${_lib}) + else(_lib) + message(STATUS "Unable to find library ${token}") + endif(_lib) + endif(token MATCHES "-L([^\" ]+|\"[^\"]+\")") + endforeach(token) + set(_lib + "NOTFOUND" + CACHE INTERNAL "Scratch variable" FORCE + ) # only the LAST occurence of each library is required since there should be no circular dependencies - if (_libs_found) - list (REVERSE _libs_found) - list (REMOVE_DUPLICATES _libs_found) - list (REVERSE _libs_found) - endif (_libs_found) - set (${LIBS} "${_libs_found}") -endmacro (RESOLVE_LIBRARIES) + if(_libs_found) + list(REVERSE _libs_found) + list(REMOVE_DUPLICATES _libs_found) + list(REVERSE _libs_found) + endif(_libs_found) + set(${LIBS} "${_libs_found}") +endmacro(RESOLVE_LIBRARIES) -macro (RESOLVE_INCLUDES INCS COMPILE_LINE) - string (REGEX MATCHALL "-I([^\" ]+|\"[^\"]+\")" _all_tokens "${COMPILE_LINE}") - set (_incs_found "") - foreach (token ${_all_tokens}) - string (REGEX REPLACE "^-I" "" token ${token}) - string (REGEX REPLACE "//" "/" token ${token}) +macro(RESOLVE_INCLUDES INCS COMPILE_LINE) + string(REGEX MATCHALL "-I([^\" ]+|\"[^\"]+\")" _all_tokens "${COMPILE_LINE}") + set(_incs_found "") + foreach(token ${_all_tokens}) + string(REGEX REPLACE "^-I" "" token ${token}) + string(REGEX REPLACE "//" "/" token ${token}) convert_cygwin_path(token) - if (EXISTS ${token}) - list (APPEND _incs_found ${token}) - else (EXISTS ${token}) - message (STATUS "Include directory ${token} does not exist") - endif (EXISTS ${token}) - endforeach (token) - list (REMOVE_DUPLICATES _incs_found) - set (${INCS} "${_incs_found}") -endmacro (RESOLVE_INCLUDES) + if(EXISTS ${token}) + list(APPEND _incs_found ${token}) + else(EXISTS ${token}) + message(STATUS "Include directory ${token} does not exist") + endif(EXISTS ${token}) + endforeach(token) + list(REMOVE_DUPLICATES _incs_found) + set(${INCS} "${_incs_found}") +endmacro(RESOLVE_INCLUDES) diff --git a/cmake/Sanitizers.cmake b/cmake/Sanitizers.cmake index 715a08ab88..aab58d6f70 100644 --- a/cmake/Sanitizers.cmake +++ b/cmake/Sanitizers.cmake @@ -4,7 +4,9 @@ function(enable_sanitizers target_name) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + ".*Clang" + ) option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) message(STATUS "Enable coverage: ${ENABLE_COVERAGE}") @@ -17,33 +19,40 @@ function(enable_sanitizers target_name) find_program(genhtml_FOUND genhtml) message(STATUS "Looking for genhtml: ${genhtml_FOUND}") - if (lcov_FOUND AND genhtml_FOUND) - set(COVERAGE_NAME coverage CACHE STRING "Name of coverage output file") + if(lcov_FOUND AND genhtml_FOUND) + set(COVERAGE_NAME + coverage + CACHE STRING "Name of coverage output file" + ) set(COVERAGE_FILE "${COVERAGE_NAME}.info") - set(COVERAGE_MSG "Open file://${PROJECT_SOURCE_DIR}/${COVERAGE_NAME}/index.html in your browser to view coverage HTML output") + set(COVERAGE_MSG + "Open file://${PROJECT_SOURCE_DIR}/${COVERAGE_NAME}/index.html in your browser to view coverage HTML output" + ) - add_custom_target(code-coverage-capture + add_custom_target( + code-coverage-capture COMMAND - lcov -c --directory "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/bout++.dir/src" - --output-file "${COVERAGE_FILE}" - COMMAND - genhtml --output-directory "${COVERAGE_NAME}" --demangle-cpp --legend --show-details "${COVERAGE_FILE}" - COMMAND - "${CMAKE_COMMAND}" -E echo ${COVERAGE_MSG} + lcov -c --directory + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/bout++.dir/src" + --output-file "${COVERAGE_FILE}" + COMMAND genhtml --output-directory "${COVERAGE_NAME}" --demangle-cpp + --legend --show-details "${COVERAGE_FILE}" + COMMAND "${CMAKE_COMMAND}" -E echo ${COVERAGE_MSG} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Capturing coverage information" - BYPRODUCTS - "${COVERAGE_FILE}" - "${COVERAGE_NAME}/index.html" - ) + BYPRODUCTS "${COVERAGE_FILE}" "${COVERAGE_NAME}/index.html" + ) - add_custom_target(code-coverage-clean - COMMAND - lcov --zerocounters + add_custom_target( + code-coverage-clean + COMMAND lcov --zerocounters COMMENT "Cleaning coverage information" - ) + ) else() - message(FATAL_ERROR "Coverage enabled, but coverage-capture not available. Please install lcov") + message( + FATAL_ERROR + "Coverage enabled, but coverage-capture not available. Please install lcov" + ) endif() endif() @@ -60,7 +69,9 @@ function(enable_sanitizers target_name) list(APPEND SANITIZERS "leak") endif() - option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" FALSE) + option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR + "Enable undefined behavior sanitizer" FALSE + ) if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR) list(APPEND SANITIZERS "undefined") endif() @@ -68,7 +79,10 @@ function(enable_sanitizers target_name) option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE) if(ENABLE_SANITIZER_THREAD) if("address" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS) - message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled") + message( + WARNING + "Thread sanitizer does not work with Address and Leak sanitizer enabled" + ) else() list(APPEND SANITIZERS "thread") endif() @@ -78,32 +92,40 @@ function(enable_sanitizers target_name) if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") if("address" IN_LIST SANITIZERS OR "thread" IN_LIST SANITIZERS - OR "leak" IN_LIST SANITIZERS) - message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled") + OR "leak" IN_LIST SANITIZERS + ) + message( + WARNING + "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled" + ) else() list(APPEND SANITIZERS "memory") endif() endif() - list( - JOIN - SANITIZERS - "," - LIST_OF_SANITIZERS) + list(JOIN SANITIZERS "," LIST_OF_SANITIZERS) endif() # Default value gets overridden below - set(BOUT_USE_SANITIZERS "None" PARENT_SCOPE) + set(BOUT_USE_SANITIZERS + "None" + PARENT_SCOPE + ) if(LIST_OF_SANITIZERS) - if(NOT - "${LIST_OF_SANITIZERS}" - STREQUAL - "") - set(BOUT_USE_SANITIZERS ${LIST_OF_SANITIZERS} PARENT_SCOPE) - target_compile_options(${target_name} PUBLIC -fsanitize=${LIST_OF_SANITIZERS} -fno-omit-frame-pointer) - target_link_options(${target_name} PUBLIC -fsanitize=${LIST_OF_SANITIZERS}) + if(NOT "${LIST_OF_SANITIZERS}" STREQUAL "") + set(BOUT_USE_SANITIZERS + ${LIST_OF_SANITIZERS} + PARENT_SCOPE + ) + target_compile_options( + ${target_name} PUBLIC -fsanitize=${LIST_OF_SANITIZERS} + -fno-omit-frame-pointer + ) + target_link_options( + ${target_name} PUBLIC -fsanitize=${LIST_OF_SANITIZERS} + ) endif() endif() diff --git a/cmake/SetupBOUTThirdParty.cmake b/cmake/SetupBOUTThirdParty.cmake index 88fee587f5..c5e890d4c5 100644 --- a/cmake/SetupBOUTThirdParty.cmake +++ b/cmake/SetupBOUTThirdParty.cmake @@ -1,12 +1,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") # determined in SetupCompilers.cmake -if (BOUT_USE_MPI) +if(BOUT_USE_MPI) target_link_libraries(bout++ PUBLIC MPI::MPI_CXX) -endif () +endif() # determined in SetupCompilers.cmake -if (BOUT_USE_OPENMP) +if(BOUT_USE_OPENMP) target_link_libraries(bout++ PUBLIC OpenMP::OpenMP_CXX) set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} -fopenmp") set(CONFIG_LDFLAGS_SHARED "${CONFIG_LDFLAGS_SHARED} -fopenmp") @@ -14,7 +14,7 @@ if (BOUT_USE_OPENMP) endif() # determined in SetupCompilers.cmake -if (BOUT_HAS_CUDA) +if(BOUT_HAS_CUDA) enable_language(CUDA) message(STATUS "BOUT_HAS_CUDA ${CMAKE_CUDA_COMPILER}") @@ -29,58 +29,65 @@ if (BOUT_HAS_CUDA) set_target_properties(bout++ PROPERTIES CUDA_SEPARABLE_COMPILATION ON) set_target_properties(bout++ PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(bout++ PROPERTIES LINKER_LANGUAGE CUDA) -endif () +endif() # Caliper option(BOUT_ENABLE_CALIPER "Enable Caliper" OFF) -if (BOUT_ENABLE_CALIPER) +if(BOUT_ENABLE_CALIPER) find_package(caliper REQUIRED) target_include_directories(bout++ PUBLIC ${caliper_INCLUDE_DIR}) target_link_libraries(bout++ PUBLIC caliper) -endif () +endif() set(BOUT_HAS_CALIPER ${BOUT_ENABLE_CALIPER}) # UMPIRE option(BOUT_ENABLE_UMPIRE "Enable UMPIRE memory management" OFF) -if (BOUT_ENABLE_UMPIRE) +if(BOUT_ENABLE_UMPIRE) find_package(UMPIRE REQUIRED) target_include_directories(bout++ PUBLIC ${UMPIRE_INCLUDE_DIRS}/include) target_link_libraries(bout++ PUBLIC umpire) -endif () +endif() set(BOUT_HAS_UMPIRE ${BOUT_ENABLE_UMPIRE}) # RAJA option(BOUT_ENABLE_RAJA "Enable RAJA" OFF) -if (BOUT_ENABLE_RAJA) +if(BOUT_ENABLE_RAJA) find_package(RAJA REQUIRED) - message(STATUS "RAJA_CONFIG:" ${RAJA_CONFIG}) + message(STATUS "RAJA_CONFIG:" ${RAJA_CONFIG}) string(FIND ${RAJA_CONFIG} "raja" loc) math(EXPR value "${loc} + 5" OUTPUT_FORMAT DECIMAL) - string(SUBSTRING ${RAJA_CONFIG} 0 ${value} RAJA_PATH) + string(SUBSTRING ${RAJA_CONFIG} 0 ${value} RAJA_PATH) message(STATUS "RAJA_PATH" ${RAJA_PATH}) target_include_directories(bout++ PUBLIC ${RAJA_PATH}/include) target_link_libraries(bout++ PUBLIC RAJA) -endif () +endif() set(BOUT_HAS_RAJA ${BOUT_ENABLE_RAJA}) # Hypre option(BOUT_USE_HYPRE "Enable support for Hypre solvers" OFF) -if (BOUT_USE_HYPRE) +if(BOUT_USE_HYPRE) enable_language(C) find_package(HYPRE REQUIRED) target_link_libraries(bout++ PUBLIC HYPRE::HYPRE) - if (HYPRE_WITH_CUDA AND BOUT_HAS_CUDA) - target_compile_definitions(bout++ PUBLIC "HYPRE_USING_CUDA;HYPRE_USING_UNIFIED_MEMORY") - target_link_libraries(bout++ PUBLIC CUDA::cusparse CUDA::curand CUDA::culibos CUDA::cublas CUDA::cublasLt) - endif () -endif () + if(HYPRE_WITH_CUDA AND BOUT_HAS_CUDA) + target_compile_definitions( + bout++ PUBLIC "HYPRE_USING_CUDA;HYPRE_USING_UNIFIED_MEMORY" + ) + target_link_libraries( + bout++ PUBLIC CUDA::cusparse CUDA::curand CUDA::culibos CUDA::cublas + CUDA::cublasLt + ) + endif() +endif() message(STATUS "HYPRE support: ${BOUT_USE_HYPRE}") set(BOUT_HAS_HYPRE ${BOUT_USE_HYPRE}) # PETSc -option(BOUT_USE_PETSC "Enable support for PETSc time solvers and inversions" OFF) -if (BOUT_USE_PETSC) - if (NOT CMAKE_SYSTEM_NAME STREQUAL "CrayLinuxEnvironment") +option(BOUT_USE_PETSC "Enable support for PETSc time solvers and inversions" + OFF +) +if(BOUT_USE_PETSC) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "CrayLinuxEnvironment") # Cray wrappers sort this out for us find_package(PETSc REQUIRED) target_link_libraries(bout++ PUBLIC PETSc::PETSc) @@ -94,28 +101,44 @@ endif() message(STATUS "PETSc support: ${BOUT_USE_PETSC}") set(BOUT_HAS_PETSC ${BOUT_USE_PETSC}) - -cmake_dependent_option(BOUT_USE_SYSTEM_MPARK_VARIANT "Use external installation of mpark.variant" OFF - "BOUT_UPDATE_GIT_SUBMODULE OR EXISTS ${PROJECT_SOURCE_DIR}/externalpackages/mpark.variant/CMakeLists.txt" ON) +cmake_dependent_option( + BOUT_USE_SYSTEM_MPARK_VARIANT + "Use external installation of mpark.variant" + OFF + "BOUT_UPDATE_GIT_SUBMODULE OR EXISTS ${PROJECT_SOURCE_DIR}/externalpackages/mpark.variant/CMakeLists.txt" + ON +) if(BOUT_USE_SYSTEM_MPARK_VARIANT) message(STATUS "Using external mpark.variant") find_package(mpark_variant REQUIRED) - get_target_property(MPARK_VARIANT_INCLUDE_PATH mpark_variant INTERFACE_INCLUDE_DIRECTORIES) + get_target_property( + MPARK_VARIANT_INCLUDE_PATH mpark_variant INTERFACE_INCLUDE_DIRECTORIES + ) else() message(STATUS "Using mpark.variant submodule") bout_update_submodules() add_subdirectory(externalpackages/mpark.variant) if(NOT TARGET mpark_variant) - message(FATAL_ERROR "mpark_variant not found! Have you disabled the git submodules (BOUT_UPDATE_GIT_SUBMODULE)?") + message( + FATAL_ERROR + "mpark_variant not found! Have you disabled the git submodules (BOUT_UPDATE_GIT_SUBMODULE)?" + ) endif() - set(MPARK_VARIANT_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externalpackages/mpark.variant/include") + set(MPARK_VARIANT_INCLUDE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/externalpackages/mpark.variant/include" + ) set(CONFIG_CFLAGS "${CONFIG_CFLAGS} -I\${MPARK_VARIANT_INCLUDE_PATH}") endif() target_link_libraries(bout++ PUBLIC mpark_variant) -cmake_dependent_option(BOUT_USE_SYSTEM_FMT "Use external installation of fmt" OFF - "BOUT_UPDATE_GIT_SUBMODULE OR EXISTS ${PROJECT_SOURCE_DIR}/externalpackages/fmt/CMakeLists.txt" ON) +cmake_dependent_option( + BOUT_USE_SYSTEM_FMT + "Use external installation of fmt" + OFF + "BOUT_UPDATE_GIT_SUBMODULE OR EXISTS ${PROJECT_SOURCE_DIR}/externalpackages/fmt/CMakeLists.txt" + ON +) if(BOUT_USE_SYSTEM_FMT) message(STATUS "Using external fmt") @@ -125,32 +148,46 @@ else() message(STATUS "Using fmt submodule") bout_update_submodules() # Need to install fmt alongside BOUT++ - set(FMT_INSTALL ON CACHE BOOL "") - set(FMT_DEBUG_POSTFIX "" CACHE STRING "") + set(FMT_INSTALL + ON + CACHE BOOL "" + ) + set(FMT_DEBUG_POSTFIX + "" + CACHE STRING "" + ) add_subdirectory(externalpackages/fmt) if(NOT TARGET fmt::fmt) - message(FATAL_ERROR "fmt not found! Have you disabled the git submodules (BOUT_UPDATE_GIT_SUBMODULE)?") + message( + FATAL_ERROR + "fmt not found! Have you disabled the git submodules (BOUT_UPDATE_GIT_SUBMODULE)?" + ) endif() # Build the library in /lib: this makes updating the path # for bout-config much easier - set_target_properties(fmt PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") - set(FMT_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externalpackages/fmt/include") + set_target_properties( + fmt PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" + ) + set(FMT_INCLUDE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/externalpackages/fmt/include" + ) set(CONFIG_CFLAGS "${CONFIG_CFLAGS} -I\${FMT_INCLUDE_PATH}") set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} -lfmt") endif() target_link_libraries(bout++ PUBLIC fmt::fmt) option(BOUT_USE_PVODE "Enable support for bundled PVODE" ON) -if (BOUT_USE_PVODE) +if(BOUT_USE_PVODE) add_subdirectory(externalpackages/PVODE) target_link_libraries(bout++ PUBLIC pvode pvpre) # Build the libraries in /lib: this makes updating the # path for bout-config much easier - set_target_properties(pvode pvpre PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") + set_target_properties( + pvode pvpre + PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" + ) set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} -lpvode -lpvpre") endif() message(STATUS "PVODE support: ${BOUT_USE_PVODE}") @@ -158,25 +195,30 @@ set(BOUT_HAS_PVODE ${BOUT_USE_PVODE}) option(BOUT_USE_NETCDF "Enable support for NetCDF output" ON) option(BOUT_DOWNLOAD_NETCDF_CXX4 "Download and build netCDF-cxx4" OFF) -if (BOUT_USE_NETCDF) - if (BOUT_DOWNLOAD_NETCDF_CXX4) +if(BOUT_USE_NETCDF) + if(BOUT_DOWNLOAD_NETCDF_CXX4) message(STATUS "Downloading and configuring NetCDF-cxx4") include(FetchContent) FetchContent_Declare( netcdf-cxx4 - GIT_REPOSITORY https://github.com/ZedThree/netcdf-cxx4 - GIT_TAG "ad3e50953190615cb69dcc8a4652f9a88a8499cf" - ) + GIT_REPOSITORY https://github.com/Unidata/netcdf-cxx4 + GIT_TAG "a43d6d4d415d407712c246faca553bd951730dc1" + ) # Don't build the netcdf tests, they have lots of warnings - set(NCXX_ENABLE_TESTS OFF CACHE BOOL "" FORCE) + set(NCXX_ENABLE_TESTS + OFF + CACHE BOOL "" FORCE + ) # Use our own FindnetCDF module which uses nc-config find_package(netCDF REQUIRED) FetchContent_MakeAvailable(netcdf-cxx4) target_link_libraries(bout++ PUBLIC netCDF::netcdf-cxx4) else() find_package(netCDFCxx) - if (netCDFCxx_FOUND) - set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${netCDF_CXX_LIBRARY} ${netCDF_LIBRARIES}") + if(netCDFCxx_FOUND) + set(CONFIG_LDFLAGS + "${CONFIG_LDFLAGS} ${netCDF_CXX_LIBRARY} ${netCDF_LIBRARIES}" + ) target_link_libraries(bout++ PUBLIC netCDF::netcdf-cxx4) else() find_package(PkgConfig REQUIRED) @@ -186,17 +228,23 @@ if (BOUT_USE_NETCDF) set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${NETCDF_LDFLAGS_STRING}") endif() endif() + if(netCDF_DIR) + set(netCDF_ROOT "${netCDF_DIR}") + endif() + if(netCDFCxx_DIR) + set(netCDFCxx_ROOT "${netCDFCxx_DIR}") + endif() endif() message(STATUS "NetCDF support: ${BOUT_USE_NETCDF}") set(BOUT_HAS_NETCDF ${BOUT_USE_NETCDF}) option(BOUT_USE_ADIOS2 "Enable support for ADIOS output" OFF) option(BOUT_DOWNLOAD_ADIOS2 "Download and build ADIOS2" OFF) -if (BOUT_USE_ADIOS2) +if(BOUT_USE_ADIOS2) enable_language(C) find_package(MPI REQUIRED COMPONENTS C) - if (BOUT_DOWNLOAD_ADIOS2) + if(BOUT_DOWNLOAD_ADIOS2) message(STATUS "Downloading and configuring ADIOS2") include(FetchContent) FetchContent_Declare( @@ -204,28 +252,60 @@ if (BOUT_USE_ADIOS2) GIT_REPOSITORY https://github.com/ornladios/ADIOS2.git GIT_TAG origin/master GIT_SHALLOW 1 - ) - set(ADIOS2_USE_MPI ON CACHE BOOL "" FORCE) - set(ADIOS2_USE_Fortran OFF CACHE BOOL "" FORCE) - set(ADIOS2_USE_Python OFF CACHE BOOL "" FORCE) - set(ADIOS2_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + ) + set(ADIOS2_USE_MPI + ON + CACHE BOOL "" FORCE + ) + set(ADIOS2_USE_Fortran + OFF + CACHE BOOL "" FORCE + ) + set(ADIOS2_USE_Python + OFF + CACHE BOOL "" FORCE + ) + set(ADIOS2_BUILD_EXAMPLES + OFF + CACHE BOOL "" FORCE + ) # Disable testing, or ADIOS will try to find or install GTEST - set(BUILD_TESTING OFF CACHE BOOL "" FORCE) + set(BUILD_TESTING + OFF + CACHE BOOL "" FORCE + ) # Note: SST requires but doesn't check at configure time - set(ADIOS2_USE_SST OFF CACHE BOOL "" FORCE) + set(ADIOS2_USE_SST + OFF + CACHE BOOL "" FORCE + ) FetchContent_MakeAvailable(adios2) message(STATUS "ADIOS2 done configuring") else() find_package(ADIOS2 REQUIRED) endif() - target_link_libraries(bout++ PUBLIC adios2::cxx11_mpi MPI::MPI_C) + + foreach(_adios2_candidate adios2::cxx_mpi adios2::cxx20_mpi adios2::cxx17_mpi + adios2::cxx11_mpi + ) + if(TARGET ${_adios2_candidate}) + set(_adios2_target ${_adios2_candidate}) + break() + endif() + endforeach() + + if(NOT DEFINED _adios2_target) + message(FATAL_ERROR "Could not find a usable ADIOS2 CXX CMake target. ") + endif() + message(STATUS "Using ADIOS2 CMake target: ${_adios2_target}") + + target_link_libraries(bout++ PUBLIC ${_adios2_target} MPI::MPI_C) endif() message(STATUS "ADIOS2 support: ${BOUT_USE_ADIOS2}") set(BOUT_HAS_ADIOS2 ${BOUT_USE_ADIOS2}) - option(BOUT_USE_FFTW "Enable support for FFTW" ON) -if (BOUT_USE_FFTW) +if(BOUT_USE_FFTW) find_package(FFTW REQUIRED) target_link_libraries(bout++ PUBLIC FFTW::FFTW) set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${FFTW_LIBRARIES}") @@ -238,15 +318,15 @@ option(BOUT_USE_LAPACK "Enable support for LAPACK" AUTO) set_property(CACHE BOUT_USE_LAPACK PROPERTY STRINGS ${ON_OFF_AUTO}) set(LAPACK_FOUND OFF) -if (BOUT_USE_LAPACK) - if (NOT CMAKE_SYSTEM_NAME STREQUAL "CrayLinuxEnvironment") +if(BOUT_USE_LAPACK) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "CrayLinuxEnvironment") # Cray wrappers sort this out for us - if (BOUT_USE_LAPACK STREQUAL ON) + if(BOUT_USE_LAPACK STREQUAL ON) find_package(LAPACK REQUIRED) else() find_package(LAPACK) endif() - if (LAPACK_FOUND) + if(LAPACK_FOUND) target_link_libraries(bout++ PUBLIC "${LAPACK_LIBRARIES}") string(JOIN " " CONFIG_LAPACK_LIBRARIES ${LAPACK_LIBRARIES}) set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${CONFIG_LAPACK_LIBRARIES}") @@ -258,7 +338,7 @@ message(STATUS "LAPACK support: ${LAPACK_FOUND}") set(BOUT_HAS_LAPACK ${LAPACK_FOUND}) option(BOUT_USE_SLEPC "Enable support for SLEPc eigen solver" OFF) -if (BOUT_USE_SLEPC) +if(BOUT_USE_SLEPC) find_package(SLEPc REQUIRED) target_link_libraries(bout++ PUBLIC SLEPc::SLEPc) string(JOIN " " CONFIG_SLEPC_LIBRARIES ${SLEPC_LIBRARIES}) @@ -269,41 +349,78 @@ set(BOUT_HAS_SLEPC ${BOUT_USE_SLEPC}) option(BOUT_DOWNLOAD_SUNDIALS "Download and build SUNDIALS" OFF) # Force BOUT_USE_SUNDIALS if we're downloading it! -cmake_dependent_option(BOUT_USE_SUNDIALS "Enable support for SUNDIALS time solvers" OFF - "NOT BOUT_DOWNLOAD_SUNDIALS" ON) -if (BOUT_USE_SUNDIALS) +cmake_dependent_option( + BOUT_USE_SUNDIALS "Enable support for SUNDIALS time solvers" OFF + "NOT BOUT_DOWNLOAD_SUNDIALS" ON +) +set(BOUT_HAS_SUNDIALS_MANYVECTOR OFF) +if(BOUT_USE_SUNDIALS) enable_language(C) - if (BOUT_DOWNLOAD_SUNDIALS) + if(BOUT_DOWNLOAD_SUNDIALS) message(STATUS "Downloading and configuring SUNDIALS") include(FetchContent) FetchContent_Declare( sundials GIT_REPOSITORY https://github.com/LLNL/sundials - GIT_TAG v7.4.0 - ) + GIT_TAG v7.9.0 + ) # Note: These are settings for building SUNDIALS - set(EXAMPLES_ENABLE_C OFF CACHE BOOL "" FORCE) - set(EXAMPLES_INSTALL OFF CACHE BOOL "" FORCE) - set(ENABLE_MPI ${BOUT_USE_MPI} CACHE BOOL "" FORCE) - set(ENABLE_OPENMP OFF CACHE BOOL "" FORCE) - if (BUILD_SHARED_LIBS) - set(BUILD_STATIC_LIBS OFF CACHE BOOL "" FORCE) + set(EXAMPLES_ENABLE_C + OFF + CACHE BOOL "" FORCE + ) + set(EXAMPLES_INSTALL + OFF + CACHE BOOL "" FORCE + ) + set(ENABLE_MPI + ${BOUT_USE_MPI} + CACHE BOOL "" FORCE + ) + set(ENABLE_OPENMP + ${BOUT_USE_OPENMP} + CACHE BOOL "" FORCE + ) + if(BUILD_SHARED_LIBS) + set(BUILD_STATIC_LIBS + OFF + CACHE BOOL "" FORCE + ) else() - set(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE) + set(BUILD_STATIC_LIBS + ON + CACHE BOOL "" FORCE + ) endif() FetchContent_MakeAvailable(sundials) message(STATUS "SUNDIALS done configuring") else() find_package(SUNDIALS REQUIRED) - if (SUNDIALS_VERSION VERSION_LESS 4.0.0) - message(FATAL_ERROR "SUNDIALS_VERSION 4.0.0 or newer is required. Found version ${SUNDIALS_VERSION}.") + if(SUNDIALS_VERSION VERSION_LESS 4.0.0) + message( + FATAL_ERROR + "SUNDIALS_VERSION 4.0.0 or newer is required. Found version ${SUNDIALS_VERSION}." + ) endif() endif() + if(SUNDIALS_DIR) + set(SUNDIALS_ROOT "${SUNDIALS_DIR}") + endif() target_link_libraries(bout++ PUBLIC SUNDIALS::nvecparallel) + if(TARGET SUNDIALS::nvecmanyvector) + target_link_libraries(bout++ PUBLIC SUNDIALS::nvecmanyvector) + set(BOUT_HAS_SUNDIALS_MANYVECTOR ON) + else() + message( + STATUS "SUNDIALS ManyVector support not found; custom N_Vector disabled" + ) + endif() target_link_libraries(bout++ PUBLIC SUNDIALS::cvode) target_link_libraries(bout++ PUBLIC SUNDIALS::ida) target_link_libraries(bout++ PUBLIC SUNDIALS::arkode) - set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${SUNDIALS_cvode_LIBRARY} ${SUNDIALS_ida_LIBRARY} ${SUNDIALS_arkode_LIBRARY} ${SUNDIALS_nvecparallel_LIBRARY}") + set(CONFIG_LDFLAGS + "${CONFIG_LDFLAGS} ${SUNDIALS_cvode_LIBRARY} ${SUNDIALS_ida_LIBRARY} ${SUNDIALS_arkode_LIBRARY} ${SUNDIALS_nvecparallel_LIBRARY}" + ) endif() message(STATUS "SUNDIALS support: ${BOUT_USE_SUNDIALS}") set(BOUT_HAS_SUNDIALS ${BOUT_USE_SUNDIALS}) @@ -312,46 +429,51 @@ set(BOUT_HAS_CVODE ${BOUT_USE_SUNDIALS}) set(BOUT_HAS_IDA ${BOUT_USE_SUNDIALS}) set(ON_OFF_AUTO ON OFF AUTO) -set(BOUT_USE_NLS AUTO CACHE STRING "Enable Native Language Support") +set(BOUT_USE_NLS + AUTO + CACHE STRING "Enable Native Language Support" +) set_property(CACHE BOUT_USE_NLS PROPERTY STRINGS ${ON_OFF_AUTO}) set(BOUT_HAS_GETTEXT OFF) -if (BOUT_USE_NLS) +if(BOUT_USE_NLS) find_package(Gettext) - if (GETTEXT_FOUND) + if(GETTEXT_FOUND) find_package(Intl) - if (Intl_FOUND) - target_link_libraries(bout++ - PUBLIC ${Intl_LIBRARIES}) - target_include_directories(bout++ - PUBLIC ${Intl_INCLUDE_DIRS}) + if(Intl_FOUND) + target_link_libraries(bout++ PUBLIC ${Intl_LIBRARIES}) + target_include_directories(bout++ PUBLIC ${Intl_INCLUDE_DIRS}) set(BOUT_HAS_GETTEXT ON) else() - if (NOT BOUT_USE_NLS STREQUAL "AUTO") - message(FATAL_ERROR "Intl not found but requested!") + if(NOT BOUT_USE_NLS STREQUAL "AUTO") + message(FATAL_ERROR "Intl not found but requested!") endif() endif() else() - if (NOT BOUT_USE_NLS STREQUAL "AUTO") + if(NOT BOUT_USE_NLS STREQUAL "AUTO") message(FATAL_ERROR "GETTEXT not found but requested!") endif() endif() endif() option(BOUT_USE_SCOREP "Enable support for Score-P based instrumentation" OFF) -if (BOUT_USE_SCOREP) - message(STATUS "Score-P support enabled. Please make sure you are calling CMake like so: +if(BOUT_USE_SCOREP) + message( + STATUS + "Score-P support enabled. Please make sure you are calling CMake like so: SCOREP_WRAPPER=off cmake -DCMAKE_C_COMPILER=scorep-mpicc -DCMAKE_CXX_COMPILER=scorep-mpicxx -") +" + ) endif() set(BOUT_HAS_SCOREP ${BOUT_USE_SCOREP}) -option(BOUT_USE_UUID_SYSTEM_GENERATOR "Enable support for using a system UUID generator" ON) -if (BOUT_USE_UUID_SYSTEM_GENERATOR) +option(BOUT_USE_UUID_SYSTEM_GENERATOR + "Enable support for using a system UUID generator" ON +) +if(BOUT_USE_UUID_SYSTEM_GENERATOR) find_package(Libuuid QUIET) - if (Libuuid_FOUND) - target_link_libraries(bout++ - PUBLIC Libuuid::libuuid) + if(Libuuid_FOUND) + target_link_libraries(bout++ PUBLIC Libuuid::libuuid) set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${Libuuid_LIBRARIES}") else() message(STATUS "libuuid not found, using fallback UUID generator") @@ -360,3 +482,43 @@ if (BOUT_USE_UUID_SYSTEM_GENERATOR) endif() message(STATUS "UUID_SYSTEM_GENERATOR: ${BOUT_USE_UUID_SYSTEM_GENERATOR}") set(BOUT_HAS_UUID_SYSTEM_GENERATOR ${BOUT_USE_UUID_SYSTEM_GENERATOR}) + +cmake_dependent_option( + BOUT_USE_SYSTEM_CPPTRACE + "Use external installation of cpptrace" + OFF + "BOUT_UPDATE_GIT_SUBMODULE OR EXISTS ${PROJECT_SOURCE_DIR}/externalpackages/cpptrace/CMakeLists.txt" + ON +) + +if(BOUT_USE_SYSTEM_CPPTRACE) + message(STATUS "Using external cpptrace") + find_package(cpptrace REQUIRED) + get_target_property( + CPPTRACE_INCLUDE_PATH cpptrace::cpptrace INTERFACE_INCLUDE_DIRECTORIES + ) +else() + message(STATUS "Using cpptrace submodule") + bout_update_submodules() + # Need a fork with some fixes for CMake + set(CPPTRACE_LIBDWARF_REPO + "https://github.com/ZedThree/libdwarf-lite.git" + CACHE STRING "" FORCE + ) + set(CPPTRACE_LIBDWARF_TAG + "ebe10a39afd56b8247de633bfe17666ad50ab95e" + CACHE STRING "" FORCE + ) + add_subdirectory(externalpackages/cpptrace) + if(NOT TARGET cpptrace::cpptrace) + message( + FATAL_ERROR + "cpptrace not found! Have you disabled the git submodules (BOUT_UPDATE_GIT_SUBMODULE)?" + ) + endif() + set(CPPTRACE_INCLUDE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/externalpackages/cpptrace/include" + ) +endif() +set(CONFIG_CFLAGS "${CONFIG_CFLAGS} -I\${CPPTRACE_INCLUDE_PATH}") +target_link_libraries(bout++ PUBLIC cpptrace::cpptrace) diff --git a/cmake/SetupCompilers.cmake b/cmake/SetupCompilers.cmake index 647cb20f75..fbe960b0f0 100644 --- a/cmake/SetupCompilers.cmake +++ b/cmake/SetupCompilers.cmake @@ -1,44 +1,58 @@ - # Note: Currently BOUT++ always needs MPI. This option just determines # whether the find_* routines are used option(BOUT_ENABLE_MPI "Enable MPI support" ON) if(BOUT_ENABLE_MPI) - # This might not be entirely sensible, but helps CMake to find the - # correct MPI, workaround for https://gitlab.kitware.com/cmake/cmake/issues/18895 - find_program(MPIEXEC_EXECUTABLE NAMES mpiexec mpirun) - find_package(MPI REQUIRED) -endif () + # This might not be entirely sensible, but helps CMake to find the + # correct MPI, workaround for https://gitlab.kitware.com/cmake/cmake/issues/18895 + find_program(MPIEXEC_EXECUTABLE NAMES mpiexec mpirun) + find_package(MPI REQUIRED) +endif() set(BOUT_USE_MPI ${BOUT_ENABLE_MPI}) option(BOUT_ENABLE_OPENMP "Enable OpenMP support" OFF) -set(BOUT_OPENMP_SCHEDULE static CACHE STRING "Set OpenMP schedule") -set_property(CACHE BOUT_OPENMP_SCHEDULE PROPERTY STRINGS static dynamic guided auto) -if (BOUT_ENABLE_OPENMP) +set(BOUT_OPENMP_SCHEDULE + static + CACHE STRING "Set OpenMP schedule" +) +set_property( + CACHE BOUT_OPENMP_SCHEDULE PROPERTY STRINGS static dynamic guided auto +) +if(BOUT_ENABLE_OPENMP) find_package(OpenMP REQUIRED) set(possible_openmp_schedules static dynamic guided auto) - if (NOT BOUT_OPENMP_SCHEDULE IN_LIST possible_openmp_schedules) - message(FATAL_ERROR "BOUT_OPENMP_SCHEDULE must be one of ${possible_openmp_schedules}; got ${BOUT_OPENMP_SCHEDULE}") + if(NOT BOUT_OPENMP_SCHEDULE IN_LIST possible_openmp_schedules) + message( + FATAL_ERROR + "BOUT_OPENMP_SCHEDULE must be one of ${possible_openmp_schedules}; got ${BOUT_OPENMP_SCHEDULE}" + ) endif() message(STATUS "OpenMP schedule: ${BOUT_OPENMP_SCHEDULE}") -endif () +endif() set(BOUT_USE_OPENMP ${BOUT_ENABLE_OPENMP}) message(STATUS "Enable OpenMP: ${BOUT_ENABLE_OPENMP}") option(BOUT_ENABLE_CUDA "Enable CUDA support" OFF) -set(CUDA_ARCH "compute_70,code=sm_70" CACHE STRING "CUDA architecture") +set(CUDA_ARCH + "compute_70,code=sm_70" + CACHE STRING "CUDA architecture" +) if(BOUT_ENABLE_CUDA) - # Set specific options for CUDA if enabled - enable_language(CUDA) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode arch=${CUDA_ARCH} -ccbin ${CMAKE_CXX_COMPILER}") - if (BOUT_ENABLE_RAJA) - # RAJA uses lambda expressions - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-extended-lambda --expt-relaxed-constexpr") - endif () + # Set specific options for CUDA if enabled + enable_language(CUDA) + set(CMAKE_CUDA_FLAGS + "${CMAKE_CUDA_FLAGS} -gencode arch=${CUDA_ARCH} -ccbin ${CMAKE_CXX_COMPILER}" + ) + if(BOUT_ENABLE_RAJA) + # RAJA uses lambda expressions + set(CMAKE_CUDA_FLAGS + "${CMAKE_CUDA_FLAGS} --expt-extended-lambda --expt-relaxed-constexpr" + ) + endif() -# TODO Ensure openmp flags are not enabled twice! - if (BOUT_ENABLE_OPENMP) - # CMAKE_CUDA_FLAGS does not pass OpenMP_CXX_FLAGS to the host compiler by default - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler ${OpenMP_CXX_FLAGS}") - endif () + # TODO Ensure openmp flags are not enabled twice! + if(BOUT_ENABLE_OPENMP) + # CMAKE_CUDA_FLAGS does not pass OpenMP_CXX_FLAGS to the host compiler by default + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler ${OpenMP_CXX_FLAGS}") + endif() endif() set(BOUT_HAS_CUDA ${BOUT_ENABLE_CUDA}) diff --git a/cmake/git_metadata.cxx.in b/cmake/git_metadata.cxx.in new file mode 100644 index 0000000000..fc8a5b1a2f --- /dev/null +++ b/cmake/git_metadata.cxx.in @@ -0,0 +1,16 @@ +#include "bout/git_metadata.hxx" + +namespace bout { +namespace version { +namespace { +constexpr bool git_metadata_available_value = @git_metadata_available@; +constexpr bool git_dirty_value = @git_dirty@; +constexpr char git_diff_value[] = +"@git_diff_escaped@"; +} // namespace + +auto git_metadata_available() -> bool { return git_metadata_available_value; } +auto git_dirty() -> bool { return git_dirty_value; } +auto git_diff() -> std::string_view { return git_diff_value; } +} // namespace version +} // namespace bout diff --git a/cmake_build_defines.hxx.in b/cmake_build_defines.hxx.in index 4d63a01b7d..7fd84c07d7 100644 --- a/cmake_build_defines.hxx.in +++ b/cmake_build_defines.hxx.in @@ -20,8 +20,8 @@ #cmakedefine01 BOUT_HAS_SCOREP #cmakedefine01 BOUT_HAS_SLEPC #cmakedefine01 BOUT_HAS_SUNDIALS +#cmakedefine01 BOUT_HAS_SUNDIALS_MANYVECTOR #cmakedefine01 BOUT_HAS_UUID_SYSTEM_GENERATOR -#cmakedefine01 BOUT_USE_BACKTRACE #cmakedefine01 BOUT_USE_COLOR #cmakedefine01 BOUT_USE_OPENMP #cmakedefine01 BOUT_USE_OUTPUT_DEBUG @@ -39,4 +39,7 @@ // CMake build does not support legacy interface #define BOUT_HAS_LEGACY_NETCDF 0 +// We now always turn this on +#define BOUT_USE_BACKTRACE 1 + #endif // BOUT_BUILD_CONFIG_HXX diff --git a/examples/6field-simple/CMakeLists.txt b/examples/6field-simple/CMakeLists.txt index 6a51327cda..b6584c49e4 100644 --- a/examples/6field-simple/CMakeLists.txt +++ b/examples/6field-simple/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(6field-simple LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(elm_6f +bout_add_example( + elm_6f SOURCES elm_6f.cxx - EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc) + EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc +) diff --git a/examples/6field-simple/data/BOUT.inp b/examples/6field-simple/data/BOUT.inp index 1e1bacfe6f..951182af06 100644 --- a/examples/6field-simple/data/BOUT.inp +++ b/examples/6field-simple/data/BOUT.inp @@ -61,7 +61,7 @@ fft_measurement_flag = measure # If using FFTW, perform tests to determine fast atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning mxstep = 10000 # Number of internal steps between outputs output_step = 1.0 # time between outputs diff --git a/examples/6field-simple/elm_6f.cxx b/examples/6field-simple/elm_6f.cxx index 40e4f7b3b3..1ffa925580 100644 --- a/examples/6field-simple/elm_6f.cxx +++ b/examples/6field-simple/elm_6f.cxx @@ -6,18 +6,32 @@ * T. Xia *******************************************************************************/ +#include "bout/assert.hxx" #include "bout/bout.hxx" +#include "bout/bout_types.hxx" +#include "bout/build_defines.hxx" #include "bout/constants.hxx" +#include "bout/coordinates.hxx" #include "bout/derivs.hxx" +#include "bout/difops.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" +#include "bout/fieldgroup.hxx" #include "bout/initialprofiles.hxx" #include "bout/interpolation_xz.hxx" #include "bout/invert_laplace.hxx" -#include "bout/invert_parderiv.hxx" #include "bout/msg_stack.hxx" +#include "bout/output.hxx" #include "bout/physicsmodel.hxx" +#include "bout/smoothing.hxx" #include "bout/sourcex.hxx" +#include "bout/tokamak_coordinates.hxx" +#include "bout/unused.hxx" +#include "bout/vecops.hxx" +#include "bout/where.hxx" #include +#include constexpr BoutReal eV_K = 11605.0; // 1eV = 11605K @@ -235,9 +249,7 @@ class Elm_6f : public PhysicsModel { int damp_width; // Width of inner damped region BoutReal damp_t_const; // Timescale of damping - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, B0, hthe; - Field2D I; // Shear factor + Field2D B0; // Magnetic field BoutReal LnLambda; // ln(Lambda) /// Ion mass @@ -273,8 +285,6 @@ class Elm_6f : public PhysicsModel { * This function implements d2/dy2 where y is the poloidal coordinate theta */ - TRACE("Grad2_par2new( Field3D )"); - Field3D result = D2DY2(f); #if BOUT_USE_TRACK @@ -342,8 +352,6 @@ class Elm_6f : public PhysicsModel { // Parallel gradient along perturbed field-line Field3D Grad_parP(const Field3D& f, CELL_LOC loc = CELL_DEFAULT) { - TRACE("Grad_parP"); - Field3D result; if (parallel_lagrange || parallel_project) { @@ -361,7 +369,7 @@ class Elm_6f : public PhysicsModel { result.allocate(); for (auto i : result) { result[i] = - (fp[i.yp()] - fm[i.ym()]) / (2. * coord->dy[i] * sqrt(coord->g_22[i])); + (fp[i.yp()] - fm[i.ym()]) / (2. * coord->dy()[i] * sqrt(coord->g_22()[i])); } } else { result = Grad_par(f, loc); @@ -378,38 +386,10 @@ class Elm_6f : public PhysicsModel { int init(bool restarting) override { bool noshear; - // Get the metric tensor - Coordinates* coord = mesh->getCoordinates(); - output.write("Solving high-beta flute reduced equations\n"); output.write("\tFile : {:s}\n", __FILE__); output.write("\tCompiled: {:s} at {:s}\n", __DATE__, __TIME__); - ////////////////////////////////////////////////////////////// - // Load data from the grid - - // Load 2D profiles - mesh->get(J0, "Jpar0"); // A / m^2 - mesh->get(P0, "pressure"); // Pascals - - // Load curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 - - // Load metrics - if (mesh->get(Rxy, "Rxy")) { // m - output_error.write("Error: Cannot read Rxy from grid\n"); - return 1; - } - if (mesh->get(Bpxy, "Bpxy")) { // T - output_error.write("Error: Cannot read Bpxy from grid\n"); - return 1; - } - mesh->get(Btxy, "Btxy"); // T - mesh->get(B0, "Bxy"); // T - mesh->get(hthe, "hthe"); // m - mesh->get(I, "sinty"); // m^-2 T^-1 - ////////////////////////////////////////////////////////////// // Read parameters from the options file // @@ -685,19 +665,43 @@ class Elm_6f : public PhysicsModel { phi_curv = options["phi_curv"].doc("Compressional ExB terms").withDefault(true); g = options["gamma"].doc("Ratio of specific heats").withDefault(5.0 / 3.0); - if (!include_curvature) { - b0xcv = 0.0; - } + ////////////////////////////////////////////////////////////// + // Load data from the grid - if (!include_jpar0) { - J0 = 0.0; - } + // Load 2D profiles + mesh->get(P0, "pressure"); // Pascals - if (noshear) { - if (include_curvature) { + // Typical magnetic field + mesh->get(Bbar, "bmag", 1.0); + // Typical length scale + mesh->get(Lbar, "rmag", 1.0); + + // Read, normalise, and set coordinates + const auto tokamak_coords = + bout::set_tokamak_coordinates(*mesh, Lbar, Bbar, noshear or mesh->IncIntShear); + const auto& Rxy = tokamak_coords.Rxy; + const auto& Bpxy = tokamak_coords.Bpxy; + const auto& Btxy = tokamak_coords.Btxy; + const auto& hthe = tokamak_coords.hthe; + const auto& I = tokamak_coords.I_unnormalised; + // Needed in rhs too + B0 = tokamak_coords.Bxy; + + if (include_curvature) { + // Load curvature term + b0xcv.covariant = false; // Read contravariant components + mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 + if (noshear) { b0xcv.z += I * b0xcv.x; } - I = 0.0; + } else { + b0xcv = 0.0; + } + + if (include_jpar0) { + mesh->get(J0, "Jpar0"); // A / m^2 + } else { + J0 = 0.0; } ////////////////////////////////////////////////////////////// @@ -705,26 +709,17 @@ class Elm_6f : public PhysicsModel { if (mesh->IncIntShear) { // BOUT-06 style, using d/dx = d/dpsi + I * d/dz - coord->IntShiftTorsion = I; - + mesh->getCoordinates()->setIntShiftTorsion(I); } else { // Dimits style, using local coordinate system if (include_curvature) { b0xcv.z += I * b0xcv.x; } - I = 0.0; // I disappears from metric } ////////////////////////////////////////////////////////////// // NORMALISE QUANTITIES - if (mesh->get(Bbar, "bmag")) { // Typical magnetic field - Bbar = 1.0; - } - if (mesh->get(Lbar, "rmag")) { // Typical length scale - Lbar = 1.0; - } - if (mesh->get(Tibar, "Ti_x")) { // Typical ion temperature scale Tibar = 1.0; } @@ -862,14 +857,6 @@ class Elm_6f : public PhysicsModel { b0xcv.y *= Lbar * Lbar; b0xcv.z *= Lbar * Lbar; - Rxy /= Lbar; - Bpxy /= Bbar; - Btxy /= Bbar; - B0 /= Bbar; - hthe /= Lbar; - coord->dx /= Lbar * Lbar * Bbar; - I *= Lbar * Lbar * Bbar; - if ((!T0_fake_prof) && n0_fake_prof) { N0 = N0tanh(n0_height * Nbar, n0_ave * Nbar, n0_width, n0_center, n0_bottom_x); @@ -955,7 +942,7 @@ class Elm_6f : public PhysicsModel { output.write("\tlog Lambda: {:e}\n", LnLambda); nu_e = 2.91e-6 * LnLambda * ((N0)*Nbar * density / 1.e6) - * pow(Te0 * Tebar, -1.5); // nu_e in 1/S. + * pow(Field2D{Te0 * Tebar}, -1.5); // nu_e in 1/S. output.write("\telectron collision rate: {:e} -> {:e} [1/s]\n", min(nu_e), max(nu_e)); // nu_e.applyBoundary(); // mesh->communicate(nu_e); @@ -967,7 +954,8 @@ class Elm_6f : public PhysicsModel { // xqx addition, begin // Use Spitzer thermal conductivities nu_i = 4.80e-8 * (Zi * Zi * Zi * Zi / sqrt(AA)) * LnLambda - * ((N0)*Nbar * density / 1.e6) * pow(Ti0 * Tibar, -1.5); // nu_i in 1/S. + * ((N0)*Nbar * density / 1.e6) + * pow(Field2D{Ti0 * Tibar}, -1.5); // nu_i in 1/S. // output.write("\tCoulomb Logarithm: {:e} \n", max(LnLambda)); output.write("\tion collision rate: {:e} -> {:e} [1/s]\n", min(nu_i), max(nu_i)); @@ -1032,8 +1020,9 @@ class Elm_6f : public PhysicsModel { // Use Spitzer resistivity output.write("\n\tSpizter parameters"); // output.write("\tTemperature: {:e} -> {:e} [eV]\n", min(Te), max(Te)); - eta_spitzer = 0.51 * 1.03e-4 * Zi * LnLambda - * pow(Te0 * Tebar, -1.5); // eta in Ohm-m. NOTE: ln(Lambda) = 20 + eta_spitzer = + 0.51 * 1.03e-4 * Zi * LnLambda + * pow(Field2D{Te0 * Tebar}, -1.5); // eta in Ohm-m. NOTE: ln(Lambda) = 20 output.write("\tSpitzer resistivity: {:e} -> {:e} [Ohm m]\n", min(eta_spitzer), max(eta_spitzer)); eta_spitzer /= SI::mu0 * Va * Lbar; @@ -1049,27 +1038,6 @@ class Elm_6f : public PhysicsModel { dump.add(eta, "eta", 0); } - /**************** CALCULATE METRICS ******************/ - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(B0) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - coord->Bxy = B0; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(B0 * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); // Calculate quantities from metric tensor - // Set B field vector B0vec.covariant = false; @@ -1161,7 +1129,7 @@ class Elm_6f : public PhysicsModel { // Only if not restarting: Check initial perturbation // Set U to zero where P0 < vacuum_pressure - U = where(P0 - vacuum_pressure, U, 0.0); + U = where(Field2D{P0 - vacuum_pressure}, U, 0.0); // Field2D lap_temp = 0.0; Field2D logn0 = laplace_alpha * N0; @@ -1288,24 +1256,25 @@ class Elm_6f : public PhysicsModel { // Update resistivity if (spitzer_resist) { // Use Spitzer formula - eta_spitzer = 0.51 * 1.03e-4 * Zi * LnLambda - * pow(Te_tmp * Tebar, -1.5); // eta in Ohm-m. ln(Lambda) = 20 + eta_spitzer = + 0.51 * 1.03e-4 * Zi * LnLambda + * pow(Field3D{Te_tmp * Tebar}, -1.5); // eta in Ohm-m. ln(Lambda) = 20 eta_spitzer /= SI::mu0 * Va * Lbar; } else { eta = core_resist + (vac_resist - core_resist) * vac_mask; } nu_e = 2.91e-6 * LnLambda * (N_tmp * Nbar * density / 1.e6) - * pow(Te_tmp * Tebar, -1.5); // nu_e in 1/S. + * pow(Field3D{Te_tmp * Tebar}, -1.5); // nu_e in 1/S. if (diffusion_par > 0.0) { // Use Spitzer thermal conductivities nu_i = 4.80e-8 * (Zi * Zi * Zi * Zi / sqrt(AA)) * LnLambda * (N_tmp * Nbar * density / 1.e6) - * pow(Ti_tmp * Tibar, -1.5); // nu_i in 1/S. - vth_i = 9.79e3 * sqrt(Ti_tmp * Tibar / AA); // vth_i in m/S. - vth_e = 4.19e5 * sqrt(Te_tmp * Tebar); // vth_e in m/S. + * pow(Field3D{Ti_tmp * Tibar}, -1.5); // nu_i in 1/S. + vth_i = 9.79e3 * sqrt(Ti_tmp * Tibar / AA); // vth_i in m/S. + vth_e = 4.19e5 * sqrt(Te_tmp * Tebar); // vth_e in m/S. } if (diffusion_par > 0.0) { @@ -1446,11 +1415,11 @@ class Elm_6f : public PhysicsModel { if (hyperviscos > 0.0) { // Calculate coefficient. - hyper_mu_x = hyperviscos * coord->g_11 * SQ(coord->dx) - * abs(coord->g11 * D2DX2(U)) / (abs(U) + 1e-3); + hyper_mu_x = hyperviscos * coord->g_11() * SQ(coord->dx()) + * abs(coord->g11() * D2DX2(U)) / (abs(U) + 1e-3); hyper_mu_x.applyBoundary("dirichlet"); // Set to zero on all boundaries - ddt(U) += hyper_mu_x * coord->g11 * D2DX2(U); + ddt(U) += hyper_mu_x * coord->g11() * D2DX2(U); if (first_run) { // Print out maximum values of viscosity used on this processor diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e8c09ca5bc..031380dbd5 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -30,7 +30,6 @@ add_subdirectory(invertable_operator) add_subdirectory(laplacexy/alfven-wave) add_subdirectory(laplacexy/laplace_perp) add_subdirectory(laplacexy/simple) -add_subdirectory(laplacexy/simple-hypre) add_subdirectory(monitor-newapi) add_subdirectory(orszag-tang) add_subdirectory(preconditioning/wave) diff --git a/examples/IMEX/advection-diffusion/CMakeLists.txt b/examples/IMEX/advection-diffusion/CMakeLists.txt index 334d48d767..f2008f3479 100644 --- a/examples/IMEX/advection-diffusion/CMakeLists.txt +++ b/examples/IMEX/advection-diffusion/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(advection-diffusion LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/IMEX/advection-reaction/CMakeLists.txt b/examples/IMEX/advection-reaction/CMakeLists.txt index 03e8686371..d89ff10a78 100644 --- a/examples/IMEX/advection-reaction/CMakeLists.txt +++ b/examples/IMEX/advection-reaction/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(advection-reaction LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(split_operator +bout_add_example( + split_operator SOURCES split_operator.cxx - EXTRA_FILES simple_xz.nc) + EXTRA_FILES simple_xz.nc +) diff --git a/examples/IMEX/diffusion-nl/CMakeLists.txt b/examples/IMEX/diffusion-nl/CMakeLists.txt index 664d16e042..73c7250bb5 100644 --- a/examples/IMEX/diffusion-nl/CMakeLists.txt +++ b/examples/IMEX/diffusion-nl/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(diffusion-nl LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/IMEX/diffusion-nl/README.md b/examples/IMEX/diffusion-nl/README.md index 3654d484ee..8356955b95 100644 --- a/examples/IMEX/diffusion-nl/README.md +++ b/examples/IMEX/diffusion-nl/README.md @@ -32,7 +32,7 @@ Preconditioning The preconditioner can be enabled by adding another flag (or setting in BOUT.inp) - $ ./diffusion-nl solver:use_precon=true + $ ./diffusion-nl solver:cvode_precon_method=user which then greatly reduces the number of iterations needed by CVODE: @@ -59,4 +59,3 @@ can be calculated using finite differences. This uses coloring to improve effici 1.000e+00 2 26 3.10e-03 31.9 0.0 5.9 7.8 54.4 2.000e+00 2 23 2.24e-03 35.7 0.0 7.0 7.9 49.4 3.000e+00 2 18 2.04e-03 35.0 0.0 6.2 8.5 50.4 - diff --git a/examples/IMEX/drift-wave-constraint/CMakeLists.txt b/examples/IMEX/drift-wave-constraint/CMakeLists.txt index 5680b5367e..b72396d2f0 100644 --- a/examples/IMEX/drift-wave-constraint/CMakeLists.txt +++ b/examples/IMEX/drift-wave-constraint/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(drift-wave-constraint LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/IMEX/drift-wave-constraint/test-drift.cxx b/examples/IMEX/drift-wave-constraint/test-drift.cxx index e3bf88acfc..ddeb5ef9d4 100644 --- a/examples/IMEX/drift-wave-constraint/test-drift.cxx +++ b/examples/IMEX/drift-wave-constraint/test-drift.cxx @@ -61,10 +61,10 @@ class DriftWave : public PhysicsModel { // This code results in ddt(Ne) depending on y+2, y-2 // which are not (currently) included in the coloring // The result is that IMEX-BDF2 with coloring doesn't converge - + Ve = ( Grad_par(phi) - Grad_par(Ne) ) / nu; mesh->communicate(Ve); - + ddt(Ne) = -Div_par(Ve); ddt(Vort) = -Div_par(Ve); */ @@ -82,7 +82,7 @@ class DriftWave : public PhysicsModel { // ddt(phi) = Delp2(phi) - Vort; // This version uses central differencing for Delp2 - ddt(phi) = (coord->g11 * D2DX2(phi) + coord->g33 * D2DZ2(phi)) - Vort; + ddt(phi) = (coord->g11() * D2DX2(phi) + coord->g33() * D2DZ2(phi)) - Vort; return 0; } diff --git a/examples/IMEX/drift-wave/CMakeLists.txt b/examples/IMEX/drift-wave/CMakeLists.txt index e3e2a1b8ee..44fbbd7b0f 100644 --- a/examples/IMEX/drift-wave/CMakeLists.txt +++ b/examples/IMEX/drift-wave/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(drift-wave LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/blob2d-laplacexz/CMakeLists.txt b/examples/blob2d-laplacexz/CMakeLists.txt index 17f9ebe97a..855d86af70 100644 --- a/examples/blob2d-laplacexz/CMakeLists.txt +++ b/examples/blob2d-laplacexz/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(blob2d-laplacexz LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/blob2d-outerloop/CMakeLists.txt b/examples/blob2d-outerloop/CMakeLists.txt index cd7187ee3f..e991b45d51 100644 --- a/examples/blob2d-outerloop/CMakeLists.txt +++ b/examples/blob2d-outerloop/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(blob2d-outerloop LANGUAGES CXX C) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/blob2d/CMakeLists.txt b/examples/blob2d/CMakeLists.txt index a4772874d9..f3f93f0246 100644 --- a/examples/blob2d/CMakeLists.txt +++ b/examples/blob2d/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(blob2d LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(blob2d +bout_add_example( + blob2d SOURCES blob2d.cxx DATA_DIRS delta_0.25 delta_1 delta_10 two_blobs data - EXTRA_FILES blob_velocity.py) + EXTRA_FILES blob_velocity.py +) diff --git a/examples/blob2d/blob_velocity.py b/examples/blob2d/blob_velocity.py index d044946320..6de0937d0f 100644 --- a/examples/blob2d/blob_velocity.py +++ b/examples/blob2d/blob_velocity.py @@ -3,96 +3,100 @@ import pickle try: - from past.utils import old_div + from past.utils import old_div except ImportError: - def old_div(a,b): - return a/b - -def blob_velocity(n,**kwargs): - - from boututils import calculus as Calc - # Calculate blob velocity in normalized time and normalized grid spacing - # - # Input: Blob density as a 3D vector in the form n[t,x,z] where t is time and x,z are the perpendicular spatial coordinates - # - # Keywords: - # - # type='peak' -> Calculate velocity of the peak density - # type='COM' -> Calculate centre of mass velocity - # Index=True -> return indices used to create velocity - # - # Default: Peak velocity with no index returning - - size = n.shape - - try: - v_type = kwargs['type'] - except: - v_type = 'peak' #Default to peak velocity calculation - try: - return_index = kwargs['Index'] - except: - return_index = False #Default to no index returning - - - if v_type == 'peak': - x = np.zeros(size[0]) - z = np.zeros(size[0]) - for i in np.arange(size[0]): - nmax,nmin = np.amax((n[i,:,:])),np.amin((n[i,:,:])) - xpos,zpos = np.where(n[i,:,:]==nmax) - x[i] = xpos[0] - z[i] = zpos[0] - - if v_type == 'COM': - x = np.zeros(size[0]) - z = np.zeros(size[0]) - for i in np.arange(size[0]): - data = n[i,:,:] - n[0,0,0] #use corner cell rather than nmin - ntot = np.sum(data[:,:]) - - z[i] = old_div(np.sum(np.sum(data[:,:],axis=0)*(np.arange(size[2]))),ntot) - x[i] = old_div(np.sum(np.sum(data[:,:],axis=1)*(np.arange(size[1]))),ntot) - - vx = Calc.deriv(x) - vz = Calc.deriv(z) - - if return_index: - return vx,vz,x,z - else: - return vx,vz - - - -data='data' + def old_div(a, b): + return a / b + + +def blob_velocity(n, **kwargs): + from boututils import calculus as Calc + # Calculate blob velocity in normalized time and normalized grid spacing + # + # Input: Blob density as a 3D vector in the form n[t,x,z] where t is time and x,z are the perpendicular spatial coordinates + # + # Keywords: + # + # type='peak' -> Calculate velocity of the peak density + # type='COM' -> Calculate centre of mass velocity + # Index=True -> return indices used to create velocity + # + # Default: Peak velocity with no index returning + + size = n.shape + + try: + v_type = kwargs["type"] + except: + v_type = "peak" # Default to peak velocity calculation + try: + return_index = kwargs["Index"] + except: + return_index = False # Default to no index returning + + if v_type == "peak": + x = np.zeros(size[0]) + z = np.zeros(size[0]) + for i in np.arange(size[0]): + nmax, nmin = np.amax((n[i, :, :])), np.amin((n[i, :, :])) + xpos, zpos = np.where(n[i, :, :] == nmax) + x[i] = xpos[0] + z[i] = zpos[0] + + if v_type == "COM": + x = np.zeros(size[0]) + z = np.zeros(size[0]) + for i in np.arange(size[0]): + data = n[i, :, :] - n[0, 0, 0] # use corner cell rather than nmin + ntot = np.sum(data[:, :]) + + z[i] = old_div( + np.sum(np.sum(data[:, :], axis=0) * (np.arange(size[2]))), ntot + ) + x[i] = old_div( + np.sum(np.sum(data[:, :], axis=1) * (np.arange(size[1]))), ntot + ) + + vx = Calc.deriv(x) + vz = Calc.deriv(z) + + if return_index: + return vx, vz, x, z + else: + return vx, vz + + +data = "data" if True: - import sys - if len(sys.argv) > 1: - data=sys.argv[1] + import sys + + if len(sys.argv) > 1: + data = sys.argv[1] -n = collect('n', path=data, info=False) +n = collect("n", path=data, info=False) -vx,vy,xx,yy = blob_velocity(n[:,:,0,:],type='COM',Index=True) +vx, vy, xx, yy = blob_velocity(n[:, :, 0, :], type="COM", Index=True) -f = open('Velocity.dat','wb') -pickle.dump(vx,f) +f = open("Velocity.dat", "wb") +pickle.dump(vx, f) f.close() -f = open('Position.dat','wb') -pickle.dump(xx,f) +f = open("Position.dat", "wb") +pickle.dump(xx, f) f.close() -f = open('Velocity.dat','rb') +f = open("Velocity.dat", "rb") vx = pickle.load(f) f.close() try: - import matplotlib.pyplot as plt - plt.plot(vx) - plt.show() + import matplotlib.pyplot as plt + + plt.plot(vx) + plt.show() except ImportError: - pass + pass diff --git a/examples/boundary-conditions/advection/CMakeLists.txt b/examples/boundary-conditions/advection/CMakeLists.txt index a4ab73a24d..edd55d183a 100644 --- a/examples/boundary-conditions/advection/CMakeLists.txt +++ b/examples/boundary-conditions/advection/CMakeLists.txt @@ -2,13 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(advection LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(advection +bout_add_example( + advection SOURCES advection.cxx - DATA_DIRS central-dirichlet - central-free - central-free-o3 - upwind) + DATA_DIRS central-dirichlet central-free central-free-o3 upwind +) diff --git a/examples/boutpp/CMakeLists.txt b/examples/boutpp/CMakeLists.txt index e46a7ae990..1cc5c9619b 100644 --- a/examples/boutpp/CMakeLists.txt +++ b/examples/boutpp/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.13) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/boutpp/simulation.py b/examples/boutpp/simulation.py index 1b57ff8b33..9948bd9b03 100755 --- a/examples/boutpp/simulation.py +++ b/examples/boutpp/simulation.py @@ -3,12 +3,13 @@ bc.init("mesh:n=48") + class Model(bc.PhysicsModel): - def init(self,restart): + def init(self, restart): self.dens = bc.create3D("sin(x)") self.solve_for(n=self.dens) - def rhs(self,time): + def rhs(self, time): self.dens.ddt(bc.DDX(self.dens)) diff --git a/examples/conducting-wall-mode/CMakeLists.txt b/examples/conducting-wall-mode/CMakeLists.txt index 857a22038e..0e000c1ba8 100644 --- a/examples/conducting-wall-mode/CMakeLists.txt +++ b/examples/conducting-wall-mode/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(conducting-wall-mode LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(conducting-wall-mode +bout_add_example( + conducting-wall-mode SOURCES cwm.cxx - EXTRA_FILES cwm_grid.nc) + EXTRA_FILES cwm_grid.nc +) diff --git a/examples/conducting-wall-mode/cwm.cxx b/examples/conducting-wall-mode/cwm.cxx index 6ad23033ee..c3cd40630c 100644 --- a/examples/conducting-wall-mode/cwm.cxx +++ b/examples/conducting-wall-mode/cwm.cxx @@ -4,12 +4,26 @@ * Mode discoverd by H.L. Berk et. al. 1993 * Model version in the code created by M. Umansky and J. Myra. *******************************************************************************/ -#include +#include +#include #include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include +#include +#include + +#include +#include class CWM : public PhysicsModel { private: @@ -28,9 +42,6 @@ class CWM : public PhysicsModel { // Phi boundary conditions Field3D dphi_bc_ydown, dphi_bc_yup; - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe, Zxy; - // parameters BoutReal Te_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; BoutReal lambda_ei; @@ -54,8 +65,6 @@ class CWM : public PhysicsModel { std::unique_ptr phiSolver{nullptr}; int init(bool UNUSED(restarting)) override { - Field2D I; // Shear factor - /************* LOAD DATA FROM GRID FILE ****************/ // Load 2D profiles (set to zero if not found) @@ -63,11 +72,6 @@ class CWM : public PhysicsModel { coord = mesh->getCoordinates(); - // Load metrics - GRID_LOAD(Rxy, Zxy, Bpxy, Btxy, hthe); - mesh->get(coord->dx, "dpsi"); - mesh->get(I, "sinty"); - // Load normalisation values GRID_LOAD(Te_x, Ni_x, bmag); @@ -93,13 +97,11 @@ class CWM : public PhysicsModel { /************* SHIFTED RADIAL COORDINATES ************/ // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault( - "identity"); + const auto ptstr = + Options::root()["mesh"]["paralleltransform"]["type"].withDefault("identity"); - if (lowercase(ptstr) == "shifted") { - ShearFactor = 0.0; // I disappears from metric - } + // I disappears from metric + const bool noshear = (lowercase(ptstr) == "shifted"); /************** CALCULATE PARAMETERS *****************/ @@ -132,39 +134,19 @@ class CWM : public PhysicsModel { Ni0 /= Ni_x / 1.0e14; Te0 /= Te_x; - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - I *= rho_s * rho_s * (bmag / 1e4) * ShearFactor; - coord->dx /= rho_s * rho_s * (bmag / 1e4); - - // Normalise magnetic field - Bpxy /= (bmag / 1.e4); - Btxy /= (bmag / 1.e4); - coord->Bxy /= (bmag / 1.e4); - // Set nu nu = nu_hat * Ni0 / pow(Te0, 1.5); /**************** CALCULATE METRICS ******************/ - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); + // Read, normalise, and set coordinates + const auto tokamak_coords = + bout::set_tokamak_coordinates(*mesh, rho_s, bmag / 1e4, noshear); + auto Rxy = tokamak_coords.Rxy; + auto Zxy = tokamak_coords.Zxy; + auto Bpxy = tokamak_coords.Bpxy; + auto Btxy = tokamak_coords.Btxy; + auto hthe = tokamak_coords.hthe; /**************** SET EVOLVING VARIABLES *************/ @@ -349,7 +331,7 @@ class CWM : public PhysicsModel { result = VDDX(DDZ(p), f); } else { // Use full expression with all terms - result = b0xGrad_dot_Grad(p, f) / coord->Bxy; + result = b0xGrad_dot_Grad(p, f) / coord->Bxy(); } return result; } @@ -358,10 +340,10 @@ class CWM : public PhysicsModel { Field3D result; if (bout_exb) { // Use a subset of terms for comparison to BOUT-06 - result = VDDZ(-DDX(p), f); + result = VDDZ(Field2D{-DDX(p)}, f); } else { // Use full expression with all terms - result = b0xGrad_dot_Grad(p, f) / coord->Bxy; + result = b0xGrad_dot_Grad(p, f) / coord->Bxy(); } return result; } @@ -373,7 +355,7 @@ class CWM : public PhysicsModel { result = VDDX(DDZ(p), f) + VDDZ(-DDX(p), f); } else { // Use full expression with all terms - result = b0xGrad_dot_Grad(p, f) / coord->Bxy; + result = b0xGrad_dot_Grad(p, f) / coord->Bxy(); } return result; } diff --git a/examples/conduction-snb/CMakeLists.txt b/examples/conduction-snb/CMakeLists.txt index 45072dbe59..3de25718d1 100644 --- a/examples/conduction-snb/CMakeLists.txt +++ b/examples/conduction-snb/CMakeLists.txt @@ -2,11 +2,20 @@ cmake_minimum_required(VERSION 3.13) project(conduction-snb LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(conduction-snb +bout_add_example( + conduction-snb SOURCES conduction-snb.cxx - EXTRA_FILES fit_temperature.py sinusoid.py snb.csv spitzer-harm.csv step.py temperature.csv vfp.csv - DATA_DIRS data step) + EXTRA_FILES + fit_temperature.py + sinusoid.py + snb.csv + spitzer-harm.csv + step.py + temperature.csv + vfp.csv + DATA_DIRS data step +) diff --git a/examples/conduction-snb/fit_temperature.py b/examples/conduction-snb/fit_temperature.py index 1e7f3ddf94..81faa9cf93 100644 --- a/examples/conduction-snb/fit_temperature.py +++ b/examples/conduction-snb/fit_temperature.py @@ -3,23 +3,31 @@ import matplotlib.pyplot as plt Te_ref = np.loadtxt("temperature.csv", delimiter=",") -Te_ref[:,0] *= 1e-4 # Convert X axis to m +Te_ref[:, 0] *= 1e-4 # Convert X axis to m + def te_function(ypos, mid, wwid, w0, w1, w2, Tmax, Tmin, clip=False): - width = w0 + ((ypos - mid)*w1 + (ypos - mid)**2 * w2) * np.exp(-((ypos - mid)/wwid)**2) + width = w0 + ((ypos - mid) * w1 + (ypos - mid) ** 2 * w2) * np.exp( + -(((ypos - mid) / wwid) ** 2) + ) if clip: width = np.clip(width, 1e-10, None) - return Tmax - 0.5 * (1 + np.tanh((ypos - mid)/width)) * (Tmax - Tmin) + return Tmax - 0.5 * (1 + np.tanh((ypos - mid) / width)) * (Tmax - Tmin) + -popt, pcov = optimize.curve_fit(te_function, Te_ref[:,0], Te_ref[:,1], - p0 = [2.2e-4, 1e-4, 1e-4, 0.0, 0.0, 0.960, 0.190]) +popt, pcov = optimize.curve_fit( + te_function, + Te_ref[:, 0], + Te_ref[:, 1], + p0=[2.2e-4, 1e-4, 1e-4, 0.0, 0.0, 0.960, 0.190], +) print(popt) -xfit = np.linspace(Te_ref[0,0], Te_ref[-1,0], 100) +xfit = np.linspace(Te_ref[0, 0], Te_ref[-1, 0], 100) -plt.plot(xfit, te_function(xfit, *popt, clip=True), '-k') -plt.plot(Te_ref[:,0], Te_ref[:,1], 'or') +plt.plot(xfit, te_function(xfit, *popt, clip=True), "-k") +plt.plot(Te_ref[:, 0], Te_ref[:, 1], "or") plt.show() diff --git a/examples/conduction-snb/sinusoid.py b/examples/conduction-snb/sinusoid.py index 10c81923a3..439530383e 100644 --- a/examples/conduction-snb/sinusoid.py +++ b/examples/conduction-snb/sinusoid.py @@ -11,7 +11,7 @@ build_and_log("Sinusoidal SNB") # Electron temperature in eV -Telist = 10 ** np.linspace(0,3,20) +Telist = 10 ** np.linspace(0, 3, 20) # Electron density in m^-3 Ne = 1e20 @@ -19,29 +19,30 @@ # Length of the domain in m length = 1.0 -c = 299792458 -mu0 = 4.e-7*np.pi -e0 = 1/(c*c*mu0) +c = 299792458 +mu0 = 4.0e-7 * np.pi +e0 = 1 / (c * c * mu0) qe = 1.602176634e-19 me = 9.10938356e-31 -thermal_speed = np.sqrt(2.*qe * Telist / me) -Y = (qe**2 / (e0 * me))**2 / (4 * np.pi) +thermal_speed = np.sqrt(2.0 * qe * Telist / me) +Y = (qe**2 / (e0 * me)) ** 2 / (4 * np.pi) coulomb_log = 6.6 - 0.5 * np.log(Ne * 1e-20) + 1.5 * np.log(Telist) -lambda_ee_T = thermal_speed**4 / (Y * Ne * coulomb_log) +lambda_ee_T = thermal_speed**4 / (Y * Ne * coulomb_log) beta_max_list = [5, 10, 20, 40] -colors = ['k','b','g','r'] +colors = ["k", "b", "g", "r"] ngroups_list = [20, 40, 80] -syms = ['x', 'o', 'D'] +syms = ["x", "o", "D"] for beta_max, color in zip(beta_max_list, colors): for ngroups, sym in zip(ngroups_list, syms): - flux_ratio = [] for Te in Telist: - cmd = "./conduction-snb \"Te={0}+0.01*sin(y)\" Ne={1} mesh:length={2} snb:beta_max={3} snb:ngroups={4}".format(Te, Ne, length, beta_max, ngroups) + cmd = './conduction-snb "Te={0}+0.01*sin(y)" Ne={1} mesh:length={2} snb:beta_max={3} snb:ngroups={4}'.format( + Te, Ne, length, beta_max, ngroups + ) # Run the case s, out = launch_safe(cmd, nproc=1, mthread=1, pipe=True) @@ -54,7 +55,12 @@ flux_ratio.append(div_q[ind] / div_q_SH[ind]) - plt.plot(lambda_ee_T / length, flux_ratio, '-'+sym+color, label=r"$\beta_{{max}}={0}, N_g={1}$".format(beta_max,ngroups)) + plt.plot( + lambda_ee_T / length, + flux_ratio, + "-" + sym + color, + label=r"$\beta_{{max}}={0}, N_g={1}$".format(beta_max, ngroups), + ) plt.legend() plt.xlabel(r"$\lambda_{ee,T} / L$") diff --git a/examples/conduction-snb/step.py b/examples/conduction-snb/step.py index 1f8933e66b..63a13149f4 100644 --- a/examples/conduction-snb/step.py +++ b/examples/conduction-snb/step.py @@ -3,7 +3,7 @@ # # Uses a step in the temperature, intended for comparison to VFP results -length = 6e-4 # Domain length in m +length = 6e-4 # Domain length in m qe = 1.602176634e-19 @@ -40,37 +40,37 @@ # Read reference values Te_ref = np.loadtxt("temperature.csv", delimiter=",") -Te_ref[:,0] *= 1e-4 # Convert X axis to m +Te_ref[:, 0] *= 1e-4 # Convert X axis to m SH_ref = np.loadtxt("spitzer-harm.csv", delimiter=",") -SH_ref[:,0] *= 1e-4 +SH_ref[:, 0] *= 1e-4 SNB_ref = np.loadtxt("snb.csv", delimiter=",") -SNB_ref[:,0] *= 1e-4 +SNB_ref[:, 0] *= 1e-4 VFP_ref = np.loadtxt("vfp.csv", delimiter=",") -VFP_ref[:,0] *= 1e-4 +VFP_ref[:, 0] *= 1e-4 ######################################### fig, ax1 = plt.subplots() -color='tab:red' +color = "tab:red" ax1.plot(position, Te * 1e-3, color=color, label="Te") -ax1.plot(Te_ref[:,0], Te_ref[:,1], color=color, marker="o", label="Reference Te") +ax1.plot(Te_ref[:, 0], Te_ref[:, 1], color=color, marker="o", label="Reference Te") ax1.set_xlabel("position [m]") ax1.set_ylabel("Electron temperature [keV]", color=color) -ax1.set_ylim(0,1) -ax1.tick_params(axis='y', colors=color) +ax1.set_ylim(0, 1) +ax1.tick_params(axis="y", colors=color) ax2 = ax1.twinx() -ax2.plot(position, q_SH * 1e-4, '-k', label="Spitzer-Harm") -ax2.plot(SH_ref[:,0], SH_ref[:,1], '--k', label="Reference SH") +ax2.plot(position, q_SH * 1e-4, "-k", label="Spitzer-Harm") +ax2.plot(SH_ref[:, 0], SH_ref[:, 1], "--k", label="Reference SH") -ax2.plot(position, q * 1e-4, '-b', label="SNB") -ax2.plot(SNB_ref[:,0], SNB_ref[:,1], '--b', label="Reference SNB") +ax2.plot(position, q * 1e-4, "-b", label="SNB") +ax2.plot(SNB_ref[:, 0], SNB_ref[:, 1], "--b", label="Reference SNB") -ax2.plot(VFP_ref[:,0], VFP_ref[:,1], '--g', label="Reference VFP") +ax2.plot(VFP_ref[:, 0], VFP_ref[:, 1], "--g", label="Reference VFP") ax2.set_ylabel("Heat flux W/cm^2") ax2.set_ylim(bottom=0.0) @@ -78,8 +78,7 @@ plt.legend() fig.tight_layout() -plt.xlim(0,3.5e-4) +plt.xlim(0, 3.5e-4) plt.savefig("snb-step.png") plt.show() - diff --git a/examples/conduction/CMakeLists.txt b/examples/conduction/CMakeLists.txt index f26b838621..b81164f614 100644 --- a/examples/conduction/CMakeLists.txt +++ b/examples/conduction/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(conduction LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(conduction +bout_add_example( + conduction SOURCES conduction.cxx DATA_DIRS data fromfile - EXTRA_FILES generate.py) + EXTRA_FILES generate.py +) diff --git a/examples/conduction/generate.py b/examples/conduction/generate.py index 7138026898..4a2a2acfc0 100755 --- a/examples/conduction/generate.py +++ b/examples/conduction/generate.py @@ -4,9 +4,9 @@ # Generate an input mesh # -from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries +from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries -nx = 5 # Minimum is 5: 2 boundary, one evolved +nx = 5 # Minimum is 5: 2 boundary, one evolved ny = 64 # Minimum 5. Should be divisible by number of processors (so powers of 2 nice) f = DataFile() diff --git a/examples/constraints/alfven-wave/CMakeLists.txt b/examples/constraints/alfven-wave/CMakeLists.txt index a95ace4086..375415ab3c 100644 --- a/examples/constraints/alfven-wave/CMakeLists.txt +++ b/examples/constraints/alfven-wave/CMakeLists.txt @@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(constraints-alfven-wave LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(constraints-alfven-wave +bout_add_example( + constraints-alfven-wave SOURCES alfven.cxx DATA_DIRS cbm18 data - EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc d3d_119919.nc) - + EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc d3d_119919.nc +) diff --git a/examples/constraints/alfven-wave/alfven.cxx b/examples/constraints/alfven-wave/alfven.cxx index 3e643331a1..85428fdc85 100644 --- a/examples/constraints/alfven-wave/alfven.cxx +++ b/examples/constraints/alfven-wave/alfven.cxx @@ -1,8 +1,9 @@ - #include #include #include #include +#include +#include /// Fundamental constants const BoutReal PI = 3.14159265; @@ -129,12 +130,12 @@ class Alfven : public PhysicsModel { } /*! - * Preconditioner. This inverts the operator (1 - gamma*J) + * Preconditioner. This inverts the operator (1 - gamma*J) * where J is the Jacobian of the system * * The system state at time t is stored as usual * whilst the vector to be inverted is in ddt(f) - * + * * Inputs * ------ * @@ -146,7 +147,7 @@ class Alfven : public PhysicsModel { * * Output * ------ - * + * * ddt(f) = Result of the inversion */ int precon(BoutReal, BoutReal, BoutReal) { @@ -159,65 +160,14 @@ class Alfven : public PhysicsModel { } void LoadMetric(BoutReal Lnorm, BoutReal Bnorm) { - // Load metric coefficients from the mesh - Field2D Rxy, Bpxy, Btxy, hthe, sinty; - GRID_LOAD5(Rxy, Bpxy, Btxy, hthe, sinty); // Load metrics - - // Get the coordinates object - Coordinates* coord = mesh->getCoordinates(); - - // Checking for dpsi and qinty used in BOUT grids - Field2D dx; - if (!mesh->get(dx, "dpsi")) { - output << "\tUsing dpsi as the x grid spacing\n"; - coord->dx = dx; // Only use dpsi if found - } else { - // dx will have been read already from the grid - output << "\tUsing dx as the x grid spacing\n"; - } - - Rxy /= Lnorm; - hthe /= Lnorm; - sinty *= SQ(Lnorm) * Bnorm; - coord->dx /= SQ(Lnorm) * Bnorm; - - Bpxy /= Bnorm; - Btxy /= Bnorm; - coord->Bxy /= Bnorm; - // Check type of parallel transform - std::string ptstr = + const auto ptstr = Options::root()["mesh"]["paralleltransform"]["type"].withDefault("identity"); - if (lowercase(ptstr) == "shifted") { - // Using shifted metric method - sinty = 0.0; // I disappears from metric - } - - BoutReal sbp = 1.0; // Sign of Bp - if (min(Bpxy, true) < 0.0) { - sbp = -1.0; - } - - // Calculate metric components - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(sinty) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -sinty * coord->g11; - coord->g23 = -sbp * Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(sinty * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = sbp * Btxy * hthe * sinty * Rxy / Bpxy; - coord->g_13 = sinty * Rxy * Rxy; - coord->g_23 = sbp * Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); + // I disappears from metric + const bool noshear = (lowercase(ptstr) == "shifted"); + // Read, normalise, and set coordinates + bout::set_tokamak_coordinates(*mesh, Lnorm, Bnorm, noshear); } }; diff --git a/examples/constraints/laplace-dae/CMakeLists.txt b/examples/constraints/laplace-dae/CMakeLists.txt index e487bd6a0a..d515fc3515 100644 --- a/examples/constraints/laplace-dae/CMakeLists.txt +++ b/examples/constraints/laplace-dae/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(constraints-laplace-dae LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(constraints-laplace-dae +bout_add_example( + constraints-laplace-dae SOURCES laplace_dae.cxx - EXTRA_FILES simple_xz.nc) + EXTRA_FILES simple_xz.nc +) diff --git a/examples/constraints/laplace-dae/data/BOUT.inp b/examples/constraints/laplace-dae/data/BOUT.inp index ea7c8d1765..ccc9a647ee 100644 --- a/examples/constraints/laplace-dae/data/BOUT.inp +++ b/examples/constraints/laplace-dae/data/BOUT.inp @@ -54,7 +54,7 @@ mxstep = 50000 #type=splitrk #timestep=1e-4 -use_precon = true +cvode_precon_method = user output_step = 0.01 # time between outputs # Settings for split operator test case diff --git a/examples/dalf3/CMakeLists.txt b/examples/dalf3/CMakeLists.txt index 5f5b3d701d..0b6f8461f5 100644 --- a/examples/dalf3/CMakeLists.txt +++ b/examples/dalf3/CMakeLists.txt @@ -2,11 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(dalf3 LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() - -bout_add_example(dalf3 +bout_add_example( + dalf3 SOURCES dalf3.cxx - EXTRA_FILES cbm18_8_y064_x516_090309.nc) + EXTRA_FILES cbm18_8_y064_x516_090309.nc +) diff --git a/examples/dalf3/dalf3.cxx b/examples/dalf3/dalf3.cxx index 493e8f5e45..4cf0e811bf 100644 --- a/examples/dalf3/dalf3.cxx +++ b/examples/dalf3/dalf3.cxx @@ -1,6 +1,6 @@ /**************************************************************** * DALF3 model - * + * * Four-field model for electron pressure, vorticity, A|| and * parallel velocity * @@ -18,17 +18,18 @@ * ****************************************************************/ -#include - +#include #include #include #include +#include +#include #include + +#include #include #include -#include - // Constants const BoutReal MU0 = 4.0e-7 * PI; const BoutReal Charge = SI::qe; // electron charge e (C) @@ -71,8 +72,6 @@ class DALF3 : public PhysicsModel { BoutReal viscosity, hyper_viscosity; - bool smooth_separatrix; - FieldGroup comms; std::unique_ptr phiSolver{nullptr}; // Laplacian solver in X-Z @@ -99,22 +98,9 @@ class DALF3 : public PhysicsModel { b0xcv.covariant = false; // Read contravariant components mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - Field2D I; // Shear factor - - if (mesh->get(Rxy, "Rxy")) { // m - output_error.write("Error: Cannot read Rxy from grid\n"); - return 1; - } - if (mesh->get(Bpxy, "Bpxy")) { // T - output_error.write("Error: Cannot read Bpxy from grid\n"); - return 1; - } - mesh->get(Btxy, "Btxy"); // T - mesh->get(B0, "Bxy"); // T - mesh->get(hthe, "hthe"); // m - mesh->get(I, "sinty"); // m^-2 T^-1 + // We need to load this in, despite using `set_tokamak_coordinates`, because + // the both length and B normalisation depend on it + mesh->get(B0, "Bxy"); // T ////////////////////////////////////////////////////////////// // Options @@ -132,7 +118,6 @@ class DALF3 : public PhysicsModel { viscosity = options["viscosity"].withDefault(-1.0); hyper_viscosity = options["hyper_viscosity"].withDefault(-1.0); viscosity_par = options["viscosity_par"].withDefault(-1.0); - smooth_separatrix = options["smooth_separatrix"].withDefault(false); filter_z = options["filter_z"].withDefault(false); @@ -166,20 +151,6 @@ class DALF3 : public PhysicsModel { return 1; } - Coordinates* coord = mesh->getCoordinates(); - - // SHIFTED RADIAL COORDINATES - - // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault("identity"); - - if (lowercase(ptstr) == "shifted") { - // Dimits style, using local coordinate system - b0xcv.z += I * b0xcv.x; - I = 0.0; // I disappears from metric - } - /////////////////////////////////////////////////// // Normalisation @@ -215,9 +186,7 @@ class DALF3 : public PhysicsModel { } else { eta = 0.51 * 1.03e-4 * 20. * pow(Te0, -1.5); } - if (mul_resist < 0.0) { - mul_resist = 0.0; - } + mul_resist = std::max(mul_resist, 0.0); eta *= mul_resist; // Plasma quantities @@ -231,41 +200,31 @@ class DALF3 : public PhysicsModel { hyper_viscosity /= wci * SQ(SQ(rho_s)); viscosity_par /= wci * SQ(rho_s); - b0xcv.x /= Bnorm; - b0xcv.y *= rho_s * rho_s; - b0xcv.z *= rho_s * rho_s; - - // Metrics - Rxy /= rho_s; - hthe /= rho_s; - I *= rho_s * rho_s * Bnorm; - Bpxy /= Bnorm; - Btxy /= Bnorm; - B0 /= Bnorm; - - coord->dx /= rho_s * rho_s * Bnorm; - /////////////////////////////////////////////////// // CALCULATE METRICS - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(B0) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); + // Check type of parallel transform + const auto ptstr = + Options::root()["mesh"]["paralleltransform"]["type"].withDefault("identity"); + + // I disappears from metric + const bool noshear = (lowercase(ptstr) == "shifted"); - coord->J = hthe / Bpxy; - coord->Bxy = B0; + // Read, normalise, and set coordinates + const auto tokamak_coords = + bout::set_tokamak_coordinates(*mesh, rho_s, Bnorm, noshear); + // Use normalised B0 + B0 = tokamak_coords.Bxy; - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(B0 * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; + // SHIFTED RADIAL COORDINATES + if (noshear) { + // Dimits style, using local coordinate system + b0xcv.z += tokamak_coords.I_unnormalised * b0xcv.x; + } - coord->geometry(); // Calculate quantities from metric tensor + b0xcv.x /= Bnorm; + b0xcv.y *= rho_s * rho_s; + b0xcv.z *= rho_s * rho_s; SOLVE_FOR3(Vort, Pe, Vpar); comms.add(Vort, Pe, Vpar); @@ -300,7 +259,7 @@ class DALF3 : public PhysicsModel { // LaplaceXY for n=0 solve if (split_n0) { // Create an XY solver for n=0 component - laplacexy = std::make_unique(mesh); + laplacexy = LaplaceXY::create(mesh); phi2D = 0.0; // Starting guess } @@ -466,11 +425,6 @@ class DALF3 : public PhysicsModel { ddt(Pe) = -bracket(phi, Pet, bm) + Pet * (Kappa(phi - Pe) + B0 * Grad_parP(jpar - Vpar) / B0); - if (smooth_separatrix) { - // Experimental smoothing across separatrix - ddt(Vort) += mesh->smoothSeparatrix(Vort); - } - if (filter_z) { ddt(Pe) = filter(ddt(Pe), 1); } diff --git a/examples/dalf3/data/BOUT.inp b/examples/dalf3/data/BOUT.inp index cd6070a1dd..53fa675f83 100644 --- a/examples/dalf3/data/BOUT.inp +++ b/examples/dalf3/data/BOUT.inp @@ -58,7 +58,7 @@ group_nonblock = false # Use non-blocking group operations? atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning use_jacobian = false # Use user-supplied Jacobian mxstep = 5000 # Number of internal steps between outputs diff --git a/examples/eigen-box/CMakeLists.txt b/examples/eigen-box/CMakeLists.txt index 76af4fbaa6..305e330652 100644 --- a/examples/eigen-box/CMakeLists.txt +++ b/examples/eigen-box/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(eigen-box LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(eigen-box +bout_add_example( + eigen-box SOURCES eigen-box.cxx - EXTRA_FILES eigenvals.py) + EXTRA_FILES eigenvals.py +) diff --git a/examples/eigen-box/eigenvals.py b/examples/eigen-box/eigenvals.py index 7b52fc60f2..5a71aabfc6 100755 --- a/examples/eigen-box/eigenvals.py +++ b/examples/eigen-box/eigenvals.py @@ -27,7 +27,8 @@ def plot_eigenvals(eigenvalues, eigenvectors=None): raise ValueError("Expecting eigenvectors to be 2D") if eigenvectors.shape[0] != len(eigenvalues): raise ValueError( - "First dimension of eigenvectors must match length of eigenvalues") + "First dimension of eigenvectors must match length of eigenvalues" + ) # If no eigenvectors supplied, only plot eigenvalues, otherwise # eigenvalues and eigenvectors @@ -44,18 +45,18 @@ def plot_eigenvals(eigenvalues, eigenvectors=None): range_r = amax(eigs_r) - amin(eigs_r) range_i = amax(eigs_i) - amin(eigs_i) - ax[0].plot(eigs_r, eigs_i, 'x') + ax[0].plot(eigs_r, eigs_i, "x") ax[0].set_xlabel("Real component") ax[0].set_ylabel("Imaginary component") ax[0].set_title("Eigenvalue") - overplot, = ax[0].plot([], [], 'ok') + (overplot,) = ax[0].plot([], [], "ok") if eigenvectors is not None: # Add a eigenvectors plot - vector_r, = ax[1].plot([], [], '-k', label="Real") - vector_i, = ax[1].plot([], [], '-r', label="Imag") - ax[1].legend(loc='upper right') + (vector_r,) = ax[1].plot([], [], "-k", label="Real") + (vector_i,) = ax[1].plot([], [], "-r", label="Imag") + ax[1].legend(loc="upper right") ax[1].set_xlabel("X") ax[1].set_ylabel("Amplitude") ax[1].set_title("Eigenvector") @@ -68,33 +69,33 @@ def onclick(event): # Find closest eigenvectors point, but stretch axes so # real and imaginary components are weighted equally - if(range_r == 0): - dist = ((eigs_i - event.ydata)/range_i)**2 - elif(range_i == 0): - dist = ((eigs_r - event.xdata)/range_r)**2 + if range_r == 0: + dist = ((eigs_i - event.ydata) / range_i) ** 2 + elif range_i == 0: + dist = ((eigs_r - event.xdata) / range_r) ** 2 else: - dist = ((eigs_r - event.xdata)/range_r)**2 + \ - ((eigs_i - event.ydata)/range_i)**2 + dist = ((eigs_r - event.xdata) / range_r) ** 2 + ( + (eigs_i - event.ydata) / range_i + ) ** 2 ind = argmin(dist) # Update the highlight plot overplot.set_data([eigs_r[ind]], [eigs_i[ind]]) - print("Eigenvalue number: %d (%e,%e)" % - (ind, eigs_r[ind], eigs_i[ind])) + print("Eigenvalue number: %d (%e,%e)" % (ind, eigs_r[ind], eigs_i[ind])) if eigenvectors is not None: # Update plots nx = eigenvectors.shape[1] - vector_r.set_data(arange(nx), eigenvectors[2*ind, :]) - vector_i.set_data(arange(nx), eigenvectors[2*ind+1, :]) + vector_r.set_data(arange(nx), eigenvectors[2 * ind, :]) + vector_i.set_data(arange(nx), eigenvectors[2 * ind + 1, :]) ax[1].relim() ax[1].autoscale_view() fig.canvas.draw() - fig.canvas.mpl_connect('button_press_event', onclick) + fig.canvas.mpl_connect("button_press_event", onclick) plt.show() diff --git a/examples/elm-pb-outerloop/CMakeLists.txt b/examples/elm-pb-outerloop/CMakeLists.txt index 008918a87f..12dc2f7696 100644 --- a/examples/elm-pb-outerloop/CMakeLists.txt +++ b/examples/elm-pb-outerloop/CMakeLists.txt @@ -2,16 +2,16 @@ cmake_minimum_required(VERSION 3.13) project(elm_pb LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(elm_pb_outerloop +bout_add_example( + elm_pb_outerloop SOURCES elm_pb_outerloop.cxx EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc ) if(BOUT_HAS_CUDA) - set_source_files_properties(elm_pb_outerloop.cxx PROPERTIES LANGUAGE CUDA ) + set_source_files_properties(elm_pb_outerloop.cxx PROPERTIES LANGUAGE CUDA) endif() - diff --git a/examples/elm-pb-outerloop/data/BOUT.inp b/examples/elm-pb-outerloop/data/BOUT.inp index 797ad91125..560da2999f 100644 --- a/examples/elm-pb-outerloop/data/BOUT.inp +++ b/examples/elm-pb-outerloop/data/BOUT.inp @@ -49,7 +49,7 @@ fft_measurement_flag = measure # If using FFTW, perform tests to determine fast atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning mxstep = 5000 # Number of internal steps between outputs output_step = 1 # time between outputs diff --git a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx index 8e84901806..54c3faf3e0 100644 --- a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx +++ b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx @@ -28,33 +28,26 @@ /*******************************************************************************/ +#include "bout/build_defines.hxx" +#include "bout/options.hxx" #include #include #include +#include #include #include #include #include #include -#include -#include -#include - -#include - -#include -#include #include +#include // Defines BOUT_FOR_RAJA #include #include +#include +#include +#include -#include // Defines BOUT_FOR_RAJA - -#if BOUT_HAS_HYPRE -#include -#endif - -#include +#include CELL_LOC loc = CELL_CENTRE; @@ -91,6 +84,10 @@ BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_target", "neumann"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xin", "none"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xout", "none"); +#if BOUT_HAS_HYPRE +BOUT_OVERRIDE_DEFAULT_OPTION("laplacexy:type", "hypre"); +#endif + /// 3-field ELM simulation class ELMpb : public PhysicsModel { private: @@ -242,11 +239,7 @@ class ELMpb : public PhysicsModel { bool split_n0; // Solve the n=0 component of potential -#if BOUT_HAS_HYPRE - std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#else std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#endif Field2D phi2D; // Axisymmetric phi @@ -289,8 +282,7 @@ class ELMpb : public PhysicsModel { BoutReal damp_t_const; // Timescale of damping // Metric coefficients - Field2D Rxy, Bpxy, Btxy, B0, hthe; - Field2D I; // Shear factor + Field2D B0; const BoutReal MU0 = 4.0e-7 * PI; const BoutReal Mi = 2.0 * 1.6726e-27; // Ion mass @@ -369,24 +361,7 @@ class ELMpb : public PhysicsModel { // Load data from the grid // Load 2D profiles - mesh->get(J0, "Jpar0"); // A / m^2 - mesh->get(P0, "pressure"); // Pascals - - // Load curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 - - // Load metrics - if (mesh->get(Rxy, "Rxy") != 0) { // m - throw BoutException("Error: Cannot read Rxy from grid\n"); - } - if (mesh->get(Bpxy, "Bpxy") != 0) { // T - throw BoutException("Error: Cannot read Bpxy from grid\n"); - } - mesh->get(Btxy, "Btxy"); // T - mesh->get(B0, "Bxy"); // T - mesh->get(hthe, "hthe"); // m - mesh->get(I, "sinty"); // m^-2 T^-1 + mesh->get(P0, "pressure"); // Pascals mesh->get(Psixy, "psixy"); // get Psi mesh->get(Psiaxis, "psi_axis"); // axis flux mesh->get(Psibndry, "psi_bndry"); // edge flux @@ -567,13 +542,11 @@ class ELMpb : public PhysicsModel { split_n0 = options["split_n0"] .doc("Solve zonal (n=0) component of potential using LaplaceXY?") .withDefault(false); + if (split_n0) { // Create an XY solver for n=0 component -#if BOUT_HAS_HYPRE - laplacexy = bout::utils::make_unique(mesh); -#else - laplacexy = bout::utils::make_unique(mesh); -#endif + laplacexy = LaplaceXY::create(mesh); + // Set coefficients for Boussinesq solve laplacexy->setCoefs(1.0, 0.0); phi2D = 0.0; // Starting guess @@ -720,8 +693,6 @@ class ELMpb : public PhysicsModel { Dphi0 *= -1; } - V0 = -Rxy * Bpxy * Dphi0 / B0; - if (simple_rmp) { include_rmp = true; } @@ -805,46 +776,60 @@ class ELMpb : public PhysicsModel { } } - if (!include_curvature) { + ////////////////////////////////////////////////////////////// + // Read, normalise, and set coordinates + + // Typical magnetic field + mesh->get(Bbar, "bmag", 1.0); + // Typical length scale + mesh->get(Lbar, "rmag", 1.0); + + const auto tokamak_coords = + bout::set_tokamak_coordinates(*mesh, Lbar, Bbar, noshear or mesh->IncIntShear); + const auto& Rxy = tokamak_coords.Rxy; + const auto& Bpxy = tokamak_coords.Bpxy; + const auto& Btxy = tokamak_coords.Btxy; + const auto& hthe = tokamak_coords.hthe; + const auto& I = tokamak_coords.I_unnormalised; + + B0 = tokamak_coords.Bxy; + + // Need to unnormalise Rxy, as we normalise velocity separately + V0 = -(Rxy * Lbar) * Bpxy * Dphi0 / B0; + + if (include_curvature) { + // Load curvature term + b0xcv.covariant = false; // Read contravariant components + mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 + if (noshear) { + b0xcv.z += I * b0xcv.x; + } + } else { b0xcv = 0.0; } - if (!include_jpar0) { + if (include_jpar0) { + mesh->get(J0, "Jpar0"); // A / m^2 + } else { J0 = 0.0; } - if (noshear) { - if (include_curvature) { - b0xcv.z += I * b0xcv.x; - } - I = 0.0; - } - ////////////////////////////////////////////////////////////// // SHIFTED RADIAL COORDINATES if (mesh->IncIntShear) { // BOUT-06 style, using d/dx = d/dpsi + I * d/dz - metric->IntShiftTorsion = I; - + mesh->getCoordinates()->setIntShiftTorsion(I); } else { // Dimits style, using local coordinate system if (include_curvature) { b0xcv.z += I * b0xcv.x; } - I = 0.0; // I disappears from metric } ////////////////////////////////////////////////////////////// // NORMALISE QUANTITIES - if (mesh->get(Bbar, "bmag") != 0) { // Typical magnetic field - Bbar = 1.0; - } - if (mesh->get(Lbar, "rmag") != 0) { // Typical length scale - Lbar = 1.0; - } - Va = sqrt(Bbar * Bbar / (MU0 * density * Mi)); Tbar = Lbar / Va; @@ -945,8 +930,8 @@ class ELMpb : public PhysicsModel { output.write(" drop K-H term\n"); } - Field2D Te; - Te = P0 / (2.0 * density * 1.602e-19); // Temperature in eV + // Temperature in eV + const Field2D Te = P0 / (2.0 * density * 1.602e-19); J0 = -MU0 * Lbar * J0 / B0; P0 = 2.0 * MU0 * P0 / (Bbar * Bbar); @@ -957,14 +942,6 @@ class ELMpb : public PhysicsModel { b0xcv.y *= Lbar * Lbar; b0xcv.z *= Lbar * Lbar; - Rxy /= Lbar; - Bpxy /= Bbar; - Btxy /= Bbar; - B0 /= Bbar; - hthe /= Lbar; - metric->dx /= Lbar * Lbar * Bbar; - I *= Lbar * Lbar * Bbar; - if (constn0) { T0_fake_prof = false; n0_fake_prof = false; @@ -1031,7 +1008,8 @@ class ELMpb : public PhysicsModel { vacuum_trans *= pnorm; // Transitions from 0 in core to 1 in vacuum - vac_mask = (1.0 - tanh((P0 - vacuum_pressure) / vacuum_trans)) / 2.0; + Field2D tanh_res = tanh((P0 - vacuum_pressure) / vacuum_trans); + vac_mask = (1.0 - tanh_res) / 2.0; if (spitzer_resist) { // Use Spitzer resistivity @@ -1090,27 +1068,6 @@ class ELMpb : public PhysicsModel { rmp_Psi = 0.0; } - /**************** CALCULATE METRICS ******************/ - - metric->g11 = SQ(Rxy * Bpxy); - metric->g22 = 1.0 / SQ(hthe); - metric->g33 = SQ(I) * metric->g11 + SQ(B0) / metric->g11; - metric->g12 = 0.0; - metric->g13 = -I * metric->g11; - metric->g23 = -Btxy / (hthe * Bpxy * Rxy); - - metric->J = hthe / Bpxy; - metric->Bxy = B0; - - metric->g_11 = 1.0 / metric->g11 + SQ(I * Rxy); - metric->g_22 = SQ(B0 * hthe / Bpxy); - metric->g_33 = Rxy * Rxy; - metric->g_12 = Btxy * hthe * I * Rxy / Bpxy; - metric->g_13 = I * Rxy * Rxy; - metric->g_23 = Btxy * hthe * Rxy / Bpxy; - - metric->geometry(); // Calculate quantities from metric tensor - // Set B field vector B0vec.covariant = false; @@ -1213,7 +1170,7 @@ class ELMpb : public PhysicsModel { // Only if not restarting: Check initial perturbation // Set U to zero where P0 < vacuum_pressure - U = where(P0 - vacuum_pressure, U, 0.0); + U = where(Field2D{P0 - vacuum_pressure}, U, 0.0); if (constn0) { ubyn = U; @@ -1680,12 +1637,12 @@ class ELMpb : public PhysicsModel { #endif }; - // Terms which are not yet single index operators - // Note: Terms which are included in the single index loop - // may be commented out here, to allow comparison/testing + // Terms which are not yet single index operators + // Note: Terms which are included in the single index loop + // may be commented out here, to allow comparison/testing - //////////////////////////////////////////////////// - // Parallel electric field + //////////////////////////////////////////////////// + // Parallel electric field #if not EVOLVE_JPAR // Vector potential @@ -1792,11 +1749,11 @@ class ELMpb : public PhysicsModel { if (hyperviscos > 0.0) { // Calculate coefficient. - hyper_mu_x = hyperviscos * metric->g_11 * SQ(metric->dx) - * abs(metric->g11 * D2DX2(U)) / (abs(U) + 1e-3); + hyper_mu_x = hyperviscos * metric->g_11() * SQ(metric->dx()) + * abs(metric->g11() * D2DX2(U)) / (abs(U) + 1e-3); hyper_mu_x.applyBoundary("dirichlet"); // Set to zero on all boundaries - ddt(U) += hyper_mu_x * metric->g11 * D2DX2(U); + ddt(U) += hyper_mu_x * metric->g11() * D2DX2(U); if (first_run) { // Print out maximum values of viscosity used on this processor output.write(" Hyper-viscosity values:\n"); @@ -1840,7 +1797,8 @@ class ELMpb : public PhysicsModel { ddt(U) -= 0.5 * Upara2 * bracket(Pi0, Dperp2Phi, bm_exb) / B0; Field3D B0phi = B0 * phi; mesh->communicate(B0phi); - Field3D B0phi0 = B0 * phi0; + Field2D res = B0 * phi0; + Field3D B0phi0 = res; mesh->communicate(B0phi0); ddt(U) += 0.5 * Upara2 * bracket(B0phi, Dperp2Pi0, bm_exb) / B0; ddt(U) += 0.5 * Upara2 * bracket(B0phi0, Dperp2Pi, bm_exb) / B0; @@ -1907,7 +1865,7 @@ class ELMpb : public PhysicsModel { BoutReal pnorm = P0(0, 0); ddt(P) += heating_P * source_expx2(P0, 2. * hp_width, 0.5 * hp_length) * (Tbar / pnorm); // heat source - ddt(P) += (100. * source_tanhx(P0, hp_width, hp_length) + 0.01) * metric->g11 + ddt(P) += (100. * source_tanhx(P0, hp_width, hp_length) + 0.01) * metric->g11() * D2DX2(P) * (Tbar / Lbar / Lbar); // radial diffusion } diff --git a/examples/elm-pb/CMakeLists.txt b/examples/elm-pb/CMakeLists.txt index 8c672822cf..6cdd0f9cd9 100644 --- a/examples/elm-pb/CMakeLists.txt +++ b/examples/elm-pb/CMakeLists.txt @@ -2,14 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(elm_pb LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(elm_pb +bout_add_example( + elm_pb SOURCES elm_pb.cxx - EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc - data/BOUT.inp - data-hypre/BOUT.inp - data-nonlinear/BOUT.inp) - + EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc data/BOUT.inp data-hypre/BOUT.inp + data-nonlinear/BOUT.inp +) diff --git a/examples/elm-pb/Python/2dprofile.py b/examples/elm-pb/Python/2dprofile.py index 5bb01972f9..e95709ab5b 100644 --- a/examples/elm-pb/Python/2dprofile.py +++ b/examples/elm-pb/Python/2dprofile.py @@ -4,81 +4,92 @@ import numpy as np import matplotlib.pyplot as plt from boututils.datafile import DataFile -from matplotlib.ticker import FixedFormatter, FormatStrFormatter, AutoLocator, AutoMinorLocator +from matplotlib.ticker import ( + FixedFormatter, + FormatStrFormatter, + AutoLocator, + AutoMinorLocator, +) with DataFile("./cbm18_dens8.grid_nx68ny64.nc") as f: g = {v: f.read(v) for v in f.keys()} -majorLocator = AutoLocator() -majorFormatter = FormatStrFormatter('%3.0e') -minorLocator = AutoMinorLocator() -Fm = FixedFormatter(['0','$1 \\times 10^4$','$2 \\times 10^4$','$3 \\times 10^4$','$4 \\times 10^4$']) -Fm2 = FixedFormatter(['0','$2 \\times 10^5$','$4 \\times 10^5$','$6 \\times 10^5$']) - -bxy=g.get('Bxy') -p=g.get('pressure') -jpar0=g.get('Jpar0') -psixy=g.get('psixy') -btxy=g.get('Btxy') -shiftangle=g.get('ShiftAngle') - -nx=g.get('nx') -ny=g.get('ny') +majorLocator = AutoLocator() +majorFormatter = FormatStrFormatter("%3.0e") +minorLocator = AutoMinorLocator() +Fm = FixedFormatter( + [ + "0", + "$1 \\times 10^4$", + "$2 \\times 10^4$", + "$3 \\times 10^4$", + "$4 \\times 10^4$", + ] +) +Fm2 = FixedFormatter(["0", "$2 \\times 10^5$", "$4 \\times 10^5$", "$6 \\times 10^5$"]) + +bxy = g.get("Bxy") +p = g.get("pressure") +jpar0 = g.get("Jpar0") +psixy = g.get("psixy") +btxy = g.get("Btxy") +shiftangle = g.get("ShiftAngle") + +nx = g.get("nx") +ny = g.get("ny") q = np.zeros((nx, ny)) for i in range(ny): - q[:,i] = old_div(- shiftangle, (2 * np.pi)) - - + q[:, i] = old_div(-shiftangle, (2 * np.pi)) -xarr = psixy[:,0] +xarr = psixy[:, 0] xarr = old_div((xarr + 0.854856), (0.854856 + 0.0760856)) -fig=plt.figure() -plt.plot(xarr,q[:,32]) -plt.xlabel('normalized $\psi$', fontsize=25) -plt.ylabel('$q$',rotation='horizontal',fontsize=25) +fig = plt.figure() +plt.plot(xarr, q[:, 32]) +plt.xlabel("normalized $\psi$", fontsize=25) +plt.ylabel("$q$", rotation="horizontal", fontsize=25) fig.set_tight_layout(True) fig, ax1 = plt.subplots() -ax1.plot(xarr, p[:,32], 'r-', markevery=1, linewidth=3) -ax1.set_xlabel('normalized $\psi$',fontsize=25) +ax1.plot(xarr, p[:, 32], "r-", markevery=1, linewidth=3) +ax1.set_xlabel("normalized $\psi$", fontsize=25) # Make the y-axis label and tick labels match the line color. -ax1.set_ylabel('Pressure [Pa]', color='k',fontsize=25) +ax1.set_ylabel("Pressure [Pa]", color="k", fontsize=25) -#set y limit -ax1.set_ylim(0,40000,10000) +# set y limit +ax1.set_ylim(0, 40000, 10000) -#define ticks# +# define ticks# ax1.yaxis.set_ticks(np.arange(0, 40000, 10000)) -#ax1.yaxis.set_major_locator(majorLocator) -#ax1.yaxis.set_major_formatter(majorFormatter) +# ax1.yaxis.set_major_locator(majorLocator) +# ax1.yaxis.set_major_formatter(majorFormatter) ax1.yaxis.set_major_formatter(Fm) -#for the minor ticks, use no labels; default NullFormatter +# for the minor ticks, use no labels; default NullFormatter ax1.xaxis.set_minor_locator(AutoMinorLocator()) ax1.yaxis.set_minor_locator(AutoMinorLocator(10)) -#format tick labels +# format tick labels for tl in ax1.get_yticklabels(): - tl.set_color('k') + tl.set_color("k") ax2 = ax1.twinx() s2 = -jpar0 -ax2.plot(xarr, s2[:,32], 'r-',markevery=1,linewidth=3) -ax2.set_ylabel('$J_\parallel [A/m^2]$', color='k',fontsize=25) -ax2.set_ylim(0,600000) +ax2.plot(xarr, s2[:, 32], "r-", markevery=1, linewidth=3) +ax2.set_ylabel("$J_\parallel [A/m^2]$", color="k", fontsize=25) +ax2.set_ylim(0, 600000) ax2.yaxis.set_ticks(np.arange(0, 600000, 200000)) ax2.yaxis.set_major_formatter(Fm2) for tl in ax2.get_yticklabels(): - tl.set_color('k') + tl.set_color("k") fig.set_tight_layout(True) @@ -86,4 +97,4 @@ plt.show() -#plt.savefig('2d.png', transparent=True) +# plt.savefig('2d.png', transparent=True) diff --git a/examples/elm-pb/Python/analysis.py b/examples/elm-pb/Python/analysis.py index 4faf85f8ce..0e4a3acfdd 100644 --- a/examples/elm-pb/Python/analysis.py +++ b/examples/elm-pb/Python/analysis.py @@ -6,24 +6,24 @@ import pylab as plt from boutdata.collect import collect -path='./data/' -var=collect('P', path=path) +path = "./data/" +var = collect("P", path=path) -dcvar=np.mean(var, axis=3) -rmsvar=np.sqrt(np.mean(var**2,axis=3)-dcvar**2) +dcvar = np.mean(var, axis=3) +rmsvar = np.sqrt(np.mean(var**2, axis=3) - dcvar**2) plt.figure() -plt.plot(rmsvar[:,34,32]) +plt.plot(rmsvar[:, 34, 32]) plt.show(block=False) -fvar=np.fft.rfft(var,axis=3) +fvar = np.fft.rfft(var, axis=3) plt.figure() -plt.plot(abs(fvar[:,34,32,1:10])) +plt.plot(abs(fvar[:, 34, 32, 1:10])) plt.show(block=False) plt.figure() -plt.semilogy(abs(fvar[:,34,32,1:7])) +plt.semilogy(abs(fvar[:, 34, 32, 1:7])) plt.show(block=False) plt.show() diff --git a/examples/elm-pb/Python/data/BOUT.inp b/examples/elm-pb/Python/data/BOUT.inp index f0970f22bd..73020e34d4 100644 --- a/examples/elm-pb/Python/data/BOUT.inp +++ b/examples/elm-pb/Python/data/BOUT.inp @@ -67,7 +67,7 @@ upwind = W3 atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning use_jacobian = false # Use user-supplied Jacobian mxstep = 5000 # Number of internal steps between outputs diff --git a/examples/elm-pb/Python/data0/BOUT.inp b/examples/elm-pb/Python/data0/BOUT.inp index 918530981c..330ee8bc06 100644 --- a/examples/elm-pb/Python/data0/BOUT.inp +++ b/examples/elm-pb/Python/data0/BOUT.inp @@ -68,7 +68,7 @@ upwind = W3 atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning use_jacobian = false # Use user-supplied Jacobian mxstep = 5000 # Number of internal steps between outputs diff --git a/examples/elm-pb/Python/elm_size.py b/examples/elm-pb/Python/elm_size.py index 0d5c105870..6ad2ed6a0d 100644 --- a/examples/elm-pb/Python/elm_size.py +++ b/examples/elm-pb/Python/elm_size.py @@ -4,87 +4,126 @@ from past.utils import old_div import numpy as np -def elm_size(dcp,p0,uedge,xmin=None,xmax=None,yind=None,Bbar=None): - - lis=[dcp,p0,uedge] - if np.size(lis) != 3 : + +def elm_size(dcp, p0, uedge, xmin=None, xmax=None, yind=None, Bbar=None): + lis = [dcp, p0, uedge] + if np.size(lis) != 3: print("lack of parameters") return 0 - - if xmin == None : xmin=0 - if xmax == None : xmax=327 - if yind == None : yind=63 # choose the poloidal location for 1D size - if Bbar == None : Bbar=1.992782 # the normalized magnetic field + if xmin == None: + xmin = 0 + if xmax == None: + xmax = 327 + if yind == None: + yind = 63 # choose the poloidal location for 1D size + if Bbar == None: + Bbar = 1.992782 # the normalized magnetic field - mydcp=dcp - myp0=p0 - g=uedge + mydcp = dcp + myp0 = p0 + g = uedge PI = 3.1415926 - MU0 = 4.0e-7*PI + MU0 = 4.0e-7 * PI - s=np.shape(mydcp) + s = np.shape(mydcp) - if np.ndim(mydcp) != 3 : + if np.ndim(mydcp) != 3: print("dcp should be 3D(t,x,y)") - - - nt=s[0] - nx=s[1] - ny=s[2] - - Dtheta=g['dy'] #using correct poloidal angle - psixy=g['psixy'] - R=g['Rxy'] - Bp=g['Bpxy'] - hthe=g['hthe'] - - Dpsi=np.zeros((nx,ny)) - Dpsi[0,:]=psixy[1,:]-psixy[0,:] - Dpsi[nx-1,:]=psixy[nx-1,:]-psixy[nx-2,:] - for i in range(1,nx-2): - Dpsi[i,:]=old_div((psixy[i+1,:]-psixy[i-1,:]),2) - - - Ddcp1=np.zeros(nt) - Ddcp2=np.zeros(nt) - Ddcp3=np.zeros(nt) - Tp01=0. - Tp02=0. - Tp03=0. - - for t in range(nt) : - Ddcp3[t]=2.0*PI*np.sum(mydcp[t,xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/Bp[xmin:xmax,:]) - Ddcp2[t]=np.sum(mydcp[t,xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/(R[xmin:xmax,:]*Bp[xmin:xmax,:])) - Ddcp1[t]=np.sum(mydcp[t,xmin:xmax,yind]*Dpsi[xmin:xmax,yind]/(R[xmin:xmax,yind]*Bp[xmin:xmax,yind])) - - - Tp03=2.0*PI*np.sum(myp0[xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/Bp[xmin:xmax,:]) - Tp02=np.sum(myp0[xmin:xmax,:]*hthe[xmin:xmax,:]*Dtheta[xmin:xmax,:]*Dpsi[xmin:xmax,:]/(R[xmin:xmax,:]*Bp[xmin:xmax,:])) - Tp01=np.sum(myp0[xmin:xmax,yind]*Dpsi[xmin:xmax,yind]/(R[xmin:xmax,yind]*Bp[xmin:xmax,yind])) - - s1=np.zeros(nt) - s2=np.zeros(nt) - s3=np.zeros(nt) - E_loss=np.zeros(nt) - - s1=old_div(-Ddcp1,Tp01) #1D elm size - s2=old_div(-Ddcp2,Tp02) #2D elm size - s3=old_div(-Ddcp3,Tp03) #3D elm size - - E_loss=-Ddcp3*(0.5*Bbar*Bbar/MU0) #energy loss, unit J - E_total=Tp03*(0.5*Bbar*Bbar/MU0) #total energy, unit J + + nt = s[0] + nx = s[1] + ny = s[2] + + Dtheta = g["dy"] # using correct poloidal angle + psixy = g["psixy"] + R = g["Rxy"] + Bp = g["Bpxy"] + hthe = g["hthe"] + + Dpsi = np.zeros((nx, ny)) + Dpsi[0, :] = psixy[1, :] - psixy[0, :] + Dpsi[nx - 1, :] = psixy[nx - 1, :] - psixy[nx - 2, :] + for i in range(1, nx - 2): + Dpsi[i, :] = old_div((psixy[i + 1, :] - psixy[i - 1, :]), 2) + + Ddcp1 = np.zeros(nt) + Ddcp2 = np.zeros(nt) + Ddcp3 = np.zeros(nt) + Tp01 = 0.0 + Tp02 = 0.0 + Tp03 = 0.0 + + for t in range(nt): + Ddcp3[t] = ( + 2.0 + * PI + * np.sum( + mydcp[t, xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / Bp[xmin:xmax, :] + ) + ) + Ddcp2[t] = np.sum( + mydcp[t, xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / (R[xmin:xmax, :] * Bp[xmin:xmax, :]) + ) + Ddcp1[t] = np.sum( + mydcp[t, xmin:xmax, yind] + * Dpsi[xmin:xmax, yind] + / (R[xmin:xmax, yind] * Bp[xmin:xmax, yind]) + ) + + Tp03 = ( + 2.0 + * PI + * np.sum( + myp0[xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / Bp[xmin:xmax, :] + ) + ) + Tp02 = np.sum( + myp0[xmin:xmax, :] + * hthe[xmin:xmax, :] + * Dtheta[xmin:xmax, :] + * Dpsi[xmin:xmax, :] + / (R[xmin:xmax, :] * Bp[xmin:xmax, :]) + ) + Tp01 = np.sum( + myp0[xmin:xmax, yind] + * Dpsi[xmin:xmax, yind] + / (R[xmin:xmax, yind] * Bp[xmin:xmax, yind]) + ) + + s1 = np.zeros(nt) + s2 = np.zeros(nt) + s3 = np.zeros(nt) + E_loss = np.zeros(nt) + + s1 = old_div(-Ddcp1, Tp01) # 1D elm size + s2 = old_div(-Ddcp2, Tp02) # 2D elm size + s3 = old_div(-Ddcp3, Tp03) # 3D elm size + + E_loss = -Ddcp3 * (0.5 * Bbar * Bbar / MU0) # energy loss, unit J + E_total = Tp03 * (0.5 * Bbar * Bbar / MU0) # total energy, unit J class ELM: pass - elmsize=ELM() - elmsize.s1=s1 - elmsize.s2=s2 - elmsize.s3=s3 - elmsize.E_loss=E_loss - elmsize.E_total=E_total + + elmsize = ELM() + elmsize.s1 = s1 + elmsize.s2 = s2 + elmsize.s3 = s3 + elmsize.E_loss = E_loss + elmsize.E_total = E_total return elmsize - - diff --git a/examples/elm-pb/Python/fftall.py b/examples/elm-pb/Python/fftall.py index e0a4385764..c6d5b87ded 100644 --- a/examples/elm-pb/Python/fftall.py +++ b/examples/elm-pb/Python/fftall.py @@ -2,8 +2,7 @@ from numpy import * from scipy.io import readsav -print('Calculating P..') -a=transpose(readsav('phi.idl.dat')['phi']) -fa=fft.fft(a,axis=2) -save('fp',fa) - +print("Calculating P..") +a = transpose(readsav("phi.idl.dat")["phi"]) +fa = fft.fft(a, axis=2) +save("fp", fa) diff --git a/examples/elm-pb/Python/fftall2.py b/examples/elm-pb/Python/fftall2.py index d864f356d0..64b08c437a 100644 --- a/examples/elm-pb/Python/fftall2.py +++ b/examples/elm-pb/Python/fftall2.py @@ -2,9 +2,9 @@ from numpy import * from boutdata.collect import collect -path='./data/' -data=collect('P',path=path) +path = "./data/" +data = collect("P", path=path) -print('Saving P..') -fa=fft.fft(data,axis=3) -save('fp',rollaxis(fa,0,4)) +print("Saving P..") +fa = fft.fft(data, axis=3) +save("fp", rollaxis(fa, 0, 4)) diff --git a/examples/elm-pb/Python/grate.py b/examples/elm-pb/Python/grate.py index 003f38ff8e..65d6da6449 100644 --- a/examples/elm-pb/Python/grate.py +++ b/examples/elm-pb/Python/grate.py @@ -8,12 +8,11 @@ from boututils.moment_xyzt import moment_xyzt +path = "./data/" -path='./data/' +p = collect("P", path=path) +rmsp_f = moment_xyzt(p[:, 34:35, 32:33, :], "RMS").rms -p=collect('P',path=path) -rmsp_f=moment_xyzt(p[:,34:35,32:33,:], 'RMS').rms - -print(np.gradient(np.log(rmsp_f[:,0,0]))[-1]) +print(np.gradient(np.log(rmsp_f[:, 0, 0]))[-1]) diff --git a/examples/elm-pb/Python/grate2.py b/examples/elm-pb/Python/grate2.py index f8172bcf08..af0768803a 100644 --- a/examples/elm-pb/Python/grate2.py +++ b/examples/elm-pb/Python/grate2.py @@ -2,6 +2,7 @@ from __future__ import division from builtins import range from past.utils import old_div + ### # computes average growth rate for all points at the final timestep # computes average growth rate for points in the mead plane at the final timestep @@ -10,40 +11,44 @@ from boutdata.collect import collect from boututils.moment_xyzt import moment_xyzt -path='./data/' +path = "./data/" + +p = collect("P", path=path) -p=collect('P',path=path) +nmpy = old_div(p.shape[2], 2) # define mead plane -nmpy=old_div(p.shape[2],2) # define mead plane +ik = 50 # disregard the first ik timesteps -ik = 50 # disregard the first ik timesteps def gr(p): - rmsp_f=moment_xyzt(p, 'RMS').rms + rmsp_f = moment_xyzt(p, "RMS").rms - ni=np.shape(rmsp_f)[1] - nj=np.shape(rmsp_f)[2] + ni = np.shape(rmsp_f)[1] + nj = np.shape(rmsp_f)[2] - growth=np.zeros((ni,nj)) + growth = np.zeros((ni, nj)) - for i in range(ni): - for j in range(nj): - growth[i,j]=np.gradient(np.log(rmsp_f[ik::,i,j]))[-1] + for i in range(ni): + for j in range(nj): + growth[i, j] = np.gradient(np.log(rmsp_f[ik::, i, j]))[-1] - return growth + return growth -growth=gr(p) +growth = gr(p) -d=np.ma.masked_array(growth,np.isnan(growth)) +d = np.ma.masked_array(growth, np.isnan(growth)) # masked arrays # http://stackoverflow.com/questions/5480694/numpy-calculate-averages-with-nans-removed -print('Total mean value = ', np.mean(np.ma.masked_array(d,np.isinf(d)))) -mm=np.ma.masked_array(growth[:,nmpy],np.isnan(growth[:,nmpy])) -if np.isinf(np.mean(mm)) : - print('There is an Inf value in the mead plane') - print('Mean value of floating numbers in mead plane is = ', np.mean(np.ma.masked_array(mm,np.isinf(mm)))) +print("Total mean value = ", np.mean(np.ma.masked_array(d, np.isinf(d)))) +mm = np.ma.masked_array(growth[:, nmpy], np.isnan(growth[:, nmpy])) +if np.isinf(np.mean(mm)): + print("There is an Inf value in the mead plane") + print( + "Mean value of floating numbers in mead plane is = ", + np.mean(np.ma.masked_array(mm, np.isinf(mm))), + ) else: - print('Mean value in mead plane= ', np.mean(mm)) + print("Mean value in mead plane= ", np.mean(mm)) diff --git a/examples/elm-pb/Python/plotcollapse.py b/examples/elm-pb/Python/plotcollapse.py index ee64ca381f..f68e7b06aa 100755 --- a/examples/elm-pb/Python/plotcollapse.py +++ b/examples/elm-pb/Python/plotcollapse.py @@ -10,49 +10,52 @@ import os from pathlib import Path -#Dynamic matplotlib settings +# Dynamic matplotlib settings from matplotlib import rcParams -rcParams['font.size'] = 20. -rcParams['legend.fontsize'] = 'small' -rcParams['lines.linewidth'] = 2 -if not os.path.exists('image'): - os.makedirs('image') +rcParams["font.size"] = 20.0 +rcParams["legend.fontsize"] = "small" +rcParams["lines.linewidth"] = 2 + +if not os.path.exists("image"): + os.makedirs("image") filename = Path(__file__).with_name("cbm18_dens8.grid_nx68ny64.nc") with DataFile(str(filename)) as f: g = {v: f.read(v) for v in f.keys()} -psi = old_div((g['psixy'][:, 32] - g['psi_axis']), (g['psi_bndry'] - g['psi_axis'])) +psi = old_div((g["psixy"][:, 32] - g["psi_axis"]), (g["psi_bndry"] - g["psi_axis"])) -path = './data' +path = "./data" plt.figure() -p0=collect('P0', path=path) +p0 = collect("P0", path=path) -p=collect('P', path=path) -res = moment_xyzt(p,'RMS','DC') +p = collect("P", path=path) +res = moment_xyzt(p, "RMS", "DC") rmsp = res.rms dcp = res.dc nt = dcp.shape[0] -plt.plot(psi, p0[:, 32], 'k--', label='t=0') -plt.plot(psi, p0[:, 32] + dcp[nt//4, :, 32], 'r-', label='t='+np.str(nt//4)) -plt.plot(psi, p0[:, 32] + dcp[nt//2, :, 32], 'g-', label='t='+np.str(nt//2)) -plt.plot(psi, p0[:, 32] + dcp[3*nt//4, :, 32], 'b-', label='t='+np.str(3*nt//4)) -plt.plot(psi, p0[:, 32] + dcp[-1, :, 32], 'c-', label='t='+np.str(nt)) +plt.plot(psi, p0[:, 32], "k--", label="t=0") +plt.plot(psi, p0[:, 32] + dcp[nt // 4, :, 32], "r-", label="t=" + np.str(nt // 4)) +plt.plot(psi, p0[:, 32] + dcp[nt // 2, :, 32], "g-", label="t=" + np.str(nt // 2)) +plt.plot( + psi, p0[:, 32] + dcp[3 * nt // 4, :, 32], "b-", label="t=" + np.str(3 * nt // 4) +) +plt.plot(psi, p0[:, 32] + dcp[-1, :, 32], "c-", label="t=" + np.str(nt)) plt.legend() -#plt.xlim(0.6, 1.0) -plt.xlabel(r'Normalized poloidal flux ($\psi$)') -plt.ylabel(r'$\langle p\rangle_\xi$') -plt.title(r'Pressure') +# plt.xlim(0.6, 1.0) +plt.xlabel(r"Normalized poloidal flux ($\psi$)") +plt.ylabel(r"$\langle p\rangle_\xi$") +plt.title(r"Pressure") xmin, xmax = plt.xlim() ymin, ymax = plt.ylim() -#plt.savefig('image/plotcollapse.png', bbox_inches='tight') -#plt.savefig('image/plotcollapse.eps', bbox_inches='tight') +# plt.savefig('image/plotcollapse.png', bbox_inches='tight') +# plt.savefig('image/plotcollapse.eps', bbox_inches='tight') plt.tight_layout() diff --git a/examples/elm-pb/Python/plotmode.py b/examples/elm-pb/Python/plotmode.py index d89fdaf940..9325ee8764 100644 --- a/examples/elm-pb/Python/plotmode.py +++ b/examples/elm-pb/Python/plotmode.py @@ -4,60 +4,57 @@ from builtins import range from past.utils import old_div -from numpy import *; -#from scipy.io import readsav; -import matplotlib.pyplot as plt; +from numpy import * + +# from scipy.io import readsav; +import matplotlib.pyplot as plt # Dynamic matplotlib settings -from matplotlib import rcParams; -rcParams['font.size'] = 20; -rcParams['legend.fontsize'] = 'small'; -rcParams['legend.labelspacing'] = 0.1; -rcParams['lines.linewidth'] = 2; -rcParams['savefig.bbox'] = 'tight'; +from matplotlib import rcParams +rcParams["font.size"] = 20 +rcParams["legend.fontsize"] = "small" +rcParams["legend.labelspacing"] = 0.1 +rcParams["lines.linewidth"] = 2 +rcParams["savefig.bbox"] = "tight" # Create image directory if not exists -import os; -if not os.path.exists('image'): - os.makedirs('image'); - -#fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; -fphi = load('fp.npy') - -plt.figure(); -for i in range(1, 9): - print("Growth rate for mode number", i) - print(gradient(log(abs(fphi[34, 32, i, :])))) - plt.semilogy(((abs(fphi[34, 32, i, :]))), label = 'n=' + str(i * 5)); +import os -plt.legend(loc=2); -plt.xlabel('Time'); -plt.savefig('image/plotmode.png'); -plt.savefig('image/plotmode.eps'); +if not os.path.exists("image"): + os.makedirs("image") +# fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; +fphi = load("fp.npy") -plt.show(block=False); -plt.figure(); +plt.figure() for i in range(1, 9): - plt.plot(abs(fphi[:, 32, i, -1]), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodeamp.png'); -plt.savefig('image/plotmodeamp.eps'); - -plt.show(block=False); - -plt.figure(); + print("Growth rate for mode number", i) + print(gradient(log(abs(fphi[34, 32, i, :])))) + plt.semilogy((abs(fphi[34, 32, i, :])), label="n=" + str(i * 5)) + +plt.legend(loc=2) +plt.xlabel("Time") +plt.savefig("image/plotmode.png") +plt.savefig("image/plotmode.eps") +plt.show(block=False) +plt.figure() for i in range(1, 9): - plt.plot(old_div(abs(fphi[:, 32, i, -1]),abs(fphi[:, 32, i, -1]).max()), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodenorm.png'); -plt.savefig('image/plotmodenorm.eps'); - -plt.show(); - + plt.plot(abs(fphi[:, 32, i, -1]), label="n=" + str(i * 5)) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodeamp.png") +plt.savefig("image/plotmodeamp.eps") +plt.show(block=False) +plt.figure() +for i in range(1, 9): + plt.plot( + old_div(abs(fphi[:, 32, i, -1]), abs(fphi[:, 32, i, -1]).max()), + label="n=" + str(i * 5), + ) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodenorm.png") +plt.savefig("image/plotmodenorm.eps") +plt.show() diff --git a/examples/elm-pb/Python/plotmode2.py b/examples/elm-pb/Python/plotmode2.py index d0c63f32d9..c298a3a5ef 100644 --- a/examples/elm-pb/Python/plotmode2.py +++ b/examples/elm-pb/Python/plotmode2.py @@ -4,63 +4,61 @@ from builtins import range from past.utils import old_div -from numpy import *; -#from scipy.io import readsav; -import matplotlib.pyplot as plt; +from numpy import * + +# from scipy.io import readsav; +import matplotlib.pyplot as plt from boutdata.collect import collect # Dynamic matplotlib settings -from matplotlib import rcParams; -rcParams['font.size'] = 20; -rcParams['legend.fontsize'] = 'small'; -rcParams['legend.labelspacing'] = 0.1; -rcParams['lines.linewidth'] = 2; -rcParams['savefig.bbox'] = 'tight'; +from matplotlib import rcParams +rcParams["font.size"] = 20 +rcParams["legend.fontsize"] = "small" +rcParams["legend.labelspacing"] = 0.1 +rcParams["lines.linewidth"] = 2 +rcParams["savefig.bbox"] = "tight" # Create image directory if not exists -import os; -if not os.path.exists('image'): - os.makedirs('image'); +import os + +if not os.path.exists("image"): + os.makedirs("image") -path='./data/' -data=collect('P',path=path) +path = "./data/" +data = collect("P", path=path) -#fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; +# fphi = transpose(readsav('fphi.idl.dat')['fphi'])[:,:,:,]; fphi = fft.fft(data, axis=3) -plt.figure(); +plt.figure() for i in range(1, 9): - print("Growth rate for mode number", i) - print(gradient(log(abs(fphi[:,34, 32, i])))) - plt.semilogy(((abs(fphi[:,34, 32, i]))), label = 'n=' + str(i * 5)); - -plt.legend(loc=2); -plt.xlabel('Time'); -plt.savefig('image/plotmode.png'); -plt.savefig('image/plotmode.eps'); - - -plt.show(block=False); -plt.figure(); + print("Growth rate for mode number", i) + print(gradient(log(abs(fphi[:, 34, 32, i])))) + plt.semilogy((abs(fphi[:, 34, 32, i])), label="n=" + str(i * 5)) + +plt.legend(loc=2) +plt.xlabel("Time") +plt.savefig("image/plotmode.png") +plt.savefig("image/plotmode.eps") +plt.show(block=False) +plt.figure() for i in range(1, 9): - plt.plot(abs(fphi[-1, :, 32, i]), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodeamp.png'); -plt.savefig('image/plotmodeamp.eps'); - -plt.show(block=False); - -plt.figure(); + plt.plot(abs(fphi[-1, :, 32, i]), label="n=" + str(i * 5)) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodeamp.png") +plt.savefig("image/plotmodeamp.eps") +plt.show(block=False) +plt.figure() for i in range(1, 9): - plt.plot(old_div(abs(fphi[-1, :, 32, i]),abs(fphi[-1, :, 32, i]).max()), label = 'n=' + str(i * 5)); - -plt.legend(); -plt.xlabel('X index'); - -plt.savefig('image/plotmodenorm.png'); -plt.savefig('image/plotmodenorm.eps'); - -plt.show(); + plt.plot( + old_div(abs(fphi[-1, :, 32, i]), abs(fphi[-1, :, 32, i]).max()), + label="n=" + str(i * 5), + ) + +plt.legend() +plt.xlabel("X index") +plt.savefig("image/plotmodenorm.png") +plt.savefig("image/plotmodenorm.eps") +plt.show() diff --git a/examples/elm-pb/Python/plotphase.py b/examples/elm-pb/Python/plotphase.py index 9225e498ae..10f4279cf4 100755 --- a/examples/elm-pb/Python/plotphase.py +++ b/examples/elm-pb/Python/plotphase.py @@ -4,34 +4,33 @@ from numpy import save, load, angle import matplotlib.pyplot as plt -fphi = load('fphi.npy') +fphi = load("fphi.npy") -fte = load('fte.npy') -phase_te = angle(old_div(fphi,fte)) -save('phase_te', phase_te) +fte = load("fte.npy") +phase_te = angle(old_div(fphi, fte)) +save("phase_te", phase_te) plt.figure() -plt.plot(mean(mean(phase_te[:,:,3,:],axis=1),axis=1)) -plt.title('Te') -plt.savefig('image/phase_te.png') -plt.savefig('image/phase_te.eps') +plt.plot(mean(mean(phase_te[:, :, 3, :], axis=1), axis=1)) +plt.title("Te") +plt.savefig("image/phase_te.png") +plt.savefig("image/phase_te.eps") -fti = load('fti.npy') -phase_ti = angle(old_div(fphi,fti)) -save('phase_ti', phase_ti) +fti = load("fti.npy") +phase_ti = angle(old_div(fphi, fti)) +save("phase_ti", phase_ti) plt.figure() -plt.plot(mean(mean(phase_ti[:,:,3,:],axis=1),axis=1)) -plt.title('ti') -plt.savefig('image/phase_ti.png') -plt.savefig('image/phase_ti.eps') +plt.plot(mean(mean(phase_ti[:, :, 3, :], axis=1), axis=1)) +plt.title("ti") +plt.savefig("image/phase_ti.png") +plt.savefig("image/phase_ti.eps") -fni = load('fni.npy') -phase_ni = angle(old_div(fphi,fni)) -save('phase_ni', phase_ni) +fni = load("fni.npy") +phase_ni = angle(old_div(fphi, fni)) +save("phase_ni", phase_ni) plt.figure() -plt.plot(mean(mean(phase_ni[:,:,3,:],axis=1),axis=1)) -plt.title('ni') -plt.savefig('image/phase_ni.png') -plt.savefig('image/phase_ni.eps') +plt.plot(mean(mean(phase_ni[:, :, 3, :], axis=1), axis=1)) +plt.title("ni") +plt.savefig("image/phase_ni.png") +plt.savefig("image/phase_ni.eps") plt.show() - diff --git a/examples/elm-pb/Python/polslice.py b/examples/elm-pb/Python/polslice.py index fe78495b5a..6a1179b2ae 100644 --- a/examples/elm-pb/Python/polslice.py +++ b/examples/elm-pb/Python/polslice.py @@ -11,31 +11,33 @@ # Specify parameters -path='./data/' +path = "./data/" -variable="P" +variable = "P" p = collect(variable, path=path) -period=15 +period = 15 -grid='../cbm18_dens8.grid_nx68ny64.nc' +grid = "../cbm18_dens8.grid_nx68ny64.nc" ######################################################## # Call plotpolslice once to get extended poloidal grid -r,z,fun=plotpolslice(p[0,:,:,:],grid,period=period,rz=1) +r, z, fun = plotpolslice(p[0, :, :, :], grid, period=period, rz=1) -nx=r.shape[0] # number of points in r -ny=r.shape[1] # number of points in z -nt=p.shape[0] # time intervals +nx = r.shape[0] # number of points in r +ny = r.shape[1] # number of points in z +nt = p.shape[0] # time intervals -fm=np.zeros((nt,nx,ny)) # array to store the time sequence of the poloidal cross section +fm = np.zeros( + (nt, nx, ny) +) # array to store the time sequence of the poloidal cross section -#Compute all time frames +# Compute all time frames for k in range(nt): - fm[k,:,:]=plotpolslice(p[k,:,:,:],grid,period=period,rz=0) + fm[k, :, :] = plotpolslice(p[k, :, :, :], grid, period=period, rz=0) -np.savez('pslice',fm=fm, z=z, r=r) +np.savez("pslice", fm=fm, z=z, r=r) diff --git a/examples/elm-pb/Python/post.py b/examples/elm-pb/Python/post.py index 9bb67347f0..cdaefa98cf 100644 --- a/examples/elm-pb/Python/post.py +++ b/examples/elm-pb/Python/post.py @@ -15,12 +15,12 @@ from mayavi import mlab -path0="./data0/" -path1="./data/" +path0 = "./data0/" +path1 = "./data/" -period=15 +period = 15 -gfile='./cbm18_dens8.grid_nx68ny64.nc' +gfile = "./cbm18_dens8.grid_nx68ny64.nc" with DataFile(gfile) as f: @@ -28,71 +28,115 @@ Dphi0 = collect("Dphi0", path=path0) -phi0 = collect("phi0", path=path1) # needs diamagnetic effects +phi0 = collect("phi0", path=path1) # needs diamagnetic effects # -psixy=g.get('psixy') -PSI_AXIS=g.get('psi_axis') -PSI_BNDRY=g.get('psi_bndry') +psixy = g.get("psixy") +PSI_AXIS = g.get("psi_axis") +PSI_BNDRY = g.get("psi_bndry") # -psix=old_div((psixy[:,32]-PSI_AXIS),(PSI_BNDRY-PSI_AXIS)) -Epsi=-deriv(phi0[:,32],psix) +psix = old_div((psixy[:, 32] - PSI_AXIS), (PSI_BNDRY - PSI_AXIS)) +Epsi = -deriv(phi0[:, 32], psix) # # -fig=figure() -plot(psix,-Dphi0[:,32], 'r', linewidth=5) -plot(psix,Epsi,'k',linewidth=5) -annotate('w/o flow', xy=(.3, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', size=30) -annotate('w/ flow', xy=(.7, .4), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', color='r', size=30) -xlabel('Radial $\psi$',fontsize=25) -ylabel('$\Omega(\psi)/\omega_A$',fontsize=25) -ylim([-.05,0]) -xlim([0.4,1.2]) +fig = figure() +plot(psix, -Dphi0[:, 32], "r", linewidth=5) +plot(psix, Epsi, "k", linewidth=5) +annotate( + "w/o flow", + xy=(0.3, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + size=30, +) +annotate( + "w/ flow", + xy=(0.7, 0.4), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + color="r", + size=30, +) +xlabel("Radial $\psi$", fontsize=25) +ylabel("$\Omega(\psi)/\omega_A$", fontsize=25) +ylim([-0.05, 0]) +xlim([0.4, 1.2]) fig.set_tight_layout(True) show(block=False) p_f0 = collect("P", path=path0) p_f = collect("P", path=path1) # -rmsp_f0=moment_xyzt(p_f0, 'RMS').rms -rmsp_f=moment_xyzt(p_f, 'RMS').rms +rmsp_f0 = moment_xyzt(p_f0, "RMS").rms +rmsp_f = moment_xyzt(p_f, "RMS").rms # -fig=figure(figsize=(10, 8)) -plot(np.gradient(np.log(rmsp_f0[:,34,32])), color='k',linewidth=3) -plot(np.gradient(np.log(rmsp_f[:,34,32])),color='red',linewidth=3) - -ylabel('$\gamma / \omega_A$',fontsize=25) -xlabel('Time$(\\tau_A)$',fontsize=25) -annotate('w/o flow', xy=(.5, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', size=30) -annotate('w/ flow', xy=(.5, .4), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', color='r', size=30) -ylim([0,0.5]) -xlim([0,100]) +fig = figure(figsize=(10, 8)) +plot(np.gradient(np.log(rmsp_f0[:, 34, 32])), color="k", linewidth=3) +plot(np.gradient(np.log(rmsp_f[:, 34, 32])), color="red", linewidth=3) + +ylabel("$\gamma / \omega_A$", fontsize=25) +xlabel("Time$(\\tau_A)$", fontsize=25) +annotate( + "w/o flow", + xy=(0.5, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + size=30, +) +annotate( + "w/ flow", + xy=(0.5, 0.4), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + color="r", + size=30, +) +ylim([0, 0.5]) +xlim([0, 100]) fig.set_tight_layout(True) show(block=False) - -plotpolslice(p_f0[50,:,:,:],gfile,period=period, fig=1) -mlab.text(.01,.99,"w/o flow") - -plotpolslice(p_f[50,:,:,:],gfile,period=period, fig=1) -mlab.text(.01,.99,"w/ flow") - -fig=figure() -mode_structure(p_f0[50,:,:,:], g, period=period) -plot([40,40],[0,.014],'k--',linewidth=5) -annotate('w/o flow', xy=(.3, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', size=30) -ylim([0,0.014]) -xlim([0,80]) +plotpolslice(p_f0[50, :, :, :], gfile, period=period, fig=1) +mlab.text(0.01, 0.99, "w/o flow") + +plotpolslice(p_f[50, :, :, :], gfile, period=period, fig=1) +mlab.text(0.01, 0.99, "w/ flow") + +fig = figure() +mode_structure(p_f0[50, :, :, :], g, period=period) +plot([40, 40], [0, 0.014], "k--", linewidth=5) +annotate( + "w/o flow", + xy=(0.3, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + size=30, +) +ylim([0, 0.014]) +xlim([0, 80]) fig.set_tight_layout(True) show(block=False) figure() -mode_structure(p_f[50,:,:,:], g, period=period) -plot([40,40],[0,.014],'k--',linewidth=5) -annotate('w/ flow', xy=(.3, .7), xycoords='axes fraction',horizontalalignment='center', verticalalignment='center', color='k', size=30) -ylim([0,0.0001]) -xlim([0,80]) +mode_structure(p_f[50, :, :, :], g, period=period) +plot([40, 40], [0, 0.014], "k--", linewidth=5) +annotate( + "w/ flow", + xy=(0.3, 0.7), + xycoords="axes fraction", + horizontalalignment="center", + verticalalignment="center", + color="k", + size=30, +) +ylim([0, 0.0001]) +xlim([0, 80]) show(block=False) show() diff --git a/examples/elm-pb/Python/read_elmsize.py b/examples/elm-pb/Python/read_elmsize.py index fcd3d24e53..340f57ce7b 100644 --- a/examples/elm-pb/Python/read_elmsize.py +++ b/examples/elm-pb/Python/read_elmsize.py @@ -4,12 +4,12 @@ from pylab import save, figure, plot, title, xlabel, ylabel, show, tight_layout from elm_size import elm_size -path='./data' +path = "./data" -t_array=collect('t_array', path=path) -save('t_array.dat', t_array) -p0=collect('P0', path=path) -save('p0.dat', p0) +t_array = collect("t_array", path=path) +save("t_array.dat", t_array) +p0 = collect("P0", path=path) +save("p0.dat", p0) # n0=collect('n0', path=path) @@ -22,27 +22,27 @@ with DataFile("./cbm18_dens8.grid_nx68ny64.nc") as f: gfile = {v: f.read(v) for v in f.keys()} -p=collect('P', path=path) -save('p.dat', p) -res=moment_xyzt(p,'RMS','DC') -rmsp=res.rms -dcp=res.dc -save('rmsp.dat', rmsp) -save('dcp.dat', dcp) -elmsp=elm_size(dcp,p0,gfile,yind=32,Bbar=gfile['bmag']) -save('elmsp.dat', elmsp) +p = collect("P", path=path) +save("p.dat", p) +res = moment_xyzt(p, "RMS", "DC") +rmsp = res.rms +dcp = res.dc +save("rmsp.dat", rmsp) +save("dcp.dat", dcp) +elmsp = elm_size(dcp, p0, gfile, yind=32, Bbar=gfile["bmag"]) +save("elmsp.dat", elmsp) figure(0) -plot(t_array,elmsp.s2, 'k-') -xlabel('t/Ta') -ylabel('Elm size') -title('Elm size, P') +plot(t_array, elmsp.s2, "k-") +xlabel("t/Ta") +ylabel("Elm size") +title("Elm size, P") tight_layout() show() -phi=collect('phi', path=path ) -save('phi.dat', phi) -res=moment_xyzt( phi, 'DC', 'RMS') -save('dcphi.dat',res.dc) -save('rmsphi.dat', res.rms) +phi = collect("phi", path=path) +save("phi.dat", phi) +res = moment_xyzt(phi, "DC", "RMS") +save("dcphi.dat", res.dc) +save("rmsphi.dat", res.rms) diff --git a/examples/elm-pb/Python/showpolslice.py b/examples/elm-pb/Python/showpolslice.py index d292575e35..072c53dcd6 100644 --- a/examples/elm-pb/Python/showpolslice.py +++ b/examples/elm-pb/Python/showpolslice.py @@ -6,10 +6,12 @@ import numpy as np from tvtk.tools import visual + try: from enthought.mayavi import mlab except ImportError: - try: from mayavi import mlab + try: + from mayavi import mlab except ImportError: print("No mlab available") @@ -17,40 +19,42 @@ ########################### # Read polslice array -npzfile=np.load('pslice.npz') -r=npzfile['r'] -z=npzfile['z'] -fm=npzfile['fm'] +npzfile = np.load("pslice.npz") +r = npzfile["r"] +z = npzfile["z"] +fm = npzfile["fm"] ######################################################## # Set up the window -f = mlab.figure(size=(800,600)) +f = mlab.figure(size=(800, 600)) # Tell visual to use this as the viewer. visual.set_viewer(f) ######################################################## # Do the appropriate graph -#s = mlab.contour_surf(r,z,fun, contours=30, line_width=.5, transparent=True) -#s=mlab.surf(r,z,fun, colormap='Spectral') -s = mlab.mesh(r,z,fm[0,:,:], scalars=fm[0,:,:], colormap='PuOr')#, wrap_scale='true')#, representation='wireframe') -s.enable_contours=True -s.contour.filled_contours=True +# s = mlab.contour_surf(r,z,fun, contours=30, line_width=.5, transparent=True) +# s=mlab.surf(r,z,fun, colormap='Spectral') +s = mlab.mesh( + r, z, fm[0, :, :], scalars=fm[0, :, :], colormap="PuOr" +) # , wrap_scale='true')#, representation='wireframe') +s.enable_contours = True +s.contour.filled_contours = True # Define perspective and optional attributes. You can also implement from the window afterwards -mlab.view(0,0) -#mlab.view(-94.159958841373324, +mlab.view(0, 0) +# mlab.view(-94.159958841373324, # 53.777002382688906, # 8.2311808018087582) mlab.draw(f) mlab.colorbar(orientation="vertical") -#mlab.axes() -#mlab.outline() +# mlab.axes() +# mlab.outline() ######################################################## # mlab animation -anim(s,fm, save=True) +anim(s, fm, save=True) diff --git a/examples/elm-pb/Python/sprofiles.py b/examples/elm-pb/Python/sprofiles.py index 9d8eea48de..244599f8af 100644 --- a/examples/elm-pb/Python/sprofiles.py +++ b/examples/elm-pb/Python/sprofiles.py @@ -16,45 +16,46 @@ with DataFile(gfile) as f: g = {v: f.read(v) for v in f.keys()} -var=collect("P", path=path) +var = collect("P", path=path) -sol=surface_average(var, g) -#sol=np.mean(var,axis=3) +sol = surface_average(var, g) +# sol=np.mean(var,axis=3) -p0av=collect("P0", path=path) +p0av = collect("P0", path=path) -q=np.zeros(sol.shape) +q = np.zeros(sol.shape) for i in range(sol.shape[1]): - q[:,i]=sol[:,i]+p0av[:,0] + q[:, i] = sol[:, i] + p0av[:, 0] -psixy=g.get('psixy') -psi0=g.get('psi_axis') -psix=g.get('psi_bndry') +psixy = g.get("psixy") +psi0 = g.get("psi_axis") +psix = g.get("psi_bndry") -xarr = psixy[:,0] -xarr = old_div((xarr - psi0), (-psi0 + psix)) #for this grid +xarr = psixy[:, 0] +xarr = old_div((xarr - psi0), (-psi0 + psix)) # for this grid -fig=figure() +fig = figure() -nt=q.shape[1] +nt = q.shape[1] -plot(xarr, p0av,'k',label='t=0') -plot(xarr,q[:,nt/4],'r',label='t='+np.str(nt/4)) -plot(xarr,q[:,nt/2],'b',label='t='+np.str(nt/2)) -plot(xarr,q[:,3*nt/4],'g',label='t='+np.str(3*nt/4)) -plot(xarr, q[:,-1],'k',label='t='+np.str(nt)) +plot(xarr, p0av, "k", label="t=0") +plot(xarr, q[:, nt / 4], "r", label="t=" + np.str(nt / 4)) +plot(xarr, q[:, nt / 2], "b", label="t=" + np.str(nt / 2)) +plot(xarr, q[:, 3 * nt / 4], "g", label="t=" + np.str(3 * nt / 4)) +plot(xarr, q[:, -1], "k", label="t=" + np.str(nt)) from collections import OrderedDict + handles, labels = gca().get_legend_handles_labels() by_label = OrderedDict(list(zip(labels, handles))) legend(list(by_label.values()), list(by_label.keys())) -xlabel(r"$\psi$",fontsize=25) -ylabel(r"$2 \mu_0 / B^2$",fontsize=25) +xlabel(r"$\psi$", fontsize=25) +ylabel(r"$2 \mu_0 / B^2$", fontsize=25) fig.set_tight_layout(True) diff --git a/examples/elm-pb/data-hypre/BOUT.inp b/examples/elm-pb/data-hypre/BOUT.inp index 45dd59b536..93088f3d48 100644 --- a/examples/elm-pb/data-hypre/BOUT.inp +++ b/examples/elm-pb/data-hypre/BOUT.inp @@ -44,7 +44,7 @@ fft_measurement_flag = measure # If using FFTW, perform tests to determine fast atol = 1.0e-8 # absolute tolerance rtol = 1.0e-5 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning mxstep = 5000 # Number of internal steps between outputs @@ -240,4 +240,3 @@ bndry_core = neumann bndry_xin = none bndry_xout = none #bndry_target = neumann - diff --git a/examples/elm-pb/data-nonlinear/BOUT.inp b/examples/elm-pb/data-nonlinear/BOUT.inp index b61829c709..e13228ebdf 100644 --- a/examples/elm-pb/data-nonlinear/BOUT.inp +++ b/examples/elm-pb/data-nonlinear/BOUT.inp @@ -66,7 +66,7 @@ fft_measurement_flag = measure # If using FFTW, perform tests to determine fast atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning use_jacobian = false # Use user-supplied Jacobian mxstep = 5000 # Number of internal steps between outputs diff --git a/examples/elm-pb/data/BOUT.inp b/examples/elm-pb/data/BOUT.inp index a37d69a43a..43b1b6f4b0 100644 --- a/examples/elm-pb/data/BOUT.inp +++ b/examples/elm-pb/data/BOUT.inp @@ -47,7 +47,7 @@ fft_measurement_flag = measure # If using FFTW, perform tests to determine fast atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning mxstep = 5000 # Number of internal steps between outputs output_step = 1 # time between outputs diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index d981796200..e4bd1bbee3 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -6,28 +6,28 @@ *******************************************************************************/ #include +#include +#include #include +#include #include +#include +#include +#include +#include +#include #include #include #include #include #include -#include +#include #include +#include #include -#include -#include - #include -#if BOUT_HAS_HYPRE -#include -#endif - -#include - CELL_LOC loc = CELL_CENTRE; /// Set default options @@ -36,6 +36,10 @@ BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_target", "neumann"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xin", "none"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xout", "none"); +#if BOUT_HAS_HYPRE +BOUT_OVERRIDE_DEFAULT_OPTION("laplacexy:type", "hypre"); +#endif + /// 3-field ELM simulation class ELMpb : public PhysicsModel { private: @@ -188,11 +192,7 @@ class ELMpb : public PhysicsModel { bool split_n0; // Solve the n=0 component of potential -#if BOUT_HAS_HYPRE - std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#else std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#endif Field2D phi2D; // Axisymmetric phi @@ -238,9 +238,7 @@ class ELMpb : public PhysicsModel { int damp_width; // Width of inner damped region BoutReal damp_t_const; // Timescale of damping - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, B0, hthe; - Field2D I; // Shear factor + Field2D B0; // Magnetic field const BoutReal MU0 = 4.0e-7 * PI; const BoutReal Mi = 2.0 * 1.6726e-27; // Ion mass @@ -254,8 +252,8 @@ class ELMpb : public PhysicsModel { std::unique_ptr phiSolver{nullptr}; std::unique_ptr aparSolver{nullptr}; - const Field2D N0tanh(BoutReal n0_height, BoutReal n0_ave, BoutReal n0_width, - BoutReal n0_center, BoutReal n0_bottom_x) { + Field2D N0tanh(BoutReal n0_height, BoutReal n0_ave, BoutReal n0_width, + BoutReal n0_center, BoutReal n0_bottom_x) { Field2D result; result.allocate(); @@ -307,9 +305,6 @@ class ELMpb : public PhysicsModel { protected: int init(bool restarting) override { - bool noshear; - - Coordinates* metric = mesh->getCoordinates(); output.write("Solving high-beta flute reduced equations\n"); output.write("\tFile : {:s}\n", __FILE__); @@ -319,24 +314,7 @@ class ELMpb : public PhysicsModel { // Load data from the grid // Load 2D profiles - mesh->get(J0, "Jpar0"); // A / m^2 - mesh->get(P0, "pressure"); // Pascals - - // Load curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 - - // Load metrics - if (mesh->get(Rxy, "Rxy")) { // m - throw BoutException("Error: Cannot read Rxy from grid\n"); - } - if (mesh->get(Bpxy, "Bpxy")) { // T - throw BoutException("Error: Cannot read Bpxy from grid\n"); - } - mesh->get(Btxy, "Btxy"); // T - mesh->get(B0, "Bxy"); // T - mesh->get(hthe, "hthe"); // m - mesh->get(I, "sinty"); // m^-2 T^-1 + mesh->get(P0, "pressure"); // Pascals mesh->get(Psixy, "psixy"); // get Psi mesh->get(Psiaxis, "psi_axis"); // axis flux mesh->get(Psibndry, "psi_bndry"); // edge flux @@ -490,7 +468,7 @@ class ELMpb : public PhysicsModel { experiment_Er = options["experiment_Er"].withDefault(false); - noshear = options["noshear"].withDefault(false); + const bool noshear = options["noshear"].withDefault(false); relax_j_vac = options["relax_j_vac"] .doc("Relax vacuum current to zero") @@ -525,11 +503,8 @@ class ELMpb : public PhysicsModel { .withDefault(false); if (split_n0) { // Create an XY solver for n=0 component -#if BOUT_HAS_HYPRE - laplacexy = bout::utils::make_unique(mesh); -#else - laplacexy = bout::utils::make_unique(mesh); -#endif + laplacexy = LaplaceXY::create(mesh); + // Set coefficients for Boussinesq solve laplacexy->setCoefs(1.0, 0.0); phi2D = 0.0; // Starting guess @@ -673,8 +648,6 @@ class ELMpb : public PhysicsModel { Dphi0 *= -1; } - V0 = -Rxy * Bpxy * Dphi0 / B0; - if (simple_rmp) { include_rmp = true; } @@ -758,46 +731,61 @@ class ELMpb : public PhysicsModel { } } - if (!include_curvature) { + ////////////////////////////////////////////////////////////// + // Read, normalise, and set coordinates + + // Typical magnetic field + mesh->get(Bbar, "bmag", 1.0); + // Typical length scale + mesh->get(Lbar, "rmag", 1.0); + + // Read, normalise, and set coordinates + const auto tokamak_coords = + bout::set_tokamak_coordinates(*mesh, Lbar, Bbar, noshear or mesh->IncIntShear); + const auto& Rxy = tokamak_coords.Rxy; + const auto& Bpxy = tokamak_coords.Bpxy; + const auto& Btxy = tokamak_coords.Btxy; + const auto& hthe = tokamak_coords.hthe; + const auto& I = tokamak_coords.I_unnormalised; + + B0 = tokamak_coords.Bxy; + + // Need to unnormalise Rxy, as we normalise velocity separately + V0 = -(Rxy * Lbar) * Bpxy * Dphi0 / B0; + + if (include_curvature) { + // Load curvature term + b0xcv.covariant = false; // Read contravariant components + mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 + if (noshear) { + b0xcv.z += I * b0xcv.x; + } + } else { b0xcv = 0.0; } - if (!include_jpar0) { + if (include_jpar0) { + mesh->get(J0, "Jpar0"); // A / m^2 + } else { J0 = 0.0; } - if (noshear) { - if (include_curvature) { - b0xcv.z += I * b0xcv.x; - } - I = 0.0; - } - ////////////////////////////////////////////////////////////// // SHIFTED RADIAL COORDINATES if (mesh->IncIntShear) { // BOUT-06 style, using d/dx = d/dpsi + I * d/dz - metric->IntShiftTorsion = I; - + mesh->getCoordinates()->setIntShiftTorsion(I); } else { // Dimits style, using local coordinate system if (include_curvature) { b0xcv.z += I * b0xcv.x; } - I = 0.0; // I disappears from metric } ////////////////////////////////////////////////////////////// // NORMALISE QUANTITIES - if (mesh->get(Bbar, "bmag")) { // Typical magnetic field - Bbar = 1.0; - } - if (mesh->get(Lbar, "rmag")) { // Typical length scale - Lbar = 1.0; - } - Va = sqrt(Bbar * Bbar / (MU0 * density * Mi)); Tbar = Lbar / Va; @@ -898,8 +886,8 @@ class ELMpb : public PhysicsModel { output.write(" drop K-H term\n"); } - Field2D Te; - Te = P0 / (2.0 * density * 1.602e-19); // Temperature in eV + // Temperature in eV + const Field2D Te = P0 / (2.0 * density * 1.602e-19); J0 = -MU0 * Lbar * J0 / B0; P0 = 2.0 * MU0 * P0 / (Bbar * Bbar); @@ -910,14 +898,6 @@ class ELMpb : public PhysicsModel { b0xcv.y *= Lbar * Lbar; b0xcv.z *= Lbar * Lbar; - Rxy /= Lbar; - Bpxy /= Bbar; - Btxy /= Bbar; - B0 /= Bbar; - hthe /= Lbar; - metric->dx /= Lbar * Lbar * Bbar; - I *= Lbar * Lbar * Bbar; - if (constn0) { T0_fake_prof = false; n0_fake_prof = false; @@ -1043,27 +1023,6 @@ class ELMpb : public PhysicsModel { rmp_Psi = 0.0; } - /**************** CALCULATE METRICS ******************/ - - metric->g11 = SQ(Rxy * Bpxy); - metric->g22 = 1.0 / SQ(hthe); - metric->g33 = SQ(I) * metric->g11 + SQ(B0) / metric->g11; - metric->g12 = 0.0; - metric->g13 = -I * metric->g11; - metric->g23 = -Btxy / (hthe * Bpxy * Rxy); - - metric->J = hthe / Bpxy; - metric->Bxy = B0; - - metric->g_11 = 1.0 / metric->g11 + SQ(I * Rxy); - metric->g_22 = SQ(B0 * hthe / Bpxy); - metric->g_33 = Rxy * Rxy; - metric->g_12 = Btxy * hthe * I * Rxy / Bpxy; - metric->g_13 = I * Rxy * Rxy; - metric->g_23 = Btxy * hthe * Rxy / Bpxy; - - metric->geometry(); // Calculate quantities from metric tensor - // Set B field vector B0vec.covariant = false; @@ -1185,7 +1144,7 @@ class ELMpb : public PhysicsModel { // Only if not restarting: Check initial perturbation // Set U to zero where P0 < vacuum_pressure - U = where(P0 - vacuum_pressure, U, 0.0); + U = where(Field2D{P0 - vacuum_pressure}, U, 0.0); if (constn0) { ubyn = U; @@ -1249,7 +1208,7 @@ class ELMpb : public PhysicsModel { // Perform communications mesh->communicate(comms); - Coordinates* metric = mesh->getCoordinates(); + const Coordinates* metric = mesh->getCoordinates(); //////////////////////////////////////////// // Transitions from 0 in core to 1 in vacuum @@ -1364,7 +1323,8 @@ class ELMpb : public PhysicsModel { // Only update if simulation time has advanced // Uses an exponential decay of the weighting of the value in the boundary // so that the solution is well behaved for arbitrary steps - BoutReal const weight = exp(-(t - phi_boundary_last_update) / phi_boundary_timescale); + const BoutReal weight = + exp(-(t - phi_boundary_last_update) / phi_boundary_timescale); phi_boundary_last_update = t; if (mesh->firstX()) { @@ -1373,7 +1333,7 @@ class ELMpb : public PhysicsModel { // Calculate a single phi boundary value for all Y slices BoutReal philocal = 0.0; for (int j = mesh->ystart; j <= mesh->yend; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { philocal += phi(mesh->xstart, j, k); } } @@ -1386,21 +1346,21 @@ class ELMpb : public PhysicsModel { for (int j = mesh->ystart; j <= mesh->yend; j++) { if (!phi_core_averagey) { phivalue = 0.0; // Calculate phi boundary for each Y index separately - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { phivalue += phi(mesh->xstart, j, k); } phivalue /= mesh->LocalNz; // Average in Z of point next to boundary } // Old value of phi at boundary. Note: this is constant in Z - BoutReal const oldvalue = + const BoutReal oldvalue = 0.5 * (phi(mesh->xstart - 1, j, 0) + phi(mesh->xstart, j, 0)); // New value of phi at boundary, relaxing towards phivalue - BoutReal const newvalue = weight * oldvalue + (1. - weight) * phivalue; + const BoutReal newvalue = weight * oldvalue + (1. - weight) * phivalue; // Set phi at the boundary to this value - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { phi(mesh->xstart - 1, j, k) = 2. * newvalue - phi(mesh->xstart, j, k); phi(mesh->xstart - 2, j, k) = phi(mesh->xstart - 1, j, k); } @@ -1410,7 +1370,7 @@ class ELMpb : public PhysicsModel { if (mesh->lastX()) { for (int j = mesh->ystart; j <= mesh->yend; j++) { BoutReal phivalue = 0.0; - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { phivalue += phi(mesh->xend, j, k); } phivalue /= mesh->LocalNz; // Average in Z of point next to boundary @@ -1420,10 +1380,10 @@ class ELMpb : public PhysicsModel { 0.5 * (phi(mesh->xend + 1, j, 0) + phi(mesh->xend, j, 0)); // New value of phi at boundary, relaxing towards phivalue - BoutReal const newvalue = weight * oldvalue + (1. - weight) * phivalue; + const BoutReal newvalue = weight * oldvalue + (1. - weight) * phivalue; // Set phi at the boundary to this value - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { phi(mesh->xend + 1, j, k) = 2. * newvalue - phi(mesh->xend, j, k); phi(mesh->xend + 2, j, k) = phi(mesh->xend + 1, j, k); } @@ -1448,7 +1408,7 @@ class ELMpb : public PhysicsModel { if (mesh->firstX()) { for (int j = mesh->ystart; j <= mesh->yend; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { // Average phi + Pi at the boundary, and set the boundary cell // to this value. The phi solver will then put the value back // onto the cell mid-point @@ -1460,7 +1420,7 @@ class ELMpb : public PhysicsModel { if (mesh->lastX()) { for (int j = mesh->ystart; j <= mesh->yend; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { + for (int k = mesh->zstart; k <= mesh->zend; k++) { phi_shift(mesh->xend + 1, j, k) = 0.5 * (phi_shift(mesh->xend + 1, j, k) + phi_shift(mesh->xend, j, k)); } @@ -1520,7 +1480,7 @@ class ELMpb : public PhysicsModel { if (mesh->firstX()) { for (int i = mesh->xstart - 2; i >= 0; --i) { for (int j = mesh->ystart; j <= mesh->yend; ++j) { - for (int k = 0; k < mesh->LocalNz; ++k) { + for (int k = mesh->zstart; k <= mesh->zend; ++k) { phi(i, j, k) = phi(i + 1, j, k); } } @@ -1530,7 +1490,7 @@ class ELMpb : public PhysicsModel { if (mesh->lastX()) { for (int i = mesh->xend + 2; i < mesh->LocalNx; ++i) { for (int j = mesh->ystart; j <= mesh->yend; ++j) { - for (int k = 0; k < mesh->LocalNz; ++k) { + for (int k = mesh->zstart; k <= mesh->zend; ++k) { phi(i, j, k) = phi(i - 1, j, k); } } @@ -1633,7 +1593,7 @@ class ELMpb : public PhysicsModel { for (int jz = 0; jz < mesh->LocalNz; jz++) { // Zero-gradient potential - BoutReal const phisheath = phi_fa(r.ind, mesh->ystart, jz); + const BoutReal phisheath = phi_fa(r.ind, mesh->ystart, jz); BoutReal jsheath = -(sqrt(mi_me) / (2. * sqrt(PI))) * phisheath; @@ -1654,7 +1614,7 @@ class ELMpb : public PhysicsModel { for (int jz = 0; jz < mesh->LocalNz; jz++) { // Zero-gradient potential - BoutReal const phisheath = phi_fa(r.ind, mesh->yend, jz); + const BoutReal phisheath = phi_fa(r.ind, mesh->yend, jz); BoutReal jsheath = (sqrt(mi_me) / (2. * sqrt(PI))) * phisheath; @@ -1744,10 +1704,10 @@ class ELMpb : public PhysicsModel { // Vacuum solution if (relax_j_vac) { // Calculate the J and Psi profile we're aiming for - Field3D Jtarget = Jpar * (1.0 - vac_mask); // Zero in vacuum + const Field3D Jtarget = Jpar * (1.0 - vac_mask); // Zero in vacuum // Invert laplacian for Psi - Field3D Psitarget = aparSolver->solve(Jtarget); + const Field3D Psitarget = aparSolver->solve(Jtarget); // Add a relaxation term in the vacuum ddt(Psi) = @@ -1812,11 +1772,11 @@ class ELMpb : public PhysicsModel { if (hyperviscos > 0.0) { // Calculate coefficient. - hyper_mu_x = hyperviscos * metric->g_11 * SQ(metric->dx) - * abs(metric->g11 * D2DX2(U)) / (abs(U) + 1e-3); + hyper_mu_x = hyperviscos * metric->g_11() * SQ(metric->dx()) + * abs(metric->g11() * D2DX2(U)) / (abs(U) + 1e-3); hyper_mu_x.applyBoundary("dirichlet"); // Set to zero on all boundaries - ddt(U) += hyper_mu_x * metric->g11 * D2DX2(U); + ddt(U) += hyper_mu_x * metric->g11() * D2DX2(U); if (first_run) { // Print out maximum values of viscosity used on this processor output.write(" Hyper-viscosity values:\n"); @@ -1878,7 +1838,7 @@ class ELMpb : public PhysicsModel { ddt(U) -= 0.5 * Upara2 * bracket(Pi0, Dperp2Phi, bm_exb) / B0; Field3D B0phi = B0 * phi; mesh->communicate(B0phi); - Field3D B0phi0 = B0 * phi0; + Field2D B0phi0 = B0 * phi0; mesh->communicate(B0phi0); ddt(U) += 0.5 * Upara2 * bracket(B0phi, Dperp2Pi0, bm_exb) / B0; ddt(U) += 0.5 * Upara2 * bracket(B0phi0, Dperp2Pi, bm_exb) / B0; @@ -1954,7 +1914,7 @@ class ELMpb : public PhysicsModel { BoutReal pnorm = P0(0, 0); ddt(P) += heating_P * source_expx2(P0, 2. * hp_width, 0.5 * hp_length) * (Tbar / pnorm); // heat source - ddt(P) += (100. * source_tanhx(P0, hp_width, hp_length) + 0.01) * metric->g11 + ddt(P) += (100. * source_tanhx(P0, hp_width, hp_length) + 0.01) * metric->g11() * D2DX2(P) * (Tbar / Lbar / Lbar); // radial diffusion } @@ -2076,7 +2036,8 @@ class ELMpb : public PhysicsModel { ddt(P).applyBoundary("neumann"); Field3D U1 = ddt(U); - U1 += (gamma * B0 * B0) * Grad_par(Jrhs, CELL_CENTRE) + (gamma * b0xcv) * Grad(ddt(P)); + U1 += + (gamma * B0 * B0) * Grad_par(Jrhs, CELL_CENTRE) + (gamma * b0xcv) * Grad(ddt(P)); // Second matrix, solving Alfven wave dynamics static std::unique_ptr invU{nullptr}; diff --git a/examples/elm-pb/relaxing/BOUT.inp b/examples/elm-pb/relaxing/BOUT.inp index d9489611e6..cd911417b2 100644 --- a/examples/elm-pb/relaxing/BOUT.inp +++ b/examples/elm-pb/relaxing/BOUT.inp @@ -75,7 +75,7 @@ fft_measurement_flag = measure # If using FFTW, perform tests to determine fast atol = 1.0e-8 # absolute tolerance rtol = 1.0e-5 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning mxstep = 50000 # Number of internal steps between outputs @@ -296,4 +296,3 @@ bndry_core = neumann bndry_xin = none bndry_xout = none #bndry_target = neumann - diff --git a/examples/elm-pb/runexample.py b/examples/elm-pb/runexample.py index f7ebc01028..b49902d29c 100755 --- a/examples/elm-pb/runexample.py +++ b/examples/elm-pb/runexample.py @@ -28,18 +28,22 @@ # Calculate RMS in toroidal direction prms = np.sqrt(np.mean(p**2, axis=3)) -growth = np.gradient(np.log(prms[:,42,32])) +growth = np.gradient(np.log(prms[:, 42, 32])) # Final growth-rate gamma = growth[-2] import matplotlib.pyplot as plt -plt.plot(tarr, prms[:,42,32], label='Outboard midplane') -plt.plot( [tarr[0], tarr[-1]], - [prms[-1,42,32]*np.exp(gamma*(tarr[0] - tarr[-1])), prms[-1,42,32]], '--', label=r'$\gamma =$'+str(gamma)) +plt.plot(tarr, prms[:, 42, 32], label="Outboard midplane") +plt.plot( + [tarr[0], tarr[-1]], + [prms[-1, 42, 32] * np.exp(gamma * (tarr[0] - tarr[-1])), prms[-1, 42, 32]], + "--", + label=r"$\gamma =$" + str(gamma), +) -plt.yscale('log') +plt.yscale("log") plt.grid() plt.xlabel(r"Time [$1/\tau_A$]") @@ -57,19 +61,21 @@ # Take a poloidal slice at fixed toroidal angle from boutdata.pol_slice import pol_slice -p2d = pol_slice(p[-1,:,:,:], 'cbm18_dens8.grid_nx68ny64.nc', n=15, zangle=0.0) + +p2d = pol_slice(p[-1, :, :, :], "cbm18_dens8.grid_nx68ny64.nc", n=15, zangle=0.0) # Read grid file to get coordinates from boututils.datafile import DataFile -g = DataFile('cbm18_dens8.grid_nx68ny64.nc') -Rxy = g.read("Rxy") # Major radius [m] -Zxy = g.read("Zxy") # Height [m] +g = DataFile("cbm18_dens8.grid_nx68ny64.nc") + +Rxy = g.read("Rxy") # Major radius [m] +Zxy = g.read("Zxy") # Height [m] plt.contourf(Rxy, Zxy, p2d, 30) -plt.axis('equal') # Maintain aspect ratio +plt.axis("equal") # Maintain aspect ratio -plt.colorbar() # Plot a bar down the side with a color scale +plt.colorbar() # Plot a bar down the side with a color scale plt.savefig("poloidal_slice.pdf") diff --git a/examples/elm-pb/test/BOUT.inp b/examples/elm-pb/test/BOUT.inp index 63f3d96f2b..76ccf14888 100644 --- a/examples/elm-pb/test/BOUT.inp +++ b/examples/elm-pb/test/BOUT.inp @@ -79,7 +79,7 @@ upwind = W3 atol = 1e-08 # absolute tolerance rtol = 1e-05 # relative tolerance -use_precon = false # Use preconditioner: User-supplied or BBD +cvode_precon_method = none # Disable CVODE preconditioning use_jacobian = false # Use user-supplied Jacobian mxstep = 5000 # Number of internal steps between outputs diff --git a/examples/fci-wave/CMakeLists.txt b/examples/fci-wave/CMakeLists.txt index 2680b1310e..ea299edb5a 100644 --- a/examples/fci-wave/CMakeLists.txt +++ b/examples/fci-wave/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(fci-wave LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(fci-wave +bout_add_example( + fci-wave SOURCES fci-wave.cxx DATA_DIRS div div-integrate logn - EXTRA_FILES compare-density.py) + EXTRA_FILES compare-density.py +) diff --git a/examples/fci-wave/compare-density.py b/examples/fci-wave/compare-density.py index c039c250b6..16e620a08f 100644 --- a/examples/fci-wave/compare-density.py +++ b/examples/fci-wave/compare-density.py @@ -1,4 +1,3 @@ - import matplotlib.pyplot as plt from boutdata import collect import numpy as np @@ -9,60 +8,61 @@ # Note: Data from fci-wave-logn examples commented out. data_noboundary = [ - ("div", "Model 1 (density, point interpolation)") - ,("div-integrate", "Model 2 (density, area integration)") - ,("logn", "Model 3 (log density, area integration)") - #,("../fci-wave-logn/div-integrate", "Model 5 (velocity, log density, area integration)") + ("div", "Model 1 (density, point interpolation)"), + ("div-integrate", "Model 2 (density, area integration)"), + ("logn", "Model 3 (log density, area integration)"), + # ,("../fci-wave-logn/div-integrate", "Model 5 (velocity, log density, area integration)") ] data_boundary = [ - ("boundary", "Model 2 (density, momentum)") - ,("boundary-logn", "Model 3 (log density, momentum)") - #,("../fci-wave-logn/boundary", "Model 5 (log density, velocity)") - ] + ("boundary", "Model 2 (density, momentum)"), + ("boundary-logn", "Model 3 (log density, momentum)"), + # ,("../fci-wave-logn/boundary", "Model 5 (log density, velocity)") +] # Change this to select no boundary or boundary cases data = data_noboundary if run: from boututils.run_wrapper import shell_safe, launch_safe + shell_safe("make > make.log") - for path,label in data: - launch_safe("./fci-wave -d "+path, nproc=nproc, pipe=False) + for path, label in data: + launch_safe("./fci-wave -d " + path, nproc=nproc, pipe=False) -# Collect the results into a dictionary +# Collect the results into a dictionary sum_n_B = {} -for path,label in data: +for path, label in data: n = collect("n", path=path) Bxyz = collect("Bxyz", path=path) time = collect("t_array", path=path) - + nt, nx, ny, nz = n.shape - + n_B = np.ndarray(nt) for t in range(nt): - n_B[t] = np.sum(n[t,:,:,:] / Bxyz) + n_B[t] = np.sum(n[t, :, :, :] / Bxyz) sum_n_B[path] = (time, n_B) # Plot the density at the final time - + plt.figure() - plt.contourf(n[-1,:,0,:].T, 100) + plt.contourf(n[-1, :, 0, :].T, 100) plt.colorbar() plt.xlabel("Major radius") plt.ylabel("Height") - plt.title("Density n, "+label) - plt.savefig(path+".pdf") + plt.title("Density n, " + label) + plt.savefig(path + ".pdf") plt.show() # Make a plot comparing total sum density / B - + plt.figure() -for path,label in data: +for path, label in data: time, n_B = sum_n_B[path] plt.plot(time, n_B, label=label) plt.legend() @@ -71,4 +71,3 @@ plt.savefig("compare-density.pdf") plt.show() - diff --git a/examples/fci-wave/fci-wave.cxx b/examples/fci-wave/fci-wave.cxx index 9f8bb18b8f..0ded45ebfd 100644 --- a/examples/fci-wave/fci-wave.cxx +++ b/examples/fci-wave/fci-wave.cxx @@ -1,6 +1,15 @@ - -#include "bout/parallel_boundary_region.hxx" -#include "bout/physicsmodel.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include class FCIwave : public PhysicsModel { private: @@ -19,35 +28,26 @@ class FCIwave : public PhysicsModel { Field3D f_B = f / Bxyz; f_B.splitParallelSlices(); - mesh->getCoordinates()->getParallelTransform().integrateParallelSlices(f_B); + const Coordinates* coord = mesh->getCoordinates(); + coord->getParallelTransform().integrateParallelSlices(f_B); // integrateParallelSlices replaces all yup/down points, so the boundary conditions // now need to be applied. If Bxyz has neumann parallel boundary conditions // then the boundary condition is simpler since f = 0 gives f_B=0 boundary condition. - /// Loop over the mesh boundary regions - for (const auto& reg : mesh->getBoundariesPar()) { - Field3D& f_B_next = f_B.ynext(reg->dir); - const Field3D& f_next = f.ynext(reg->dir); - const Field3D& B_next = Bxyz.ynext(reg->dir); - - for (reg->first(); !reg->isDone(); reg->next()) { - f_B_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) = - f_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) - / B_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()); - } - } + const auto ybndry = coord->getYBoundary(); + ybndry.iter([&](const bout::boundary::BoundaryIterator auto& point) { + point.next(f_B) = point.next(f) / point.next(Bxyz); + }); Field3D result; result.allocate(); - Coordinates* coord = mesh->getCoordinates(); - for (auto i : result.getRegion(RGN_NOBNDRY)) { result[i] = Bxyz[i] * (f_B.yup()[i.yp()] - f_B.ydown()[i.ym()]) - / (2. * coord->dy[i] * sqrt(coord->g_22[i])); + / (2. * coord->dy()[i] * sqrt(coord->g_22()[i])); - if (!finite(result[i])) { + if (!std::isfinite(result[i])) { output.write("[{:d},{:d},{:d}]: {:e}, {:e} -> {:e}\n", i.x(), i.y(), i.z(), f_B.yup()[i.yp()], f_B.ydown()[i.ym()], result[i]); } @@ -65,7 +65,7 @@ class FCIwave : public PhysicsModel { auto& options = Options::root()["fciwave"]; div_integrate = options["div_integrate"].withDefault(true); log_density = options["log_density"].withDefault(false); - background = options["background"].withDefault(false); + background = options["background"].withDefault(0.0); log_background = log(background); // Neumann boundaries simplifies parallel derivatives @@ -117,38 +117,16 @@ class FCIwave : public PhysicsModel { // between v, nv and momentum flux momflux.splitParallelSlices(); - for (const auto& reg : mesh->getBoundariesPar()) { + const auto ybndry = mesh->getCoordinates()->getYBoundary(); + ybndry.iter([&](const bout::boundary::BoundaryIterator auto& point) { // Using the values of density and velocity on the boundary - const Field3D& n_next = n.ynext(reg->dir); - const Field3D& v_next = v.ynext(reg->dir); + const BoutReal n_b = 0.5 * point.next(n) + point.current(n); + const BoutReal v_b = 0.5 * point.next(v) + point.current(v); // Set the momentum and momentum flux - Field3D& nv_next = nv.ynext(reg->dir); - Field3D& momflux_next = momflux.ynext(reg->dir); - momflux_next.allocate(); - - for (reg->first(); !reg->isDone(); reg->next()) { - // Density at the boundary - // Note: If evolving density, this should interpolate logn - // but neumann boundaries are used here anyway. - BoutReal n_b = - 0.5 - * (n_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) - + n(reg->ind().x(), reg->ind().y(), reg->ind().z())); - // Velocity at the boundary - BoutReal v_b = - 0.5 - * (v_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) - + v(reg->ind().x(), reg->ind().y(), reg->ind().z())); - - nv_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) = - 2. * n_b * v_b - nv(reg->ind().x(), reg->ind().y(), reg->ind().z()); - - momflux_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) = - 2. * n_b * v_b * v_b - - momflux(reg->ind().x(), reg->ind().y(), reg->ind().z()); - } - } + point.next(nv) = 2. * n_b * v_b - point.current(nv); + point.next(momflux) = 2. * n_b * v_b * v_b - point.current(momflux); + }); // Momentum ddt(nv) = -Div_par_integrate(momflux) - Grad_par(n) + Grad2_par2(nv); diff --git a/examples/finite-volume/diffusion/CMakeLists.txt b/examples/finite-volume/diffusion/CMakeLists.txt index 0dd7d220f6..ccc3d0f7e0 100644 --- a/examples/finite-volume/diffusion/CMakeLists.txt +++ b/examples/finite-volume/diffusion/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(finite-volume-diffusion LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(finite-volume-diffusion +bout_add_example( + finite-volume-diffusion SOURCES diffusion.cxx - EXTRA_FILES mms.py) + EXTRA_FILES mms.py +) diff --git a/examples/finite-volume/diffusion/mms.py b/examples/finite-volume/diffusion/mms.py index 2c609ca82e..31b7714727 100644 --- a/examples/finite-volume/diffusion/mms.py +++ b/examples/finite-volume/diffusion/mms.py @@ -5,26 +5,26 @@ from math import pi # Length of the y domain -Ly = 10. +Ly = 10.0 # metric tensor metric = Metric() # Identity # Define solution in terms of input x,y,z -f = 1 + 0.1*sin(2*y - t) -k = 1 + 0.1*sin(y) +f = 1 + 0.1 * sin(2 * y - t) +k = 1 + 0.1 * sin(y) # Turn solution into real x and z coordinates -replace = [ (y, metric.y*2*pi/Ly) ] +replace = [(y, metric.y * 2 * pi / Ly)] f = f.subs(replace) -k = k.subs(replace) +k = k.subs(replace) ############################## # Calculate time derivatives -dfdt = Div_par( k * Grad_par(f) ) +dfdt = Div_par(k * Grad_par(f)) ############################# # Calculate sources @@ -32,7 +32,7 @@ Sf = diff(f, t) - dfdt # Substitute back to get input y coordinates -replace = [ (metric.y, y*Ly/(2*pi) ) ] +replace = [(metric.y, y * Ly / (2 * pi))] k = k.subs(replace) f = f.subs(replace) diff --git a/examples/finite-volume/fluid/CMakeLists.txt b/examples/finite-volume/fluid/CMakeLists.txt index e9028459ec..e798da77fe 100644 --- a/examples/finite-volume/fluid/CMakeLists.txt +++ b/examples/finite-volume/fluid/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(finite-volume-fluid LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(finite-volume-fluid +bout_add_example( + finite-volume-fluid SOURCES fluid.cxx DATA_DIRS data mms - EXTRA_FILES mms.py) + EXTRA_FILES mms.py +) diff --git a/examples/finite-volume/fluid/README.md b/examples/finite-volume/fluid/README.md index d112da3039..583277d130 100644 --- a/examples/finite-volume/fluid/README.md +++ b/examples/finite-volume/fluid/README.md @@ -51,5 +51,10 @@ for the first order upwinding method, or for the second order MinMod method. +Or, to use a smooth symmetric limiter: + FV::Div_par +Or a higher-order smooth WENO reconstruction: + + FV::Div_par diff --git a/examples/finite-volume/fluid/mms.py b/examples/finite-volume/fluid/mms.py index 8ed8fba517..a31782e2c7 100644 --- a/examples/finite-volume/fluid/mms.py +++ b/examples/finite-volume/fluid/mms.py @@ -5,19 +5,19 @@ from math import pi # Length of the y domain -Ly = 10. +Ly = 10.0 # metric tensor metric = Metric() # Identity # Define solution in terms of input x,y,z -n = 1 + 0.1*sin(2*y - t) -p = 1 + 0.1*cos(3*y + t) -nv = 0.1*sin(y + 2*t) +n = 1 + 0.1 * sin(2 * y - t) +p = 1 + 0.1 * cos(3 * y + t) +nv = 0.1 * sin(y + 2 * t) # Turn solution into real x and z coordinates -replace = [ (y, metric.y*2*pi/Ly) ] +replace = [(y, metric.y * 2 * pi / Ly)] n = n.subs(replace) p = p.subs(replace) @@ -27,16 +27,16 @@ # Calculate time derivatives v = nv / n -gamma = 5./3 +gamma = 5.0 / 3 # Density equation -dndt = - Div_par(nv) +dndt = -Div_par(nv) # Pressure equation -dpdt = - Div_par(p*v) - (gamma-1.0)*p*Div_par(v) +dpdt = -Div_par(p * v) - (gamma - 1.0) * p * Div_par(v) # Momentum equation -dnvdt = - Div_par(nv*v) - Grad_par(p) +dnvdt = -Div_par(nv * v) - Grad_par(p) ############################# # Calculate sources @@ -46,7 +46,7 @@ Snv = diff(nv, t) - dnvdt # Substitute back to get input y coordinates -replace = [ (metric.y, y*Ly/(2*pi) ) ] +replace = [(metric.y, y * Ly / (2 * pi))] n = n.subs(replace) p = p.subs(replace) diff --git a/examples/finite-volume/test/CMakeLists.txt b/examples/finite-volume/test/CMakeLists.txt index 73fe99f960..d09567e193 100644 --- a/examples/finite-volume/test/CMakeLists.txt +++ b/examples/finite-volume/test/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(finite-volume-test LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/gas-compress/CMakeLists.txt b/examples/gas-compress/CMakeLists.txt index 1b4416d32b..75978ba584 100644 --- a/examples/gas-compress/CMakeLists.txt +++ b/examples/gas-compress/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(gas-compress LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(gas-compress +bout_add_example( + gas-compress SOURCES gas_compress.cxx gas_compress.hxx DATA_DIRS rayleigh-taylor sod-shock - EXTRA_FILES rt.grd.nc sod.grd.nc) + EXTRA_FILES rt.grd.nc sod.grd.nc +) diff --git a/examples/gyro-gem/CMakeLists.txt b/examples/gyro-gem/CMakeLists.txt index 7189bb06b8..5d83848688 100644 --- a/examples/gyro-gem/CMakeLists.txt +++ b/examples/gyro-gem/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(gyro-gem LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(gyro-gem +bout_add_example( + gyro-gem SOURCES gem.cxx - EXTRA_FILES cyclone_68x32.nc) + EXTRA_FILES cyclone_68x32.nc +) diff --git a/examples/gyro-gem/gem.cxx b/examples/gyro-gem/gem.cxx index 1a056c1c08..4e5e8538c3 100644 --- a/examples/gyro-gem/gem.cxx +++ b/examples/gyro-gem/gem.cxx @@ -4,17 +4,17 @@ * 6 moments for each species * * "GEM - An Energy Conserving Electromagnetic Gyrofluid Model" - * by Bruce D Scott. arXiv:physics/0501124v1 23 Jan 2005 + * by Bruce D Scott. arXiv:physics/0501124v1 23 Jan 2005 * * This version uses global parameters for collisionality etc. ****************************************************************/ +#include "bout/tokamak_coordinates.hxx" #include -#include - #include #include #include +#include /// Fundamental constants @@ -185,14 +185,6 @@ class GEM : public PhysicsModel { ////////////////////////////////// // Read profiles - // Mesh - Field2D Rxy, Bpxy, Btxy, Bxy, hthe; - GRID_LOAD(Rxy); // Major radius [m] - GRID_LOAD(Bpxy); // Poloidal B field [T] - GRID_LOAD(Btxy); // Toroidal B field [T] - GRID_LOAD(Bxy); // Total B field [T] - GRID_LOAD(hthe); // Poloidal arc length [m / radian] - GRID_LOAD(Te0); // Electron temperature in eV GRID_LOAD(Ni0); // Ion number density in 10^20 m^-3 @@ -255,6 +247,8 @@ class GEM : public PhysicsModel { if (mesh->get(Bbar, "Bbar")) { if (mesh->get(Bbar, "bmag")) { + Field3D Bxy; + mesh->get(Bxy, "Bxy"); Bbar = max(Bxy, true); } } @@ -355,44 +349,13 @@ class GEM : public PhysicsModel { ////////////////////////////////// // Metric tensor components - coord = mesh->getCoordinates(); - - // Normalise - hthe /= Lbar; // parallel derivatives normalised to Lperp - - Bpxy /= Bbar; - Btxy /= Bbar; - Bxy /= Bbar; - - Rxy /= rho_s; // Perpendicular derivatives normalised to rho_s - coord->dx /= rho_s * rho_s * Bbar; - - // Metric components - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = 0.; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - coord->Bxy = Bxy; - - coord->g_11 = 1.0 / coord->g11; - coord->g_22 = SQ(Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = 0.; - coord->g_13 = 0.; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); + const auto tokamak_coords = bout::set_tokamak_coordinates(*mesh, rho_s, Bbar); // Set B field vector B0vec.covariant = false; B0vec.x = 0.; - B0vec.y = Bpxy / hthe; + B0vec.y = tokamak_coords.Bpxy / tokamak_coords.hthe; B0vec.z = 0.; // Precompute this for use in RHS @@ -400,7 +363,7 @@ class GEM : public PhysicsModel { if (curv_logB) { Grad_par_logB = Grad_par(logB); } else { - Grad_par_logB = Grad_par(log(coord->Bxy)); + Grad_par_logB = Grad_par(log(coord->Bxy())); } } else { Grad_par_logB = 0.; @@ -1153,7 +1116,7 @@ class GEM : public PhysicsModel { if (curv_logB) { return -bracket(2. * logB, f, BRACKET_ARAKAWA); } - return -bracket(2. * log(coord->Bxy), f, BRACKET_ARAKAWA); + return -bracket(2. * log(coord->Bxy()), f, BRACKET_ARAKAWA); } //////////////////////////////////////////////////////////////////////// @@ -1168,7 +1131,7 @@ class GEM : public PhysicsModel { delp2.applyBoundary("neumann"); mesh->communicate(delp2); - return nu_perp * Delp2(delp2 * SQ(SQ(1. / coord->Bxy))) + return nu_perp * Delp2(delp2 * SQ(SQ(1. / coord->Bxy()))) - nu_par * Grad2_par2(f) // NB: This should be changed for variable B ; } @@ -1184,8 +1147,8 @@ class GEM : public PhysicsModel { } const Field3D Div_parP(const Field3D& f, CELL_LOC loc = CELL_DEFAULT) { - return interp_to(coord->Bxy, loc) - * Grad_parP(f / interp_to(coord->Bxy, f.getLocation()), loc); + return interp_to(coord->Bxy(), loc) + * Grad_parP(f / interp_to(coord->Bxy(), f.getLocation()), loc); } }; diff --git a/examples/hasegawa-wakatani-3d/CMakeLists.txt b/examples/hasegawa-wakatani-3d/CMakeLists.txt index 0cdb5207f8..c555d6d7f9 100644 --- a/examples/hasegawa-wakatani-3d/CMakeLists.txt +++ b/examples/hasegawa-wakatani-3d/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(hw3d LANGUAGES CXX C) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/hasegawa-wakatani/CMakeLists.txt b/examples/hasegawa-wakatani/CMakeLists.txt index c9b9401b3a..53f4e5ed4f 100644 --- a/examples/hasegawa-wakatani/CMakeLists.txt +++ b/examples/hasegawa-wakatani/CMakeLists.txt @@ -2,9 +2,8 @@ cmake_minimum_required(VERSION 3.13) project(hasegawa-wakatani LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() bout_add_example(hasegawa-wakatani SOURCES hw.cxx) - diff --git a/examples/invertable_operator/CMakeLists.txt b/examples/invertable_operator/CMakeLists.txt index f054466f23..f18a085ec1 100644 --- a/examples/invertable_operator/CMakeLists.txt +++ b/examples/invertable_operator/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(invertable_operator LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(invertable_operator +bout_add_example( + invertable_operator SOURCES invertable_operator.cxx - REQUIRES BOUT_HAS_PETSC) + REQUIRES BOUT_HAS_PETSC +) diff --git a/examples/invertable_operator/invertable_operator.cxx b/examples/invertable_operator/invertable_operator.cxx index 57f9e24b08..99db7f7a1e 100644 --- a/examples/invertable_operator/invertable_operator.cxx +++ b/examples/invertable_operator/invertable_operator.cxx @@ -1,5 +1,4 @@ #include -#include #include #include @@ -26,7 +25,7 @@ class HW : public PhysicsModel { // Drop C term for now Field3D operator()(const Field3D& input) { - TRACE("myLaplacian::operator()"); + Timer timer("invertable_operator_operate"); Field3D result = A * input + D * Delp2(input); @@ -43,7 +42,7 @@ class HW : public PhysicsModel { // Drop C term for now Field3D operator()(const Field3D& input) { - TRACE("myLaplacian::operator()"); + Timer timer("invertable_operator_operate"); Field3D result = A * input + B * Laplace_perp(input); if (withDiv) { diff --git a/examples/laplace-petsc3d/plotcheck.py b/examples/laplace-petsc3d/plotcheck.py index 707e5db1ee..7f2758dd81 100755 --- a/examples/laplace-petsc3d/plotcheck.py +++ b/examples/laplace-petsc3d/plotcheck.py @@ -10,27 +10,27 @@ xg = 2 -f = collect('f', path=datadir)[xg:-xg, :, :] -rhs = collect('rhs', path=datadir)[xg:-xg, :, :] -rhs_check = collect('rhs_check', path=datadir)[xg:-xg, :, :] -error = collect('error', path=datadir)[xg:-xg, :, :] +f = collect("f", path=datadir)[xg:-xg, :, :] +rhs = collect("rhs", path=datadir)[xg:-xg, :, :] +rhs_check = collect("rhs_check", path=datadir)[xg:-xg, :, :] +error = collect("error", path=datadir)[xg:-xg, :, :] pyplot.subplot(221) pyplot.pcolormesh(f[:, yind, :]) pyplot.colorbar() -pyplot.title('f') +pyplot.title("f") pyplot.subplot(222) pyplot.pcolormesh(rhs[:, yind, :]) pyplot.colorbar() -pyplot.title('rhs') +pyplot.title("rhs") pyplot.subplot(223) pyplot.pcolormesh(rhs_check[:, yind, :]) pyplot.colorbar() -pyplot.title('rhs_check') +pyplot.title("rhs_check") pyplot.subplot(224) pyplot.pcolormesh(error[:, yind, :]) pyplot.colorbar() -pyplot.title('error') +pyplot.title("error") pyplot.show() diff --git a/examples/laplace-petsc3d/test-laplace3d.cxx b/examples/laplace-petsc3d/test-laplace3d.cxx index 46bfce7859..5e40b42495 100644 --- a/examples/laplace-petsc3d/test-laplace3d.cxx +++ b/examples/laplace-petsc3d/test-laplace3d.cxx @@ -36,13 +36,13 @@ Field3D this_Laplace_perp(const Field3D& f) { // dfdy not divided by dy yet auto dfdy = bout::derivatives::index::DDY(f, CELL_DEFAULT, "DEFAULT", "RGN_NOY"); - return coords->G1 * DDX(f) - + (coords->G2 - DDY(coords->J / coords->g_22) / coords->J) * DDY(f) - + coords->G3 * DDZ(f) + coords->g11 * D2DX2(f) - + (coords->g22 - 1. / coords->g_22) * D2DY2(f) + coords->g33 * D2DZ2(f) + return coords->G1() * DDX(f) + + (coords->G2() - DDY(coords->J() / coords->g_22()) / coords->J()) * DDY(f) + + coords->G3() * DDZ(f) + coords->g11() * D2DX2(f) + + (coords->g22() - 1. / coords->g_22()) * D2DY2(f) + coords->g33() * D2DZ2(f) + 2. - * (coords->g12 * DDX(dfdy) / coords->dy + coords->g13 * D2DXDZ(f) - + coords->g23 * D2DYDZ(f)); + * (coords->g12() * DDX(dfdy) / coords->dy() + coords->g13() * D2DXDZ(f) + + coords->g23() * D2DYDZ(f)); } int main(int argc, char** argv) { @@ -136,7 +136,7 @@ int main(int argc, char** argv) { /////////////////////////////////////////////////////////////////////////////////////// // Calculate error /////////////////////////////////////////////////////////////////////////////////////// - auto& g_22 = mesh->getCoordinates()->g_22; + const auto& g_22 = mesh->getCoordinates()->g_22(); Field3D rhs_check = D * this_Laplace_perp(f) + (Grad(f) * Grad(C2) - DDY(C2) * DDY(f) / g_22) / C1 + A * f; // The usual way to do this would be diff --git a/examples/laplacexy/alfven-wave/CMakeLists.txt b/examples/laplacexy/alfven-wave/CMakeLists.txt index 2423400519..ebda7703e6 100644 --- a/examples/laplacexy/alfven-wave/CMakeLists.txt +++ b/examples/laplacexy/alfven-wave/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(laplacexy-alfven-wave LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(laplacexy-alfven-wave +bout_add_example( + laplacexy-alfven-wave SOURCES alfven.cxx DATA_DIRS cbm18 data - EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc d3d_119919.nc) + EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc d3d_119919.nc +) diff --git a/examples/laplacexy/alfven-wave/alfven.cxx b/examples/laplacexy/alfven-wave/alfven.cxx index a4248afcf7..cf66af7295 100644 --- a/examples/laplacexy/alfven-wave/alfven.cxx +++ b/examples/laplacexy/alfven-wave/alfven.cxx @@ -1,9 +1,11 @@ - #include #include #include #include #include +#include + +#include /// Fundamental constants const BoutReal PI = 3.14159265; @@ -30,9 +32,9 @@ class Alfven : public PhysicsModel { BoutReal mu_epar; // Electron parallel viscosity BoutReal resistivity; - bool laplace_perp; // Use Laplace_perp or Delp2? - bool split_n0; // Split solve into n=0 and n~=0? - LaplaceXY* laplacexy; // Laplacian solver in X-Y (n=0) + bool laplace_perp; // Use Laplace_perp or Delp2? + bool split_n0; // Split solve into n=0 and n~=0? + std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) bool newXZsolver; std::unique_ptr phiSolver; // Old Laplacian in X-Z @@ -69,7 +71,7 @@ class Alfven : public PhysicsModel { resistivity = opt["resistivity"].withDefault(1e-7); // Load metric tensor from the mesh, passing length and B field normalisations - LoadMetric(rho_s0, Bnorm); + bout::set_tokamak_coordinates(*mesh, rho_s0, Bnorm, true); // Specify evolving variables SOLVE_FOR2(Vort, Apar); @@ -80,7 +82,7 @@ class Alfven : public PhysicsModel { if (split_n0) { // Create an XY solver for n=0 component - laplacexy = new LaplaceXY(mesh); + laplacexy = LaplaceXY::create(mesh); phi2D = 0.0; // Starting guess } @@ -167,59 +169,6 @@ class Alfven : public PhysicsModel { return 0; } - - void LoadMetric(BoutReal Lnorm, BoutReal Bnorm) { - // Load metric coefficients from the mesh - Field2D Rxy, Bpxy, Btxy, hthe, sinty; - GRID_LOAD5(Rxy, Bpxy, Btxy, hthe, sinty); // Load metrics - - Coordinates* coord = mesh->getCoordinates(); // Metric tensor - - // Checking for dpsi and qinty used in BOUT grids - Field2D dx; - if (!mesh->get(dx, "dpsi")) { - output << "\tUsing dpsi as the x grid spacing\n"; - coord->dx = dx; // Only use dpsi if found - } else { - // dx will have been read already from the grid - output << "\tUsing dx as the x grid spacing\n"; - } - - Rxy /= Lnorm; - hthe /= Lnorm; - sinty *= SQ(Lnorm) * Bnorm; - coord->dx /= SQ(Lnorm) * Bnorm; - - Bpxy /= Bnorm; - Btxy /= Bnorm; - coord->Bxy /= Bnorm; - - // Calculate metric components - sinty = 0.0; // I disappears from metric for shifted coordinates - - BoutReal sbp = 1.0; // Sign of Bp - if (min(Bpxy, true) < 0.0) { - sbp = -1.0; - } - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(sinty) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -sinty * coord->g11; - coord->g23 = -sbp * Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(sinty * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = sbp * Btxy * hthe * sinty * Rxy / Bpxy; - coord->g_13 = sinty * Rxy * Rxy; - coord->g_23 = sbp * Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); - } }; BOUTMAIN(Alfven); diff --git a/examples/laplacexy/laplace_perp/CMakeLists.txt b/examples/laplacexy/laplace_perp/CMakeLists.txt index 388513b044..d12725c5de 100644 --- a/examples/laplacexy/laplace_perp/CMakeLists.txt +++ b/examples/laplacexy/laplace_perp/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(laplacexy-laplace_perp LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(laplacexy-laplace_perp +bout_add_example( + laplacexy-laplace_perp SOURCES test.cxx - EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc - DATA_DIRS square torus) + EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc + DATA_DIRS square torus +) diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index 75577bb8b7..b1686d1764 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -1,9 +1,9 @@ #include -#include - #include +#include #include #include +#include using bout::globals::mesh; @@ -13,41 +13,7 @@ int main(int argc, char** argv) { /////////////////////////////////////// const bool calc_metric = Options::root()["calc_metric"].withDefault(false); if (calc_metric) { - // Read metric tensor - Field2D Rxy; - Field2D Btxy; - Field2D Bpxy; - Field2D B0; - Field2D hthe; - Field2D I; - mesh->get(Rxy, "Rxy"); // m - mesh->get(Btxy, "Btxy"); // T - mesh->get(Bpxy, "Bpxy"); // T - mesh->get(B0, "Bxy"); // T - mesh->get(hthe, "hthe"); // m - mesh->get(I, "sinty"); // m^-2 T^-1 - - Coordinates* coord = mesh->getCoordinates(); - - // Calculate metrics - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(B0) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - coord->Bxy = B0; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(B0 * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); + bout::set_tokamak_coordinates(*mesh); } /////////////////////////////////////// @@ -56,10 +22,10 @@ int main(int argc, char** argv) { FieldFactory::get()->create2D("input_field", Options::getRoot(), mesh); // Create a LaplaceXY solver - LaplaceXY laplacexy{mesh}; + auto laplacexy = LaplaceXY::create(mesh); // Solve, using 0.0 as starting guess - Field2D solved = laplacexy.solve(input, 0.0); + Field2D solved = laplacexy->solve(input, 0.0); // Need to communicate guard cells mesh->communicate(solved); diff --git a/examples/laplacexy/simple-hypre/.gitignore b/examples/laplacexy/simple-hypre/.gitignore deleted file mode 100644 index eeede075f9..0000000000 --- a/examples/laplacexy/simple-hypre/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test-laplacexy diff --git a/examples/laplacexy/simple-hypre/CMakeLists.txt b/examples/laplacexy/simple-hypre/CMakeLists.txt deleted file mode 100644 index 788ebb1776..0000000000 --- a/examples/laplacexy/simple-hypre/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(test_laplacexy_hypre LANGUAGES CXX C) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(test_laplacexy_hypre - SOURCES test-laplacexy-hypre.cxx - REQUIRES BOUT_HAS_HYPRE) - -if(BOUT_HAS_CUDA) - set_source_files_properties(test-laplacexy-hypre.cxx PROPERTIES LANGUAGE CUDA ) -endif() diff --git a/examples/laplacexy/simple-hypre/data/BOUT.inp b/examples/laplacexy/simple-hypre/data/BOUT.inp deleted file mode 100644 index 5da492168d..0000000000 --- a/examples/laplacexy/simple-hypre/data/BOUT.inp +++ /dev/null @@ -1,37 +0,0 @@ -# -# Simple test of the LaplaceXY solver. -# -# Inverts a given function (rhs), writing "rhs" and solution "x" to file -# - -[mesh] - -# Mesh sizes -nx = 20 -ny = 32 -nz = 1 - -# mesh spacing -dx = 1.0 -dy = 1.0 -dz = 1.0 - -[laplacexy] - -ksptype = gmres # Iterative solver type - not used with Hypre interface -pctype = jacobi # Preconditioner. "jacobi", "bjacobi" and "sor" usually good -# On one processor"lu" uses direct solver - -atol = 1e-12 # type: BoutReal, doc: Relative tolerance for Hypre solver -core_bndry_dirichlet = false # type: bool -hypre_print_level = 3 # type: int, doc: Verbosity for Hypre solver. Integer from 0 (silent) to 4 (most verbose). -#hypre_solver_type = gmres # type: HYPRE_SOLVER_TYPE, doc: Type of solver to use when solving Hypre system. Possible values are: gmres, bicgstab -hypre_solver_type = bicgstab # type: HYPRE_SOLVER_TYPE, doc: Type of solver to use when solving Hypre system. Possible values are: gmres, bicgstab -include_y_derivs = true # type: bool, doc: Include Y derivatives in operator to invert? -maxits = 2000 # type: int, doc: Maximum iterations for Hypre solver -print_timing = true # type: bool, doc: Print extra timing information for LaplaceXY2Hypre -rtol = 1e-07 # type: BoutReal, doc: Relative tolerance for Hypre solver -y_bndry_dirichlet = false # type: bool - -# Function to be inverted -rhs = sin(2*pi*x)*sin(y) diff --git a/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx b/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx deleted file mode 100644 index af2367e1a0..0000000000 --- a/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -int main(int argc, char** argv) { - BoutInitialise(argc, argv); - { - /// Create a LaplaceXY object - LaplaceXY2Hypre laplacexy(bout::globals::mesh); - - /// Generate rhs function - Field2D rhs = FieldFactory::get()->create2D("laplacexy:rhs", Options::getRoot(), - bout::globals::mesh); - - /// Solution - Field2D solution = 0.0; - - solution = laplacexy.solve(rhs, solution); - - Options dump; - dump["rhs"] = rhs; - dump["x"] = solution; - bout::writeDefaultOutputFile(dump); - } - BoutFinalise(); -#if BOUT_HAS_CUDA - cudaDeviceReset(); -#endif - return 0; -} diff --git a/examples/laplacexy/simple/CMakeLists.txt b/examples/laplacexy/simple/CMakeLists.txt index ec5e7d2492..e999b9cf58 100644 --- a/examples/laplacexy/simple/CMakeLists.txt +++ b/examples/laplacexy/simple/CMakeLists.txt @@ -2,8 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(laplacexy-simple LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(laplacexy-simple SOURCES test-laplacexy.cxx) +bout_add_example( + laplacexy-simple + SOURCES test-laplacexy.cxx + DATA_DIRS data hypre +) diff --git a/examples/laplacexy/simple/README.md b/examples/laplacexy/simple/README.md index ce7cbebf00..491d00d4b3 100644 --- a/examples/laplacexy/simple/README.md +++ b/examples/laplacexy/simple/README.md @@ -8,7 +8,7 @@ and preconditioners. See the "ksptype" and "pctype" settings in BOUT.inp Run with - $ ./test-laplacexy -ksp_monitor + $ ./test-laplacexy -laplacexy:petsc:ksp_monitor which should print the KSP norms from PETSc: @@ -31,3 +31,8 @@ which should print the KSP norms from PETSc: 16 KSP Residual norm 4.309526296050e-01 17 KSP Residual norm 1.115269396077e-01 18 KSP Residual norm 4.334487475743e-13 + +HYPRE +----- + +Use the `hypre` directory to use the HYPRE preconditioner instead of PETSc. diff --git a/examples/laplacexy/simple/hypre/BOUT.inp b/examples/laplacexy/simple/hypre/BOUT.inp new file mode 100644 index 0000000000..338e902d4e --- /dev/null +++ b/examples/laplacexy/simple/hypre/BOUT.inp @@ -0,0 +1,23 @@ +# +# Simple test of the LaplaceXY solver using HYPRE +# +# Inverts a given function (rhs), writing "rhs" and solution "x" to file +# + +[mesh] + +# Mesh sizes +nx = 20 +ny = 32 +nz = 1 + +# mesh spacing +dx = 1.0 +dy = 1.0 +dz = 1.0 + +[laplacexy] +type = hypre + +# Function to be inverted +rhs = sin(2*pi*x)*sin(y) diff --git a/examples/laplacexy/simple/test-laplacexy.cxx b/examples/laplacexy/simple/test-laplacexy.cxx index c033eb68e3..49a93aafdb 100644 --- a/examples/laplacexy/simple/test-laplacexy.cxx +++ b/examples/laplacexy/simple/test-laplacexy.cxx @@ -7,20 +7,18 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); /// Create a LaplaceXY object - LaplaceXY laplacexy(bout::globals::mesh); + auto laplacexy = LaplaceXY::create(bout::globals::mesh); /// Generate rhs function Field2D rhs = FieldFactory::get()->create2D("laplacexy:rhs", Options::getRoot(), bout::globals::mesh); /// Solution - Field2D x = 0.0; - - x = laplacexy.solve(rhs, x); + Field2D result = laplacexy->solve(rhs, 0.0); Options dump; dump["rhs"] = rhs; - dump["x"] = x; + dump["result"] = result; bout::writeDefaultOutputFile(dump); BoutFinalise(); diff --git a/examples/monitor-newapi/CMakeLists.txt b/examples/monitor-newapi/CMakeLists.txt index 0ee3ee7f85..5c2022b792 100644 --- a/examples/monitor-newapi/CMakeLists.txt +++ b/examples/monitor-newapi/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(monitor-newapi LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/orszag-tang/CMakeLists.txt b/examples/orszag-tang/CMakeLists.txt index 9ac8fd8d1c..46eae5d0f2 100644 --- a/examples/orszag-tang/CMakeLists.txt +++ b/examples/orszag-tang/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(orszag-tang LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(orszag-tang +bout_add_example( + orszag-tang SOURCES mhd.cxx - EXTRA_FILES data/otv.grd.nc) + EXTRA_FILES data/otv.grd.nc +) diff --git a/examples/orszag-tang/generate.py b/examples/orszag-tang/generate.py index 3ba6dbbea9..acce7497c3 100644 --- a/examples/orszag-tang/generate.py +++ b/examples/orszag-tang/generate.py @@ -2,14 +2,16 @@ from __future__ import division from builtins import range from past.utils import old_div + # the Scientific Python netCDF 3 interface # http://dirac.cnrs-orleans.fr/ScientificPython/ -#from Scientific.IO.NetCDF import NetCDFFile as Dataset +# from Scientific.IO.NetCDF import NetCDFFile as Dataset # the 'classic' version of the netCDF4 python interface # http://code.google.com/p/netcdf4-python/ import numpy as np from netCDF4 import Dataset -from numpy import dtype # array module from http://numpy.scipy.org +from numpy import dtype # array module from http://numpy.scipy.org + """ This example writes some surface pressure and temperatures The companion program sfc_pres_temp_rd.py shows how to read the netCDF @@ -30,44 +32,45 @@ # # the output array to write will be nx x ny -ny = 100; nx = ny + 4 +ny = 100 +nx = ny + 4 # dy of grid dy = old_div(1.0, np.float(ny)) dx = dy # create grid -dxarr=np.zeros((nx,ny),dtype='float32')+dx -dyarr=np.zeros((nx,ny),dtype='float32')+dy +dxarr = np.zeros((nx, ny), dtype="float32") + dx +dyarr = np.zeros((nx, ny), dtype="float32") + dy -xarr=np.arange(0.,np.float(nx),1.,dtype='float32')*dx -yarr=np.arange(0.,np.float(ny),1.,dtype='float32')*dy +xarr = np.arange(0.0, np.float(nx), 1.0, dtype="float32") * dx +yarr = np.arange(0.0, np.float(ny), 1.0, dtype="float32") * dy # compute initial variables -rho=np.zeros((nx,ny),dtype='float32')+old_div(25.,(36.*np.pi)) -p=np.zeros((nx,ny),dtype='float32')+old_div(5.,(12.*np.pi)) +rho = np.zeros((nx, ny), dtype="float32") + old_div(25.0, (36.0 * np.pi)) +p = np.zeros((nx, ny), dtype="float32") + old_div(5.0, (12.0 * np.pi)) -rho=1. -p=old_div(rho,3.) +rho = 1.0 +p = old_div(rho, 3.0) -v_x=np.zeros((nx,ny),dtype='float32') -Bx=np.zeros((nx,ny),dtype='float32') +v_x = np.zeros((nx, ny), dtype="float32") +Bx = np.zeros((nx, ny), dtype="float32") for y in range(ny): - v_x[:,y]=-np.sin(2.*np.pi*yarr[y]) - Bx[:,y]=-np.sin(2.*np.pi*yarr[y]) - -#Bx=Bx/np.sqrt(4.*np.pi) + v_x[:, y] = -np.sin(2.0 * np.pi * yarr[y]) + Bx[:, y] = -np.sin(2.0 * np.pi * yarr[y]) +# Bx=Bx/np.sqrt(4.*np.pi) -v_y=np.zeros((nx,ny),dtype='float32') -By=np.zeros((nx,ny),dtype='float32') + +v_y = np.zeros((nx, ny), dtype="float32") +By = np.zeros((nx, ny), dtype="float32") for x in range(nx): - v_y[x,:]=np.sin(2.*np.pi*xarr[x]) - By[x,:]=np.sin(4.*np.pi*xarr[x]) - -#By=By/np.sqrt(4.*np.pi) + v_y[x, :] = np.sin(2.0 * np.pi * xarr[x]) + By[x, :] = np.sin(4.0 * np.pi * xarr[x]) + +# By=By/np.sqrt(4.*np.pi) # Domain inside core (periodic) @@ -76,55 +79,62 @@ ixseps2 = nx # open a new netCDF file for writing. -ncfile = Dataset('otv.grd.128.nc','w', format='NETCDF3_CLASSIC') +ncfile = Dataset("otv.grd.128.nc", "w", format="NETCDF3_CLASSIC") # output data. # create the nx and ny dimensions. -ncfile.createDimension('x',nx) -ncfile.createDimension('y',ny) -ncfile.createDimension('single',1) +ncfile.createDimension("x", nx) +ncfile.createDimension("y", ny) +ncfile.createDimension("single", 1) # create and write nx,ny variables -nxx=ncfile.createVariable('nx','i4',('single')) -nyy=ncfile.createVariable('ny','i4',('single')) +nxx = ncfile.createVariable("nx", "i4", ("single")) +nyy = ncfile.createVariable("ny", "i4", ("single")) -nxx[:]=nx -nyy[:]=ny +nxx[:] = nx +nyy[:] = ny # Define the coordinate variables. They will hold the coordinate # information, that is, xarr,yarr -dx = ncfile.createVariable('dx',dtype('float32').char,('x','y')) -dy = ncfile.createVariable('dy',dtype('float32').char,('x','y',)) +dx = ncfile.createVariable("dx", dtype("float32").char, ("x", "y")) +dy = ncfile.createVariable( + "dy", + dtype("float32").char, + ( + "x", + "y", + ), +) # write data to coordinate vars. -dx[:,:] = dxarr -dy[:,:] = dyarr +dx[:, :] = dxarr +dy[:, :] = dyarr # create and write ixseps* dimensions. -ix1=ncfile.createVariable('ixseps1','i4',('single')) -ix2=ncfile.createVariable('ixseps2','i4',('single')) +ix1 = ncfile.createVariable("ixseps1", "i4", ("single")) +ix2 = ncfile.createVariable("ixseps2", "i4", ("single")) -ix1[:]=ixseps1 -ix2[:]=ixseps2 +ix1[:] = ixseps1 +ix2[:] = ixseps2 -# create the corresponding variables -rho0 = ncfile.createVariable('rho0',dtype('float32').char,('x','y')) -p0 = ncfile.createVariable('p0',dtype('float32').char,('x','y')) -v0_x = ncfile.createVariable('v0_x',dtype('float32').char,('x','y')) -v0_y = ncfile.createVariable('v0_y',dtype('float32').char,('x','y')) -B0x = ncfile.createVariable('B0x',dtype('float32').char,('x','y')) -B0y = ncfile.createVariable('B0y',dtype('float32').char,('x','y')) +# create the corresponding variables +rho0 = ncfile.createVariable("rho0", dtype("float32").char, ("x", "y")) +p0 = ncfile.createVariable("p0", dtype("float32").char, ("x", "y")) +v0_x = ncfile.createVariable("v0_x", dtype("float32").char, ("x", "y")) +v0_y = ncfile.createVariable("v0_y", dtype("float32").char, ("x", "y")) +B0x = ncfile.createVariable("B0x", dtype("float32").char, ("x", "y")) +B0y = ncfile.createVariable("B0y", dtype("float32").char, ("x", "y")) # write data to variables. -rho0[:,:]=rho -p0[:,:]=p -v0_x[:,:]=v_x -v0_y[:,:]=v_y -B0x[:,:]=Bx -B0y[:,:]=By +rho0[:, :] = rho +p0[:, :] = p +v0_x[:, :] = v_x +v0_y[:, :] = v_y +B0x[:, :] = Bx +B0y[:, :] = By ncfile.close() -print('*** SUCCESS writing file otv.grd.py.nc!') +print("*** SUCCESS writing file otv.grd.py.nc!") diff --git a/examples/performance/arithmetic/.gitignore b/examples/performance/arithmetic/.gitignore deleted file mode 100644 index 077be4cbd0..0000000000 --- a/examples/performance/arithmetic/.gitignore +++ /dev/null @@ -1 +0,0 @@ -arithmetic \ No newline at end of file diff --git a/examples/performance/arithmetic/arithmetic.cxx b/examples/performance/arithmetic/arithmetic.cxx deleted file mode 100644 index fc2357978a..0000000000 --- a/examples/performance/arithmetic/arithmetic.cxx +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Timing of arithmetic operations - * - */ - -#include - -#include - -#include - -using SteadyClock = std::chrono::time_point; -using Duration = std::chrono::duration; -using namespace std::chrono; - -#define TIMEIT(elapsed, ...) \ - { \ - SteadyClock start = steady_clock::now(); \ - { __VA_ARGS__; } \ - Duration diff = steady_clock::now() - start; \ - diff *= 1000 * 1000; \ - elapsed.min = diff > elapsed.min ? elapsed.min : diff; \ - elapsed.max = diff < elapsed.max ? elapsed.max : diff; \ - elapsed.count++; \ - elapsed.avg = elapsed.avg * (1 - 1. / elapsed.count) + diff / elapsed.count; \ - } - -struct Durations { - Duration max; - Duration min; - Duration avg; - int count; -}; - -class Arithmetic : public PhysicsModel { -protected: - int init(bool) { - - Field3D a = 1.0; - Field3D b = 2.0; - Field3D c = 3.0; - a.setRegion("RGN_ALL"); - b.setRegion("RGN_NOBNDRY"); - - Field3D result1, result2, result3, result4; - - // Using Field methods (classic operator overloading) - - result1 = 2. * a + b * c; -#define dur_init {Duration::min(), Duration::max(), Duration::zero(), 0} - Durations elapsed1 = dur_init, elapsed2 = dur_init, elapsed3 = dur_init, - elapsed4 = dur_init; - - for (int ik = 0; ik < 1e3; ++ik) { - TIMEIT(elapsed1, result1 = 2. * a + b * c;); - - // Using C loops - result2.allocate(); - BoutReal* rd = &result2(0, 0, 0); - BoutReal* ad = &a(0, 0, 0); - BoutReal* bd = &b(0, 0, 0); - BoutReal* cd = &c(0, 0, 0); - TIMEIT( - elapsed2, - for (int i = 0, iend = (mesh->LocalNx * mesh->LocalNy * mesh->LocalNz) - 1; - i != iend; i++) { - *rd = 2. * (*ad) + (*bd) * (*cd); - rd++; - ad++; - bd++; - cd++; - }); - - // Template expressions - TIMEIT(elapsed3, result3 = eval3D(add(mul(2, a), mul(b, c)));); - - // Range iterator - result4.allocate(); - TIMEIT(elapsed4, for (auto i : result4) result4[i] = 2. * a[i] + b[i] * c[i];); - } - - output.enable(); - output << "TIMING | minimum | mean | maximum\n" - << "----------- | ---------- | ---------- | ----------\n"; - //#define PRINT(str,elapsed) output << str << elapsed.min.count()<< - //elapsed.avg.count()<< elapsed.max.count() << endl; -#define PRINT(str, elapsed) \ - output.write("{:s} | {:7.3f} us | {:7.3f} us | {:7.3f} us\n", str, \ - elapsed.min.count(), elapsed.avg.count(), elapsed.max.count()) - PRINT("Fields: ", elapsed1); - PRINT("C loop: ", elapsed2); - PRINT("Templates: ", elapsed3); - PRINT("Range For: ", elapsed4); - output.disable(); - SOLVE_FOR(n); - return 0; - } - - int rhs(BoutReal) { - ddt(n) = 0; - return 0; - } - Field3D n; -}; - -BOUTMAIN(Arithmetic); diff --git a/examples/performance/arithmetic/data/BOUT.inp b/examples/performance/arithmetic/data/BOUT.inp deleted file mode 100644 index 0deb623c4b..0000000000 --- a/examples/performance/arithmetic/data/BOUT.inp +++ /dev/null @@ -1,5 +0,0 @@ -MZ = 1024 - -[mesh] -nx = 50 -ny = 2 diff --git a/examples/performance/arithmetic/run.sh b/examples/performance/arithmetic/run.sh deleted file mode 100755 index 3a1cc844a6..0000000000 --- a/examples/performance/arithmetic/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -make || exit - -./arithmetic -q -q -q diff --git a/examples/performance/arithmetic_3d2d/.gitignore b/examples/performance/arithmetic_3d2d/.gitignore deleted file mode 100644 index 14968af063..0000000000 --- a/examples/performance/arithmetic_3d2d/.gitignore +++ /dev/null @@ -1 +0,0 @@ -arithmetic_3d2d \ No newline at end of file diff --git a/examples/performance/arithmetic_3d2d/arithmetic_3d2d.cxx b/examples/performance/arithmetic_3d2d/arithmetic_3d2d.cxx deleted file mode 100644 index 83167a5b42..0000000000 --- a/examples/performance/arithmetic_3d2d/arithmetic_3d2d.cxx +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Timing of arithmetic operations (Field3D/Field2D mixed) - * - */ - -#include - -#include - -#include -#include -#include - -using SteadyClock = std::chrono::time_point; -using Duration = std::chrono::duration; -using namespace std::chrono; - -#define TIMEIT(NAME, ...) \ - { \ - SteadyClock start = steady_clock::now(); \ - __VA_ARGS__ \ - Duration diff = steady_clock::now() - start; \ - auto elapsed = elapsedMap[NAME]; \ - elapsed.min = std::min(diff, elapsed.min); \ - elapsed.max = std::max(diff, elapsed.max); \ - elapsed.count++; \ - elapsed.avg = elapsed.avg * (1 - 1. / elapsed.count) + diff / elapsed.count; \ - elapsedMap[NAME] = elapsed; \ - } - -struct Durations { - Duration max; - Duration min; - Duration avg; - int count; - Durations() - : max(Duration::min()), min(Duration::max()), avg(Duration::zero()), count(0){}; -}; - -class Arithmetic : public PhysicsModel { -protected: - std::map elapsedMap; - - int init(bool) { - Field3D a = 1.0; - Field3D b = 2.0; - Field2D c = 3.0; - - Field3D result1, result2, result3, result4; - - // Using Field methods (classic operator overloading) - result1 = 2. * a + b * c; - - for (int ik = 0; ik < 1e2; ++ik) { - result1.allocate(); - TIMEIT("Fields", result1 = 2. * a + b * c;); - - // Using C loops - result2.allocate(); - BoutReal* rd = &result2(0, 0, 0); - BoutReal* ad = &a(0, 0, 0); - BoutReal* bd = &b(0, 0, 0); - BoutReal* cd = &c(0, 0, 0); - TIMEIT( - "C loop", - for (int i = 0, iend = (mesh->LocalNx * mesh->LocalNy) - 1; i != iend; i++) { - for (int j = 0, jend = mesh->LocalNz - 1; j != jend; j++) { - *rd = 2. * (*ad) + (*bd) * (*cd); - rd++; - ad++; - bd++; - } - cd++; - }); - - // Template expressions - result3.allocate(); - TIMEIT("Templates", result3 = eval3D(add(mul(2, a), mul(b, c)));); - - // Range iterator - result4.allocate(); - TIMEIT("Range For", for (auto i : result4) result4[i] = 2. * a[i] + b[i] * c[i];); - } - - output.enable(); - constexpr int width = 15; - output << std::setw(width) << "TIMING"; - output << std::setw(width) << "min"; - output << std::setw(width) << "avg"; - output << std::setw(width) << "max"; - output << "\n======"; - for (int i = 0; i < 4 * width; ++i) { - output << "="; - }; - output << "\n"; - - for (const auto& approach : elapsedMap) { - output << std::setw(width) << approach.first; - output << std::setw(width) << approach.second.min.count(); - output << std::setw(width) << approach.second.avg.count(); - output << std::setw(width) << approach.second.max.count(); - output << "\n"; - } - output.disable(); - SOLVE_FOR(n); - return 0; - } - - int rhs(BoutReal) { - ddt(n) = 0; - return 0; - } - Field3D n; -}; - -BOUTMAIN(Arithmetic); diff --git a/examples/performance/arithmetic_3d2d/data/BOUT.inp b/examples/performance/arithmetic_3d2d/data/BOUT.inp deleted file mode 100644 index 0deb623c4b..0000000000 --- a/examples/performance/arithmetic_3d2d/data/BOUT.inp +++ /dev/null @@ -1,5 +0,0 @@ -MZ = 1024 - -[mesh] -nx = 50 -ny = 2 diff --git a/examples/performance/arithmetic_3d2d/run.sh b/examples/performance/arithmetic_3d2d/run.sh deleted file mode 100644 index ee36808c21..0000000000 --- a/examples/performance/arithmetic_3d2d/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -make || exit - -./arithmetic_3d2d -q -q -q diff --git a/examples/performance/bracket/bracket.cxx b/examples/performance/bracket/bracket.cxx index 50012510ff..0ef9e241fb 100644 --- a/examples/performance/bracket/bracket.cxx +++ b/examples/performance/bracket/bracket.cxx @@ -68,9 +68,6 @@ int main(int argc, char** argv) { ITERATOR_TEST_BLOCK("Bracket [2D,3D] ARAKAWA", result = bracket(a, c, BRACKET_ARAKAWA);); - ITERATOR_TEST_BLOCK("Bracket [2D,3D] ARAKAWA_OLD", - result = bracket(a, c, BRACKET_ARAKAWA_OLD);); - ITERATOR_TEST_BLOCK("Bracket [2D,3D] SIMPLE", result = bracket(a, c, BRACKET_SIMPLE);); @@ -81,21 +78,12 @@ int main(int argc, char** argv) { ITERATOR_TEST_BLOCK("Bracket [3D,3D] ARAKAWA", result = bracket(a, b, BRACKET_ARAKAWA);); - ITERATOR_TEST_BLOCK("Bracket [3D,3D] ARAKAWA_OLD", - result = bracket(a, b, BRACKET_ARAKAWA_OLD);); - ITERATOR_TEST_BLOCK("Bracket [3D,3D] SIMPLE", result = bracket(a, b, BRACKET_SIMPLE);); ITERATOR_TEST_BLOCK("Bracket [3D,3D] DEFAULT", result = bracket(a, b, BRACKET_STD);); } - // Uncomment below for a "correctness" check - // Field3D resNew = bracket(a, b, BRACKET_ARAKAWA); mesh->communicate(resNew); - // Field3D resOld = bracket(a, b, BRACKET_ARAKAWA_OLD); mesh->communicate(resOld); - // time_output << "Max abs diff is - // "<LocalNx; ++i) { for (int j = mesh->ystart; j < mesh->yend; ++j) { - for (int k = 0; k < mesh->LocalNz; ++k) { + for (int k = mesh->zstart; k <= mesh->zend; ++k) { result(i, j, k) = (a(i, j + 1, k) - a(i, j - 1, k)); } } @@ -76,7 +76,7 @@ int main(int argc, char** argv) { BOUT_OMP_PERF(parallel for) for(int i=0;iLocalNx;++i) { for (int j = mesh->ystart; j < mesh->yend; ++j) { - for (int k = 0; k < mesh->LocalNz; ++k) { + for (int k = mesh->zstart; k <= mesh->zend; ++k) { result(i, j, k) = (a(i, j + 1, k) - a(i, j - 1, k)); } } diff --git a/examples/performance/iterator/iterator.cxx b/examples/performance/iterator/iterator.cxx index 7a29b00298..e1fc59d067 100644 --- a/examples/performance/iterator/iterator.cxx +++ b/examples/performance/iterator/iterator.cxx @@ -77,7 +77,7 @@ int main(int argc, char** argv) { ITERATOR_TEST_BLOCK( "Nested loop", for (int i = 0; i < mesh->LocalNx; ++i) { for (int j = 0; j < mesh->LocalNy; ++j) { - for (int k = 0; k < mesh->LocalNz; ++k) { + for (int k = mesh->zstart; k <= mesh->zend; ++k) { result(i, j, k) = a(i, j, k) + b(i, j, k); } } @@ -88,7 +88,7 @@ int main(int argc, char** argv) { BOUT_OMP_PERF(parallel for) for(int i=0;iLocalNx;++i) { for (int j = 0; j < mesh->LocalNy; ++j) { - for (int k = 0; k < mesh->LocalNz; ++k) { + for (int k = mesh->zstart; k <= mesh->zend; ++k) { result(i, j, k) = a(i, j, k) + b(i, j, k); } } diff --git a/examples/performance/iterator/scaling_parser.py b/examples/performance/iterator/scaling_parser.py index d7a23842d4..15f0ea8780 100644 --- a/examples/performance/iterator/scaling_parser.py +++ b/examples/performance/iterator/scaling_parser.py @@ -2,8 +2,7 @@ def read_file(filename): - reader = csv.reader(open(filename, 'r'), delimiter='\t', - skipinitialspace=True) + reader = csv.reader(open(filename, "r"), delimiter="\t", skipinitialspace=True) # Skip header for _, _ in zip(range(4), reader): @@ -13,7 +12,7 @@ def read_file(filename): for line in reader: if line == []: break - case_lines[line[0].rstrip('.')] = line[1] + case_lines[line[0].rstrip(".")] = line[1] titles = next(reader) cases_weak = {col.strip(): [] for col in titles[:-1]} diff --git a/examples/preconditioning/wave/CMakeLists.txt b/examples/preconditioning/wave/CMakeLists.txt index 437f39fe3a..05d7548832 100644 --- a/examples/preconditioning/wave/CMakeLists.txt +++ b/examples/preconditioning/wave/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(preconditioning-wave LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() diff --git a/examples/preconditioning/wave/data/BOUT.inp b/examples/preconditioning/wave/data/BOUT.inp index b7a2e816c3..ca2f31c741 100644 --- a/examples/preconditioning/wave/data/BOUT.inp +++ b/examples/preconditioning/wave/data/BOUT.inp @@ -12,7 +12,7 @@ first = c2 [solver] type = cvode # Need CVODE or PETSc -use_precon = true # Use preconditioner +cvode_precon_method = user # Use user-supplied preconditioner use_jacobian = false # Use user-supplied preconditioner? rightprec = false # Use Right preconditioner (default left) diagnose = true # Print additional diagnostics diff --git a/examples/staggered_grid/CMakeLists.txt b/examples/staggered_grid/CMakeLists.txt index dd2b3b463e..1950d16c0b 100644 --- a/examples/staggered_grid/CMakeLists.txt +++ b/examples/staggered_grid/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.13) project(staggered_grid LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(staggered_grid +bout_add_example( + staggered_grid SOURCES test_staggered.cxx EXTRA_FILES generate.py run test-staggered.nc - DATA_DIRS data test) + DATA_DIRS data test +) diff --git a/examples/staggered_grid/generate.py b/examples/staggered_grid/generate.py index da84e9c2e6..a5a0120612 100755 --- a/examples/staggered_grid/generate.py +++ b/examples/staggered_grid/generate.py @@ -4,11 +4,11 @@ # Generate an input mesh # -from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries +from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries -nx = 5 # Minimum is 5: 2 boundary, one evolved +nx = 5 # Minimum is 5: 2 boundary, one evolved ny = 32 # Minimum 5. Should be divisible by number of processors (so powers of 2 nice) -dy = 1. # distance between points in y, in m/g22/lengthunit +dy = 1.0 # distance between points in y, in m/g22/lengthunit ixseps1 = -1 ixseps2 = -1 diff --git a/examples/subsampling/CMakeLists.txt b/examples/subsampling/CMakeLists.txt index 86f71d98f5..c6c487e687 100644 --- a/examples/subsampling/CMakeLists.txt +++ b/examples/subsampling/CMakeLists.txt @@ -2,11 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(subsampling LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(subsampling +bout_add_example( + subsampling SOURCES monitor.cxx - EXTRA_FILES show.py) - + EXTRA_FILES show.py +) diff --git a/examples/subsampling/show.py b/examples/subsampling/show.py index 34c6ee3084..b79c5e2964 100755 --- a/examples/subsampling/show.py +++ b/examples/subsampling/show.py @@ -11,14 +11,14 @@ for pack in monitors: filename, data_name = pack - t = DataFile(path+'/'+filename+'.dmp.0.nc').read('t_array') - data = DataFile(path+'/'+filename+'.dmp.0.nc').read(data_name).flatten() + t = DataFile(path + "/" + filename + ".dmp.0.nc").read("t_array") + data = DataFile(path + "/" + filename + ".dmp.0.nc").read(data_name).flatten() plt.plot(t, data, label="{} {}".format(filename, data_name)) -time = DataFile(path+'/BOUT.dmp.0.nc').read('t_array') -data = DataFile(path+'/BOUT.dmp.0.nc').read("T")[:, 2, 2, 0] +time = DataFile(path + "/BOUT.dmp.0.nc").read("t_array") +data = DataFile(path + "/BOUT.dmp.0.nc").read("T")[:, 2, 2, 0] -plt.plot(time, data, marker='+', label="BOUT++ T") +plt.plot(time, data, marker="+", label="BOUT++ T") plt.xlabel("Time") plt.legend() diff --git a/examples/wave-slab/CMakeLists.txt b/examples/wave-slab/CMakeLists.txt index b1943c4e1c..8de548b71d 100644 --- a/examples/wave-slab/CMakeLists.txt +++ b/examples/wave-slab/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.13) project(wave-slab LANGUAGES CXX) -if (NOT TARGET bout++::bout++) +if(NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(wave-slab +bout_add_example( + wave-slab SOURCES wave_slab.cxx - EXTRA_FILES generate.py) + EXTRA_FILES generate.py +) diff --git a/examples/wave-slab/generate.py b/examples/wave-slab/generate.py index 0a2e8f3049..12698d1e24 100755 --- a/examples/wave-slab/generate.py +++ b/examples/wave-slab/generate.py @@ -51,7 +51,7 @@ for x in range(nx): Bpxy[x, :] = Bpx[x] -Bxy = sqrt(Bpxy ** 2 + Bt ** 2) +Bxy = sqrt(Bpxy**2 + Bt**2) # Calculate change in poloidal flux dr = Lx / nx # Constant mesh spacing in radius diff --git a/examples/wave-slab/wave_slab.cxx b/examples/wave-slab/wave_slab.cxx index 4169b63dab..6101268e72 100644 --- a/examples/wave-slab/wave_slab.cxx +++ b/examples/wave-slab/wave_slab.cxx @@ -1,54 +1,22 @@ /* Simple wave test in a sheared slab domain. - + Uses the same field-aligned Clebsch coordinate system as most BOUT++ tokamak simulations. See the coordinates manual for details. - - Note: Here the only components of the coordinate system which + + Note: Here the only components of the coordinate system which are tested are g_22 (for Grad_par), and the twist shift angle. - + */ +#include "bout/tokamak_coordinates.hxx" #include class WaveTest : public PhysicsModel { public: int init(bool UNUSED(restarting)) { - auto* coords = mesh->getCoordinates(); - Field2D Rxy, Bpxy, Btxy, hthe, I; - GRID_LOAD(Rxy); - GRID_LOAD(Bpxy); - GRID_LOAD(Btxy); - GRID_LOAD(hthe); - mesh->get(coords->Bxy, "Bxy"); - int ShiftXderivs = 0; - mesh->get(ShiftXderivs, "false"); - if (ShiftXderivs) { - // No integrated shear in metric - I = 0.0; - } else { - mesh->get(I, "sinty"); - } - - coords->g11 = pow(Rxy * Bpxy, 2.0); - coords->g22 = 1.0 / pow(hthe, 2.0); - coords->g33 = pow(I, 2.0) * coords->g11 + pow(coords->Bxy, 2.0) / coords->g11; - coords->g12 = 0.0; - coords->g13 = -I * coords->g11; - coords->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coords->J = hthe / Bpxy; - - coords->g_11 = 1.0 / coords->g11 + (pow(I * Rxy, 2.0)); - coords->g_22 = pow(coords->Bxy * hthe / Bpxy, 2.0); - coords->g_33 = Rxy * Rxy; - coords->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coords->g_13 = I * Rxy * Rxy; - coords->g_23 = Btxy * hthe * Rxy / Bpxy; - - coords->geometry(); - + bout::set_tokamak_coordinates(*mesh, 1.0, 1.0, true); solver->add(f, "f"); solver->add(g, "g"); diff --git a/externalpackages/PVODE/CMakeLists.txt b/externalpackages/PVODE/CMakeLists.txt index 5e3f8f2f63..51afe8047c 100644 --- a/externalpackages/PVODE/CMakeLists.txt +++ b/externalpackages/PVODE/CMakeLists.txt @@ -6,14 +6,17 @@ else() cmake_policy(VERSION 3.12) endif() -project(PVODE +project( + PVODE DESCRIPTION "ODE Solver" VERSION 0.1 - LANGUAGES CXX) + LANGUAGES CXX +) find_package(MPI REQUIRED) -add_library(pvode +add_library( + pvode source/cvode.cpp source/nvector.cpp source/llnlmath.cpp @@ -33,45 +36,43 @@ add_library(pvode include/pvode/smalldense.h include/pvode/spgmr.h include/pvode/vector.h - ) - -target_include_directories(pvode PUBLIC - $ - $ - $ - ) +) + +target_include_directories( + pvode + PUBLIC $ + $ + $ +) target_link_libraries(pvode PUBLIC MPI::MPI_CXX) -add_library(pvpre - include/pvode/pvbbdpre.h - precon/pvbbdpre.cpp - precon/band.cpp - precon/band.h - ) - +add_library( + pvpre include/pvode/pvbbdpre.h precon/pvbbdpre.cpp precon/band.cpp + precon/band.h +) -set_target_properties(pvode PROPERTIES - SOVERSION 1.0.0) +set_target_properties(pvode PROPERTIES SOVERSION 1.0.0) -target_include_directories(pvpre PUBLIC - $ - $ - $ - ) +target_include_directories( + pvpre + PUBLIC $ + $ + $ +) target_link_libraries(pvpre PUBLIC pvode MPI::MPI_CXX) - -set_target_properties(pvpre PROPERTIES - SOVERSION 1.0.0) +set_target_properties(pvpre PROPERTIES SOVERSION 1.0.0) include(GNUInstallDirs) -install(TARGETS pvode pvpre +install( + TARGETS pvode pvpre EXPORT PVODETargets LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - ) + INCLUDES + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) include(CMakePackageConfigHelpers) @@ -79,17 +80,19 @@ write_basic_package_version_file( PVODEConfigVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY SameMajorVersion - ) +) -install(EXPORT PVODETargets +install( + EXPORT PVODETargets FILE PVODEConfig.cmake NAMESPACE PVODE:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/PVODE" - ) +) -export(EXPORT PVODETargets +export( + EXPORT PVODETargets FILE "${CMAKE_CURRENT_BINARY_DIR}/PVODEConfig.cmake" NAMESPACE PVODE:: - ) +) export(PACKAGE PVODE) diff --git a/externalpackages/PVODE/makefile b/externalpackages/PVODE/makefile deleted file mode 100644 index 410470a320..0000000000 --- a/externalpackages/PVODE/makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Makefile for example codes -# Works in the same way as the root Makefile - -TARGET?=all - -DIRS = source precon - -all: $(DIRS) - -.PHONY: $(DIRS) - -$(DIRS): - @$(MAKE) -s --no-print-directory TARGET=$(TARGET) -C $@ $(TARGET) - -clean:: - @for pp in $(DIRS); do echo " " $$pp cleaned; $(MAKE) --no-print-directory -C $$pp clean; done diff --git a/externalpackages/boutdata b/externalpackages/boutdata index e458cf0cf2..11f5d0acb3 160000 --- a/externalpackages/boutdata +++ b/externalpackages/boutdata @@ -1 +1 @@ -Subproject commit e458cf0cf2af6ff68db91da39ef3e15a7e9e6b3d +Subproject commit 11f5d0acb3d92a30eb0f97866c206a238c487076 diff --git a/externalpackages/cpptrace b/externalpackages/cpptrace new file mode 160000 index 0000000000..027f9aee2d --- /dev/null +++ b/externalpackages/cpptrace @@ -0,0 +1 @@ +Subproject commit 027f9aee2d34dbe1c98f26224e1fbe1654cb4aae diff --git a/externalpackages/fmt b/externalpackages/fmt index 2ac6c5ca8b..407c905e45 160000 --- a/externalpackages/fmt +++ b/externalpackages/fmt @@ -1 +1 @@ -Subproject commit 2ac6c5ca8b3dfbcb1cc5cf49a8cc121e3984559c +Subproject commit 407c905e45ad75fc29bf0f9bb7c5c2fd3475976f diff --git a/externalpackages/googletest b/externalpackages/googletest index 0953a17a42..91c99b6ffe 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit 0953a17a4281fc26831da647ad3fcd5e21e6473b +Subproject commit 91c99b6ffecb6f37ca11c25a0db84007c263c1f2 diff --git a/include/boundary_factory.hxx b/include/boundary_factory.hxx deleted file mode 100644 index abbead8fc4..0000000000 --- a/include/boundary_factory.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_factory.hxx" has moved to "bout/boundary_factory.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_factory.hxx" diff --git a/include/boundary_op.hxx b/include/boundary_op.hxx deleted file mode 100644 index c96310f2d4..0000000000 --- a/include/boundary_op.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_op.hxx" has moved to "bout/boundary_op.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_op.hxx" diff --git a/include/boundary_region.hxx b/include/boundary_region.hxx deleted file mode 100644 index f487e88aeb..0000000000 --- a/include/boundary_region.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_region.hxx" has moved to "bout/boundary_region.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_region.hxx" diff --git a/include/boundary_standard.hxx b/include/boundary_standard.hxx deleted file mode 100644 index b7f17cf363..0000000000 --- a/include/boundary_standard.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_standard.hxx" has moved to "bout/boundary_standard.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_standard.hxx" diff --git a/include/bout.hxx b/include/bout.hxx deleted file mode 100644 index 926f035d2f..0000000000 --- a/include/bout.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "bout.hxx" has moved to "bout/bout.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/bout.hxx" diff --git a/include/bout/adios_object.hxx b/include/bout/adios_object.hxx index 12da8ce4c7..ee7e82e45a 100755 --- a/include/bout/adios_object.hxx +++ b/include/bout/adios_object.hxx @@ -1,4 +1,4 @@ -/*!************************************************************************ +/*!\file******************************************************************* * Provides access to the ADIOS library, handling initialisation and * finalisation. * @@ -16,9 +16,23 @@ #if BOUT_HAS_ADIOS2 +#include "bout/assert.hxx" +#include "bout/boutcomm.hxx" +#include "bout/boutexception.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" +#include "bout/fieldperp.hxx" +#include "bout/globals.hxx" +#include "bout/mesh.hxx" +#include "bout/utils.hxx" + #include #include #include +#include +#include +#include +#include namespace bout { @@ -27,23 +41,17 @@ void ADIOSInit(const std::string configFile, MPI_Comm comm); void ADIOSFinalize(); using ADIOSPtr = std::shared_ptr; -using EnginePtr = std::shared_ptr; -using IOPtr = std::shared_ptr; ADIOSPtr GetADIOSPtr(); -IOPtr GetIOPtr(const std::string IOName); class ADIOSStream { public: adios2::IO io; - adios2::Engine engine; - adios2::Variable vTime; - adios2::Variable vStep; int adiosStep = 0; - bool isInStep = false; // true if BeginStep was called and EndStep was not yet called /** create or return the ADIOSStream based on the target file name */ - static ADIOSStream& ADIOSGetStream(const std::string& fname); + static ADIOSStream& ADIOSGetStream(const std::string& fname, adios2::Mode mode, + const std::string& engineType = "BP5"); ~ADIOSStream(); @@ -57,9 +65,94 @@ public: } template - adios2::Variable GetArrayVariable(const std::string& varname, adios2::Dims& shape, - const std::vector& dimNames, - int rank) { + void Get(const std::string& varname, T& value, adios2::Mode mode = adios2::Mode::Sync) { + auto variable = io.InquireVariable(varname); + ASSERT1(variable); + ASSERT1(variable.ShapeID() == adios2::ShapeID::GlobalValue); + engine().Get(variable, &value, mode); + } + + template + void Get(const std::string& varname, Array& value, + adios2::Mode mode = adios2::Mode::Sync) { + GetArrayLike(varname, value, mode); + } + + template + void Get(const std::string& varname, Matrix& value, + adios2::Mode mode = adios2::Mode::Sync) { + GetArrayLike(varname, value, mode); + } + + template + void Get(const std::string& varname, Tensor& value, + adios2::Mode mode = adios2::Mode::Sync) { + GetArrayLike(varname, value, mode); + } + + void Get(const std::string& varname, Field2D& value, + adios2::Mode mode = adios2::Mode::Sync) { + value.allocate(); + GetField(varname, {"x", "y"}, *value.getMesh(), &value(0, 0), mode); + } + + void Get(const std::string& varname, Field3D& value, + adios2::Mode mode = adios2::Mode::Sync) { + value.allocate(); + GetField(varname, {"x", "y", "z"}, *value.getMesh(), &value(0, 0, 0), mode); + } + + void Get(const std::string& varname, FieldPerp& value, + adios2::Mode mode = adios2::Mode::Sync) { + value.allocate(); + GetField(varname, {"x", "z"}, *value.getMesh(), &value(0, 0), mode); + } + + template + void Put(const std::string& varname, T value, adios2::Mode mode = adios2::Mode::Sync) { + if (BoutComm::rank() != 0) { + return; + } + engine().Put(GetValueVariable(varname), value, mode); + } + + template + void Put(const std::string& varname, const Array& value, + adios2::Mode mode = adios2::Mode::Sync) { + PutArrayLike(varname, value, mode); + } + + template + void Put(const std::string& varname, const Matrix& value, + adios2::Mode mode = adios2::Mode::Sync) { + PutArrayLike(varname, value, mode); + } + + template + void Put(const std::string& varname, const Tensor& value, + adios2::Mode mode = adios2::Mode::Sync) { + PutArrayLike(varname, value, mode); + } + + void Put(const std::string& varname, const Field2D& value, + adios2::Mode mode = adios2::Mode::Sync) { + PutField(varname, {"x", "y"}, *value.getMesh(), &value(0, 0), mode); + } + + void Put(const std::string& varname, const Field3D& value, + adios2::Mode mode = adios2::Mode::Sync) { + PutField(varname, {"x", "y", "z"}, *value.getMesh(), &value(0, 0, 0), mode); + } + + void Put(const std::string& varname, const FieldPerp& value, + adios2::Mode mode = adios2::Mode::Sync) { + PutField(varname, {"x", "z"}, *value.getMesh(), &value(0, 0), mode); + } + + template + adios2::Variable + GetArrayVariable(const std::string& varname, const adios2::Dims& shape, + const std::vector& dimNames, int rank) { adios2::Variable v = io.InquireVariable(varname); if (!v) { adios2::Dims start(shape.size()); @@ -74,14 +167,218 @@ public: return v; } + auto engine() -> adios2::Engine& { + if (not engine_) { + engine_ = io.Open(fname, file_mode); + if (not engine_) { + throw BoutException("Could not open ADIOS file '{:s}'", fname); + } + } + return engine_; + } + + void beginStep() { + if (not isInStep) { + engine().BeginStep(); + isInStep = true; + adiosStep = static_cast(engine().CurrentStep()); + } + } + + void endStep() { + if (isInStep) { + engine().EndStep(); + isInStep = false; + } + } + + void finish() { + if (engine_) { + if (isInStep) { + engine().EndStep(); + isInStep = false; + } + engine().Close(); + engine_ = adios2::Engine(); + } + } + private: - ADIOSStream(const std::string fname) : fname(fname){}; + ADIOSStream(const std::string& fname, adios2::Mode mode, const std::string& engineType); + + struct FieldSelection { + adios2::Dims shape; + adios2::Dims start; + adios2::Dims count; + adios2::Dims mem_start; + adios2::Dims mem_count; + + auto selection() const { return adios2::Box{start, count}; } + auto memorySelection() const { + return adios2::Box{mem_start, mem_count}; + } + }; + + void GetField(const std::string& varname, const std::vector& dim_names, + const Mesh& mesh, BoutReal* data, adios2::Mode mode) { + auto variable = io.InquireVariable(varname); + ASSERT1(variable); + ASSERT1(variable.ShapeID() == adios2::ShapeID::GlobalArray); + + auto selection = makeFieldSelection(dim_names, mesh); + variable.SetSelection(selection.selection()); + variable.SetMemorySelection(selection.memorySelection()); + engine().Get(variable, data, mode); + } + + void PutField(const std::string& varname, const std::vector& dim_names, + const Mesh& mesh, const BoutReal* data, adios2::Mode mode) { + auto selection = makeFieldSelection(dim_names, mesh); + auto variable = + GetArrayVariable(varname, selection.shape, dim_names, BoutComm::rank()); + variable.SetSelection(selection.selection()); + variable.SetMemorySelection(selection.memorySelection()); + engine().Put(variable, data, mode); + } + + FieldSelection makeFieldSelection(const std::vector& dim_names, + const Mesh& mesh) const { + ASSERT1(!dim_names.empty()); + ASSERT1(dim_names.size() <= 3); + ASSERT1(dim_names[0] == "x"); + + FieldSelection selection; + selection.shape.push_back(static_cast(mesh.GlobalNx)); + selection.start.push_back(static_cast(mesh.MapGlobalX)); + selection.count.push_back(static_cast(mesh.MapCountX)); + selection.mem_start.push_back(static_cast(mesh.MapLocalX)); + selection.mem_count.push_back(static_cast(mesh.LocalNx)); + + if (dim_names.size() > 1) { + if (dim_names[1] == "y") { + selection.shape.push_back(static_cast(mesh.GlobalNy)); + selection.start.push_back(static_cast(mesh.MapGlobalY)); + selection.count.push_back(static_cast(mesh.MapCountY)); + selection.mem_start.push_back(static_cast(mesh.MapLocalY)); + selection.mem_count.push_back(static_cast(mesh.LocalNy)); + } else if (dim_names[1] == "z") { + selection.shape.push_back(static_cast(mesh.GlobalNz)); + selection.start.push_back(static_cast(mesh.MapGlobalZ)); + selection.count.push_back(static_cast(mesh.MapCountZ)); + selection.mem_start.push_back(static_cast(mesh.MapLocalZ)); + selection.mem_count.push_back(static_cast(mesh.LocalNz)); + } else { + ASSERT1(false); + } + } + + if (dim_names.size() > 2) { + ASSERT1(dim_names[1] == "y"); + ASSERT1(dim_names[2] == "z"); + selection.shape.push_back(static_cast(mesh.GlobalNz)); + selection.start.push_back(static_cast(mesh.MapGlobalZ)); + selection.count.push_back(static_cast(mesh.MapCountZ)); + selection.mem_start.push_back(static_cast(mesh.MapLocalZ)); + selection.mem_count.push_back(static_cast(mesh.LocalNz)); + } + + return selection; + } + + template + void GetArrayLike(const std::string& varname, Container& value, adios2::Mode mode) { + using T = typename Container::data_type; + auto variable = io.InquireVariable(varname); + ASSERT1(variable); + ASSERT1(variable.ShapeID() == adios2::ShapeID::GlobalArray); + + const auto shape = variable.Shape(); + auto dims_attr = io.InquireAttribute(varname + "/__xarray_dimensions__"); + auto read_shape = shape; + + if (dims_attr) { + const auto dim_names = dims_attr.Data(); + if (!dim_names.empty() && dim_names[0] == "rank") { + ASSERT1(!shape.empty()); + ASSERT1(static_cast(BoutComm::rank()) < shape[0]); + + adios2::Dims start{static_cast(BoutComm::rank())}; + adios2::Dims count{1}; + for (std::size_t i = 1; i < shape.size(); i++) { + start.push_back(0); + count.push_back(shape[i]); + } + + variable.SetSelection(adios2::Box{start, count}); + variable.SetMemorySelection(adios2::Box{start, count}); + read_shape = adios2::Dims(shape.begin() + 1, shape.end()); + } else if (!dim_names.empty() && dim_names[0] == "x") { + ASSERT1(globals::mesh); + auto selection = makeFieldSelection(dim_names, *globals::mesh); + variable.SetSelection(selection.selection()); + variable.SetMemorySelection(selection.memorySelection()); + read_shape = selection.mem_count; + } + } + + constexpr auto ndims = std::tuple_size_v; + ASSERT1(read_shape.size() == ndims); + + resizeForShape(value, read_shape, std::make_index_sequence{}); + engine().Get(variable, value.begin(), mode); + } + + template + void PutArrayLike(const std::string& varname, const Container& value, + adios2::Mode mode) { + using T = typename Container::data_type; + auto var = GetArrayVariable(varname, makeShape(BoutComm::size(), value), + makeDimNames(value), BoutComm::rank()); + var.SetSelection(adios2::Box{makeStart(value), makeShape(1, value)}); + engine().Put(var, value.begin(), mode); + } + + template + adios2::Dims makeShape(std::size_t first, const Container& value) const { + return std::apply( + [first](auto... sizes) { + return adios2::Dims{first, static_cast(sizes)...}; + }, + value.shape()); + } + + template + adios2::Dims makeStart(const Container& value) const { + constexpr auto ndims = std::tuple_size_v; + adios2::Dims start(ndims + 1, 0); + start[0] = static_cast(BoutComm::rank()); + return start; + } + + template + std::vector makeDimNames(const Container& value) const { + constexpr auto ndims = std::tuple_size_v; + std::vector dim_names{"rank"}; + dim_names.reserve(ndims + 1); + for (std::size_t i = 0; i < ndims; i++) { + dim_names.push_back("dim_" + std::to_string(i)); + } + return dim_names; + } + + template + void resizeForShape(Container& value, const adios2::Dims& shape, + std::index_sequence /*indices*/) { + value.reallocate(static_cast(shape[I])...); + } + std::string fname; -}; + adios2::Mode file_mode; + adios2::Engine engine_; -/** Set user parameters for an IO group */ -void ADIOSSetParameters(const std::string& input, const char delimKeyValue, - const char delimItem, adios2::IO& io); + /// true if BeginStep was called and EndStep was not yet called + bool isInStep = false; +}; } // namespace bout diff --git a/include/bout/array.hxx b/include/bout/array.hxx index 2c42f15aad..9e1437eb9c 100644 --- a/include/bout/array.hxx +++ b/include/bout/array.hxx @@ -27,14 +27,17 @@ #define BOUT_ARRAY_H #include +#include #include #include +#include #include #if BOUT_USE_OPENMP #include #endif +#include "bout/build_config.hxx" #include "bout/build_defines.hxx" #if BOUT_HAS_UMPIRE @@ -67,6 +70,7 @@ struct ArrayData { auto& rm = umpire::ResourceManager::getInstance(); #if BOUT_HAS_CUDA auto allocator = rm.getAllocator(umpire::resource::Pinned); + //auto allocator = rm.getAllocator(umpire::resource::Unified); #else auto allocator = rm.getAllocator("HOST"); #endif @@ -95,7 +99,7 @@ struct ArrayData { } iterator begin() const { return data; } iterator end() const { return data + len; } - int size() const { return len; } + BOUT_FORCEINLINE int size() const { return len; } /// Copy assignment /// Copy the underlying data from one array to the other @@ -186,9 +190,22 @@ public: Array() noexcept : ptr(nullptr) {} /*! - * Create an array of given length + * Create an array of given length. */ - Array(size_type len) { ptr = get(len); } + Array(size_type len) : ptr(get(len)) {} + + /*! + * Create an array with initializer list. + * This is explicit to avoid confusion with (size_type) constructor. + */ + static Array fromValues(std::initializer_list init) { + if (init.size() == 0) { + return Array(); + } + Array array(init.size()); + std::copy(init.begin(), init.end(), array.begin()); + return array; + } /*! * Destructor. Releases the underlying dataBlock @@ -198,7 +215,7 @@ public: /*! * Copy constructor */ - Array(const Array& other) noexcept { ptr = other.ptr; } + Array(const Array& other) noexcept : ptr(other.ptr) {} /*! * Assignment operator @@ -226,6 +243,12 @@ public: ptr = get(new_size); } + /*! + * Change shape of the container. + * Invalidates contents. + */ + void reshape(std::tuple new_shape) { reallocate(std::get<0>(new_shape)); } + /*! * Holds a static variable which controls whether * memory blocks (dataBlock) are put into a store @@ -283,6 +306,9 @@ public: return ptr->size(); } + /// Return shape of the array (the `size()` in a length-1 tuple) + std::tuple shape() const { return std::make_tuple(size()); }; + /*! * Returns true if the data is unique to this Array. * diff --git a/include/bout/assert.hxx b/include/bout/assert.hxx index 653c44ed42..9de22f958b 100644 --- a/include/bout/assert.hxx +++ b/include/bout/assert.hxx @@ -1,17 +1,17 @@ -/*! +/*!\file * Defines a macro ASSERT which throws a BoutException if a given * condition is false. Whether the assertion is tested depends on * the checking level, so assetions can be removed for optimised runs. - * + * * ASSERT ( condition ) * * level - An integer known at compile time. * condition tested if level >= CHECK * * condition - The expression to test - * + * * e.g. ASSERT2( condition ) will only test condition if CHECK >= 2 - * + * */ #ifndef BOUT_ASSERT_H @@ -19,6 +19,8 @@ #include "bout/boutexception.hxx" +#include // IWYU pragma: export + #ifndef CHECK #define CHECKLEVEL 0 #else @@ -26,40 +28,45 @@ #endif #if CHECKLEVEL >= 0 -#define ASSERT0(condition) \ - if (!(condition)) { \ - throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", __FILE__, __LINE__, \ - #condition); \ +#define ASSERT0(condition) \ + if (!(condition)) { \ + throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", \ + std::string_view(__FILE__), __LINE__, \ + std::string_view(#condition)); \ } #else // CHECKLEVEL >= 0 #define ASSERT0(condition) #endif #if CHECKLEVEL >= 1 -#define ASSERT1(condition) \ - if (!(condition)) { \ - throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", __FILE__, __LINE__, \ - #condition); \ +#define ASSERT1(condition) \ + if (!(condition)) { \ + throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", \ + std::string_view(__FILE__), __LINE__, \ + std::string_view(#condition)); \ + abort(); \ } #else // CHECKLEVEL >= 1 #define ASSERT1(condition) #endif #if CHECKLEVEL >= 2 -#define ASSERT2(condition) \ - if (!(condition)) { \ - throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", __FILE__, __LINE__, \ - #condition); \ +#define ASSERT2(condition) \ + if (!(condition)) { \ + throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", \ + std::string_view(__FILE__), __LINE__, \ + std::string_view(#condition)); \ } #else // CHECKLEVEL >= 2 #define ASSERT2(condition) #endif #if CHECKLEVEL >= 3 -#define ASSERT3(condition) \ - if (!(condition)) { \ - throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", __FILE__, __LINE__, \ - #condition); \ +#define ASSERT3(condition) \ + if (!(condition)) { \ + throw BoutException("Assertion failed in {:s}, line {:d}: {:s}", \ + std::string_view(__FILE__), __LINE__, \ + std::string_view(#condition)); \ } #else // CHECKLEVEL >= 3 #define ASSERT3(condition) diff --git a/include/bout/boundary_common.hxx b/include/bout/boundary_common.hxx new file mode 100644 index 0000000000..6d08f2c9c0 --- /dev/null +++ b/include/bout/boundary_common.hxx @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include + +namespace bout { +namespace boundary { +/// Types of free boundary condition +/// ================== =================================================== +/// Name Description +/// ================== =================================================== +/// ``limited`` use exponential if decreasing, otherwise Neumanm +/// ``exponential`` use exponential extrapolation +/// ``linear`` use linear extrapolation +/// ================== =================================================== +enum class BoundaryFreeExtrapolation : std::uint8_t { limited, exponential, linear }; + +// Limited free gradient of log of a quantity +// This ensures that the guard cell values remain positive +// while also ensuring that the quantity never increases +// +// fm fc | fp +// ^ boundary +// +// exp( 2*log(fc) - log(fm) ) +inline BoutReal limitFreeScale(BoutReal fm, BoutReal fc, + bout::boundary::BoundaryFreeExtrapolation mode) { + if ((fm < fc) && (mode == bout::boundary::BoundaryFreeExtrapolation::limited)) { + return fc; // Neumann rather than increasing into boundary + } + if (fm < 1e-10) { + return fc; // Low / no density condition + } + + BoutReal fp = 0; + switch (mode) { + case bout::boundary::BoundaryFreeExtrapolation::limited: + case bout::boundary::BoundaryFreeExtrapolation::exponential: + fp = fc * fc / fm; // Exponential + break; + case bout::boundary::BoundaryFreeExtrapolation::linear: + fp = (2.0 * fc) - fm; // Linear + break; + } + +#if CHECKLEVEL >= 2 + if (!std::isfinite(fp)) { + throw BoutException("SheathBoundary limitFree: {}, {} -> {}", fm, fc, fp); + } +#endif + + return fp; +} + +} // namespace boundary +} // namespace bout diff --git a/include/bout/boundary_factory.hxx b/include/bout/boundary_factory.hxx index 5f1f6e06a6..17807138be 100644 --- a/include/bout/boundary_factory.hxx +++ b/include/bout/boundary_factory.hxx @@ -13,17 +13,18 @@ class BoundaryRegion; class BoundaryModifier; #include +#include #include /// Create BoundaryOp objects on demand /*! * This implements a simple string parser, used to match boundary condition * names like "dirichlet" with a BoundaryOp object. - * + * * Modifiers: Simple modifications of boundary conditions can be performed, * for example transforming the coordinate system - * - * This is a singleton, so only one instance can exist. This is + * + * This is a singleton, so only one instance can exist. This is * enforced by making the constructor private, and having a getInstance() method * to return a pointer to the only instance. * @@ -33,7 +34,7 @@ class BoundaryModifier; * Boundaries are defined as classes which inherit from BoundaryOp * These define a clone() function which creates a new BoundaryOp, * given a list of arguments. See boundary_standard.hxx for examples. - * + * * class MyBoundary : public BoundaryOp { * public: * BoundaryOp* clone(BoundaryRegion *region, const list &args) { @@ -43,23 +44,23 @@ class BoundaryModifier; * void apply(Field2D &f); * void apply(Field3D &f); * }; - * + * * The singleton instance of BoundaryFactory from getInstance(): - * + * * BoundaryFactory* bf = BoundaryFactory::getInstance(); * * New boundary types can be added to the BoundaryFactory * * bf->add(new MyBoundary, "myboundary"); - * + * * * Subsequent calls to create() or createFromOptions() can make use * of the boundary type "myboundary". * * BoundaryOpBase *bndry = bf->create("myboundary()", new BoundaryRegionXOut("xout", 0, 10, localmesh)); - * + * * where the region is defined in boundary_region.hxx - * + * */ class BoundaryFactory { public: @@ -70,13 +71,16 @@ public: static void cleanup(); ///< Frees all memory /// Create a boundary operation object - BoundaryOpBase* create(const std::string& name, BoundaryRegionBase* region); - BoundaryOpBase* create(const char* name, BoundaryRegionBase* region); + BoundaryOpBase* create(const std::string& name, + const std::shared_ptr& region); + BoundaryOpBase* create(const char* name, + const std::shared_ptr& region); /// Create a boundary object using the options file BoundaryOpBase* createFromOptions(const std::string& varname, - BoundaryRegionBase* region); - BoundaryOpBase* createFromOptions(const char* varname, BoundaryRegionBase* region); + const std::shared_ptr& region); + BoundaryOpBase* createFromOptions(const char* varname, + const std::shared_ptr& region); /*! * Add available boundary conditions and modifiers diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx new file mode 100644 index 0000000000..8e5f37182e --- /dev/null +++ b/include/bout/boundary_iterator.hxx @@ -0,0 +1,108 @@ +#pragma once + +#include "bout/assert.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" +#include "bout/mesh.hxx" +#include "bout/region.hxx" +#include "bout/sys/range.hxx" + +class BoundaryRegionIter { +public: + virtual ~BoundaryRegionIter() = default; + BoundaryRegionIter(int x, int y, int bx, int by, const Mesh& mesh) + : _dir(bx + by), _x(x), _y(y), _bx(bx), _by(by), localmesh(&mesh) { + ASSERT3(_bx * _by == 0); + } + bool operator!=(const BoundaryRegionIter& rhs) const { return ind() != rhs.ind(); } + + Ind3D ind() const { return xyz2ind(_x, _y, _z); } + BoundaryRegionIter& operator++() { + ASSERT3(_z < nz()); + _z++; + if (_z == nz()) { + _z = 0; + _next(); + } + return *this; + } + +protected: + virtual void _next() = 0; + +public: + BoundaryRegionIter& operator*() { return *this; } + +protected: + int x() const { return _x; } + int y() const { return _y; } + int z() const { return _z; } + + void setx(int x) { _x = x; } + void sety(int y) { _y = y; } + +private: + int _dir; + + int _z{0}; + int _x; + int _y; + int _bx; + int _by; + + const Mesh* localmesh; + int nx() const { return localmesh->LocalNx; } + int ny() const { return localmesh->LocalNy; } + int nz() const { return localmesh->LocalNz; } + + Ind3D xyz2ind(int x, int y, int z) const { + return Ind3D{((x * ny() + y) * nz()) + z, ny(), nz()}; + } +}; + +class BoundaryRegionIterY : public BoundaryRegionIter { +public: + ~BoundaryRegionIterY() override = default; + BoundaryRegionIterY(const RangeIterator& r, int y, int dir, bool is_end, + const Mesh& mesh) + : BoundaryRegionIter(r.ind, y, 0, dir, mesh), r(r), is_end(is_end) {} + + bool operator!=(const BoundaryRegionIterY& rhs) { + ASSERT2(y() == rhs.y()); + if (is_end) { + if (rhs.is_end) { + return false; + } + return !rhs.r.isDone(); + } + if (rhs.is_end) { + return !r.isDone(); + } + return x() != rhs.x(); + } + + void _next() override { + ++r; + setx(r.ind); + } + +private: + RangeIterator r; + bool is_end; +}; + +class NewBoundaryRegionY { +public: + NewBoundaryRegionY(const Mesh& mesh, bool lower, const RangeIterator& r) + : mesh(&mesh), lower(lower), r(r) {} + BoundaryRegionIterY begin(bool begin = true) { + return BoundaryRegionIterY(r, lower ? mesh->ystart : mesh->yend, lower ? -1 : +1, + !begin, *mesh); + } + BoundaryRegionIterY end() { return begin(false); } + +private: + const Mesh* mesh; + bool lower; + RangeIterator r; +}; diff --git a/include/bout/boundary_op.hxx b/include/bout/boundary_op.hxx index 1a9aa1ad68..dedc56d0e8 100644 --- a/include/bout/boundary_op.hxx +++ b/include/bout/boundary_op.hxx @@ -55,9 +55,7 @@ public: // Note: All methods must implement clone, except for modifiers (see below) virtual BoundaryOp* clone(BoundaryRegion* UNUSED(region), - const std::list& UNUSED(args)) { - throw BoutException("BoundaryOp::clone not implemented"); - } + const std::list& UNUSED(args)) = 0; /// Clone using positional args and keywords /// If not implemented, check if keywords are passed, then call two-argument version @@ -89,6 +87,12 @@ public: BoundaryModifier(BoundaryOp* operation) : BoundaryOp(operation->bndry), op(operation) {} virtual BoundaryOp* cloneMod(BoundaryOp* op, const std::list& args) = 0; + using BoundaryOp::clone; + BoundaryOp* clone(BoundaryRegion* UNUSED(region), + const std::list& UNUSED(args)) override { + throw BoutException("This must not be used!"); + } + protected: BoundaryOp* op{nullptr}; }; diff --git a/include/bout/boundary_region.hxx b/include/bout/boundary_region.hxx index 58de12045e..106d52f21c 100644 --- a/include/bout/boundary_region.hxx +++ b/include/bout/boundary_region.hxx @@ -1,12 +1,12 @@ - -class BoundaryRegion; - #ifndef BOUT_BNDRY_REGION_H #define BOUT_BNDRY_REGION_H +#include +#include #include #include +class BoundaryRegion; class Mesh; namespace bout { namespace globals { @@ -15,16 +15,17 @@ extern Mesh* mesh; ///< Global mesh } // namespace bout /// Location of boundary -enum class BndryLoc { - xin, - xout, - ydown, - yup, - all, - par_fwd_xin, // Don't include parallel boundaries - par_bkwd_xin, - par_fwd_xout, // Don't include parallel boundaries - par_bkwd_xout +enum class BndryLoc : std::int8_t { + xin = 0, + xout = 1, + ydown = 2, + yup = 3, + all = 4, + par_fwd_xin = 5, // Don't include parallel boundaries + par_bkwd_xin = 6, + par_fwd_xout = 7, // Don't include parallel boundaries + par_bkwd_xout = 8, + invalid = -1 }; constexpr BndryLoc BNDRY_XIN = BndryLoc::xin; constexpr BndryLoc BNDRY_XOUT = BndryLoc::xout; @@ -35,10 +36,19 @@ constexpr BndryLoc BNDRY_PAR_FWD_XIN = BndryLoc::par_fwd_xin; constexpr BndryLoc BNDRY_PAR_BKWD_XIN = BndryLoc::par_bkwd_xin; constexpr BndryLoc BNDRY_PAR_FWD_XOUT = BndryLoc::par_fwd_xout; constexpr BndryLoc BNDRY_PAR_BKWD_XOUT = BndryLoc::par_bkwd_xout; +constexpr BndryLoc BNDRY_INVALID = BndryLoc::invalid; + +/// Physical type of y boundary +enum class YBndryType : std::int8_t { sheath, not_sheath, all }; +/// Base class for boundary regions class BoundaryRegionBase { public: BoundaryRegionBase() = delete; + BoundaryRegionBase(const BoundaryRegionBase&) = delete; + BoundaryRegionBase(BoundaryRegionBase&&) = delete; + BoundaryRegionBase& operator=(const BoundaryRegionBase&) = delete; + BoundaryRegionBase& operator=(BoundaryRegionBase&&) = delete; BoundaryRegionBase(std::string name, Mesh* passmesh = nullptr) : localmesh(passmesh ? passmesh : bout::globals::mesh), label(std::move(name)) {} BoundaryRegionBase(std::string name, BndryLoc loc, Mesh* passmesh = nullptr) @@ -47,12 +57,15 @@ public: virtual ~BoundaryRegionBase() = default; + virtual BoundaryRegion* getLegacyPointer(); Mesh* localmesh; ///< Mesh does this boundary region belongs to std::string label; ///< Label for this boundary region - BndryLoc location; ///< Which side of the domain is it on? - bool isParallel = false; ///< Is this a parallel boundary? + BndryLoc location{BndryLoc::invalid}; ///< Which side of the domain is it on? + bool isParallel = false; ///< Is this a parallel boundary? + bool isX = false; + bool isY = false; virtual void first() = 0; ///< Move the region iterator to the start virtual void next() = 0; ///< Get the next element in the loop @@ -60,6 +73,8 @@ public: /// X or Y first) virtual bool isDone() = 0; ///< Returns true if outside domain. Can use this with nested nextX, nextY + + std::unique_ptr legacy{nullptr}; }; /// Describes a region of the boundary, and a means of iterating over it @@ -71,6 +86,7 @@ public: BoundaryRegion(std::string name, int xd, int yd, Mesh* passmesh = nullptr) : BoundaryRegionBase(name, passmesh), bx(xd), by(yd), width(2) {} ~BoundaryRegion() override = default; + BoundaryRegion* getLegacyPointer() override { return this; } int x, y; ///< Indices of the point in the boundary int bx, by; ///< Direction of the boundary [x+bx][y+by] is going outwards diff --git a/include/bout/boundary_region_iter.hxx b/include/bout/boundary_region_iter.hxx new file mode 100644 index 0000000000..d28f9d21d4 --- /dev/null +++ b/include/bout/boundary_region_iter.hxx @@ -0,0 +1,764 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace bout { +namespace boundary { + +/// Helper concept for `BoundaryRegionIterBase::at` function accessor overloads +/// +/// This is a callable that takes two arguments: +/// - `int yoffset`, the parallel slice offset +/// - `Ind3D ind`, the index of the boundary point +/// +/// and returns a `BoutReal` +template +concept function_accessor = + std::regular_invocable + and std::is_same_v, BoutReal>; + +/// Interface for boundary iterators +/// +/// The function passed into `YBoundary::iter`, for example, operates over +/// elements of types derived from `BoundaryRegionIterBase`, but because this +/// uses CRTP they can be a bit difficult to name. Instead use `BoundaryIterator +/// auto` as the parameter type. +template +concept BoundaryIterator = requires(Iter point, Field3D f) { + point.at(f, int{}); + point.next(f); + point.current(f); + point.prev(f); + + point.ind(); + point.length(CELL_LOC{}); + point.valid(); + point.boundary_width(); + point.is_lower(); + point.offset(); + + point.smallValue(); +}; + +/// Common base class for boundary region iterators +/// +/// This uses CRTP: boundary region iterators should inherit from this, +/// templated on themselves, and they must implement all methods in +/// `boundary_iterator`, (that is, those methods that call `impl().` in this +/// class) +template +class BoundaryRegionIterBase { + BoundaryRegionIterBase() = default; + + /// Get a reference to the derived/implementation class + const Impl& impl() const { return *static_cast(this); } + +public: + /// Get the index at the last point in domain + Ind3D ind() const { return impl()._ind(); } + /// get the length from the point in the domain to the boundary in index + /// space. It is in the range [0, 1] + BoutReal length(CELL_LOC loc) const { return impl()._length(loc); } + /// Lower bound of how many points are between the first point in the domain + /// and the boundary in the other direction. + signed char valid() const { return impl()._valid(); } + /// Get the width of the boundary at the current point + int boundary_width() const { return impl()._boundary_width(); } + /// Is this the lower boundary? + bool is_lower() const { return impl()._is_lower(); } + /// Get the offset from the last point in the domain + /// For FA this is always ±1, for FCI this can be up to ±MYG, excluding 0 + int offset() const { return impl()._offset(); } + + /// Get the value at a given \p offset of a field \p f. + /// + /// `offset = -1` is the second point in the boundary + /// `offset = 0` is the first point in the boundary + /// `offset = 1` is the last point in the domain + /// `offset = 2` is the second to last point in the domain + /// + /// |---|---|---|--> interior points + /// -1 0 ^ 1 2 + /// | + /// boundary + template + requires utils::is_Field_v + const BoutReal& at(const T& f, int offset) const { + return impl().template _at(f, offset); + } + + template + requires utils::is_Field_v + BoutReal& at(T& f, int offset) const { + return impl().template _at(f, offset); + } + + /// Get the first point in the boundary + template + requires utils::is_Field_v + const BoutReal& next(const T& f) const { + return at(f, 0); + } + /// Get the first point in the boundary + template + requires utils::is_Field_v + BoutReal& next(T& f) const { + return at(f, 0); + } + /// Get the last point in the domain + template + requires utils::is_Field_v + const BoutReal& current(const T& f) const { + return at(f, 1); + } + /// Get the last point in the domain + template + requires utils::is_Field_v + BoutReal& current(T& f) const { + return at(f, 1); + } + /// Get the second to last point in the domain - this may not be valid and thus throw + template + requires utils::is_Field_v + const BoutReal& prev(const T& f) const { + return at(f, 2); + } + + /* + * FUNCTIONS ACCESSORS + */ + + /// Apply the function \p func at a given \p offset + /// + /// |---|---|---|--> interior points + /// -1 0 ^ 1 2 + /// | + /// boundary + template + BoutReal at(const function_accessor auto& func, int offset) const { + return impl().template _at(func, offset); + } + /// Get the first point in the boundary + BoutReal next(const function_accessor auto& func) const { return at(func, 0); } + /// Get the last point in the domain + BoutReal current(const function_accessor auto& func) const { return at(func, 1); } + /// Get the second to last point in the domain - this may not be valid and thus throw + BoutReal prev(const function_accessor auto& func) const { return at(func, 2); } + + void setSmallValue(BoutReal val) { + ASSERT2(val > 0); + ASSERT2(val < 0.5); + small_value = val; + } + + BoutReal smallValue() const { return small_value; } + +private: + BoutReal small_value = 1e-4; + friend Impl; +}; + +/// An FCI-aware boundary region +/// +/// This can't use the legacy iteration methods (`first()`, `next()`, and so on) +class BoundaryRegionFCI : public BoundaryRegionBase { + struct RealPoint { + BoutReal s_x; + BoutReal s_y; + BoutReal s_z; + }; + +public: + /// A single point in a `BoundaryRegionFCI` + class Point : public BoundaryRegionIterBase { + private: + /// Index of the first boundary point + Ind3D index; + Mesh* localmesh_m; + /// Intersection with boundary in index space + RealPoint intersection; + /// Distance to intersection + BoutReal length_m; + /// Direction to the boundary. Positive values are in the sense of the + /// increasing coordinate + int dir_m; + /// How many points we can go in the opposite direction + signed char valid_m; + /// How many points we are away from the boundary + signed char offset_m; + unsigned char abs_offset_m; + + public: + Point() = delete; + Point(Ind3D index, RealPoint intersection, BoutReal length, signed char valid, + signed char offset, Mesh* mesh, int dir) + : index(index), localmesh_m(mesh), intersection(intersection), length_m(length), + dir_m(dir), valid_m(valid), offset_m(offset), + abs_offset_m(static_cast(std::abs(offset))) {} + + void setValid(char valid) { valid_m = valid; }; + + BoutReal s_x() const { return intersection.s_x; }; + BoutReal s_y() const { return intersection.s_y; }; + BoutReal s_z() const { return intersection.s_z; }; + + Mesh* localmesh() const { return localmesh_m; }; + int dir() const { return dir_m; } + bool _is_lower() const { return dir_m < 0; } + + template + requires utils::is_Field_v + const BoutReal& _at(const T& f, int off) const { + ASSERT3(f.hasParallelSlices()); + if constexpr (check) { + ASSERT3(_valid() > -off - 2); + } + auto _off = _offset() - (off * dir_m); + return f.ynext(_off)[_ind().yp(_off)]; + } + + template + requires utils::is_Field_v + BoutReal& _at(T& f, int off) const { + ASSERT3(f.hasParallelSlices()); + if constexpr (check) { + ASSERT3(_valid() > -off - 2); + } + auto _off = _offset() - (off * dir_m); + return f.ynext(_off)[_ind().yp(_off)]; + } + + template + BoutReal _at(const function_accessor auto& f, int off) const { + if constexpr (check) { + ASSERT3(valid() > -off - 2); + } + auto _off = _offset() + (off * dir_m); + return f(_off, _ind().yp(_off)); + } + + signed char _offset() const { return offset_m; } + signed char _valid() const { return valid_m; } + Ind3D _ind() const { return index; } + int _boundary_width() const { return localmesh_m->ystart - abs_offset_m + 1; } + BoutReal _length([[maybe_unused]] CELL_LOC loc) const { + ASSERT3(loc == CELL_CENTRE); + return length_m; + } + + auto operator<=>(const Point& rhs) const { + // Ensure we're looking at the same boundary + ASSERT3(dir_m == rhs.dir_m); + return _ind() <=> rhs._ind(); + } + bool operator==(Point rhs) const { + ASSERT3(dir_m == rhs.dir_m); + return _ind() == rhs._ind(); + } + }; + + BoundaryRegionFCI(const std::string& name, const BndryLoc& loc, int dir, Mesh* mesh) + : BoundaryRegionBase(name, loc, mesh), _dir(dir), localmesh(mesh) { + isParallel = true; + }; + + /// Add a point to the boundary + void add_point(Ind3D ind, BoutReal x, BoutReal y, BoutReal z, BoutReal length, + char valid, signed char offset) { + if (!bndry_points.empty() && bndry_points.back()._ind() > ind) { + is_sorted = false; + } + bndry_points.emplace_back(ind, RealPoint{x, y, z}, length, valid, offset, localmesh, + _dir); + } + + /// Add a point to the boundary + void add_point(int ix, int iy, int iz, BoutReal x, BoutReal y, BoutReal z, + BoutReal length, char valid, signed char offset) { + add_point(xyz2ind(ix, iy, iz), x, y, z, length, valid, offset); + } + + /// Return `true` if the boundary contains a point at the given index + bool contains(int ix, int iy, int iz) { + ensureSorted(); + return std::ranges::binary_search(bndry_points, xyz2ind(ix, iy, iz), {}, + [](const auto& point) { return point._ind(); }); + } + + /// The direction of the boundary + int dir() const { return _dir; } + + // legacy interface + void first() override { throw BoutException("Legacy interface is not suppored"); } + void next() override { throw BoutException("Legacy interface is not suppored"); } + bool isDone() override { throw BoutException("Legacy interface is not suppored"); } + + auto begin() const { return bndry_points.begin(); } + auto end() const { return bndry_points.end(); } + auto begin() { return bndry_points.begin(); } + auto end() { return bndry_points.end(); } + +private: + friend class Point; + int _dir; + // Vector of points in the boundary + std::vector bndry_points; + Mesh* localmesh; + bool is_sorted{true}; + void ensureSorted() { + if (is_sorted) { + return; + } + std::ranges::sort(bndry_points); + } + Ind3D xyz2ind(int x, int y, int z) const { + const int ny = localmesh->LocalNy; + const int nz = localmesh->LocalNz; + return Ind3D{(((x * ny) + y) * nz) + z, ny, nz}; + } +}; + +/// Boundary region for field-aligned grids +/// +/// FCI grids should use `BoundaryRegionFCI` +/// +/// Template parameter `isXtemp` is `true` for boundaries in X, and `false` for boundaries in Y +template +class BoundaryRegionXY : public BoundaryRegionBase { +public: + /// Iterator over a `BoundaryRegionXY` + class Iterator : public BoundaryRegionIterBase { + private: + const BoundaryRegionXY* region; + size_t pos{0}; + + /// Return the current index displaced by \p offset + Ind3D offsetInd(int offset) const { + if constexpr (isXtemp) { + return _ind().xp(offset); + } else { + return _ind().yp(offset); + } + } + + public: + Iterator() = delete; + Iterator(const BoundaryRegionXY* reg, bool isstart) + : region(reg), pos(isstart ? 0 : reg->rgn.size()) {} + int dir() const { return region->_dir; } + Ind3D ind() const { return _ind(); } + + template + requires utils::is_Field_v + const BoutReal& _at(const T& f, int off) const { + if constexpr (check) { + ASSERT3(_valid() > -off - 2); + } + auto _off = (1 - off) * region->_dir; + return f[offsetInd(_off)]; + } + + template + requires utils::is_Field_v + BoutReal& _at(T& f, int off) const { + if constexpr (check) { + ASSERT3(_valid() > -off - 2); + } + auto _off = (1 - off) * region->_dir; + return f[offsetInd(_off)]; + } + + template + BoutReal _at(const function_accessor auto& f, int off) const { + if constexpr (check) { + ASSERT3(_valid() > -off - 2); + } + auto _off = (1 - off) * region->_dir; + return f(0, offsetInd(_off)); + } + + signed char _offset() const { return region->_dir; } + signed char _valid() const { return region->valid; } + Ind3D _ind() const { return region->rgn[pos]; } + int _boundary_width() const { + if constexpr (isXtemp) { + return region->localmesh->xstart; + } + return region->localmesh->ystart; + } + + BoutReal _length(CELL_LOC loc) const { + // Account for staggered grids + if ((isXtemp and loc == CELL_XLOW) or (not isXtemp and loc == CELL_YLOW)) { + return (dir() == 1) ? 1 : 0; + } + return 0.5; + } + + auto operator<=>(const Iterator& rhs) const { + ASSERT3(region == rhs.region); + return pos <=> rhs.pos; + } + + bool operator==(const Iterator& rhs) const { + ASSERT3(region == rhs.region); + return pos == rhs.pos; + } + + Iterator& operator++() { + ++pos; + return *this; + } + + Iterator& operator*() { return *this; } + }; + + BoundaryRegionXY() = delete; + BoundaryRegionXY(const std::string& name, int dir, Mesh* mesh, const Region& rgn) + : BoundaryRegionBase(name, mesh), _dir(dir), + valid(isXtemp ? mesh->xstart : mesh->ystart) { + BOUT_FOR_SERIAL(i, rgn) { this->rgn.emplace_back(i); } + if constexpr (isXtemp) { + this->isX = true; + location = dir == 1 ? BNDRY_XOUT : BNDRY_XIN; + } else { + this->isY = true; + location = dir == 1 ? BNDRY_YUP : BNDRY_YDOWN; + } + } + int dir() const { return _dir; } + // legacy interface + void first() override { throw BoutException("Legacy interface is not suppored"); } + void next() override { throw BoutException("Legacy interface is not suppored"); } + bool isDone() override { throw BoutException("Legacy interface is not suppored"); } + + auto begin() const { return Iterator(this, true); } + auto end() const { return Iterator(this, false); } + +private: + int _dir; + std::vector rgn; + signed char valid; +}; + +/// Alias for boundary regions over X specifically +using BoundaryRegionX = BoundaryRegionXY; +/// Alias for boundary regions over Y specifically +using BoundaryRegionY = BoundaryRegionXY; + +inline std::shared_ptr +NewBoundaryRegionXIn(const std::string& name, int ymin, int ymax, Mesh* mesh) { + auto pointer = std::make_shared( + name, -1, mesh, + Region(mesh->xstart, mesh->xstart, ymin, ymax, mesh->zstart, mesh->zend, + mesh->LocalNy, mesh->LocalNz, mesh->maxregionblocksize)); + pointer->legacy = std::make_unique<::BoundaryRegionXIn>(name, ymin, ymax, mesh); + return pointer; +} + +inline std::shared_ptr +NewBoundaryRegionXOut(const std::string& name, int ymin, int ymax, Mesh* mesh) { + auto pointer = std::make_shared( + name, 1, mesh, + Region(mesh->xend, mesh->xend, ymin, ymax, mesh->zstart, mesh->zend, + mesh->LocalNy, mesh->LocalNz, mesh->maxregionblocksize)); + pointer->legacy = std::make_unique<::BoundaryRegionXOut>(name, ymin, ymax, mesh); + return pointer; +} + +inline std::shared_ptr +NewBoundaryRegionYUp(const std::string& name, int xmin, int xmax, Mesh* mesh) { + auto pointer = std::make_shared( + name, 1, mesh, + Region(xmin, xmax, mesh->yend, mesh->yend, mesh->zstart, mesh->zend, + mesh->LocalNy, mesh->LocalNz, mesh->maxregionblocksize)); + pointer->legacy = std::make_unique<::BoundaryRegionYUp>(name, xmin, xmax, mesh); + return pointer; +} + +inline std::shared_ptr +NewBoundaryRegionYDown(const std::string& name, int xmin, int xmax, Mesh* mesh) { + auto pointer = std::make_shared( + name, -1, mesh, + Region(xmin, xmax, mesh->ystart, mesh->ystart, mesh->zstart, mesh->zend, + mesh->LocalNy, mesh->LocalNz, mesh->maxregionblocksize)); + pointer->legacy = std::make_unique<::BoundaryRegionYDown>(name, xmin, xmax, mesh); + return pointer; +} + +template +void iter_boundary(const std::shared_ptr& bndrybase, + const Func& func) { + if (bndrybase->isX) { + const auto* const bndry = dynamic_cast(bndrybase.get()); + return iter_boundary(*bndry, func); + } + if (bndrybase->isY) { + const auto* const bndry = dynamic_cast(bndrybase.get()); + return iter_boundary(*bndry, func); + } + if (bndrybase->isParallel) { + const auto* const bndry = dynamic_cast(bndrybase.get()); + return iter_boundary(*bndry, func); + } + throw BoutException("{} is of unknown type - probably a legacy iterator", + bndrybase->label); +} + +template + requires std::derived_from +void iter_boundary(const Bndry& bndry, const Func& func) { + for (auto& point : bndry) { + func(point); + } +} + +/* + * INTERPOLATION and EXTRAPOLATION + */ + +/// Extrapolate a given field to the boundary +template +BoutReal extrapolate_boundary_o1(const Iter& point, const Field3D& f) { + return point.current(f); +} + +/// Extrapolate a given field to the boundary +template +BoutReal extrapolate_boundary_o2(const Iter& point, const Field3D& f) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return extrapolate_boundary_o1(point, f); + } + return point.current(f) * (1 + point.length(f.getLocation())) + - point.prev(f) * point.length(f.getLocation()); +} + +/// Extrapolate a given function to the boundary +template +BoutReal extrapolate_bounday_o1(const Iter& point, const function_accessor auto& func, + [[maybe_unused]] CELL_LOC loc = CELL_CENTRE) { + return point.current(func); +} + +/// Extrapolate a given function to the boundary +template +BoutReal extrapolate_boundary_o2(const Iter& point, const function_accessor auto& func, + CELL_LOC loc = CELL_CENTRE) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return extrapolate_boundary_o1(point, func); + } + return point.current(func) * (1 + point.length(loc)) + - point.prev(func) * point.length(loc); +} + +/// Interpolate a field to the boundary, using the boundary values +template +BoutReal interpolate_boundary_o2(const Iter& point, const Field3D& f) { + return point.current(f) * (1 - point.length(f.getLocation())) + + point.next(f) * point.length(f.getLocation()); +} +/// Interpolate a field to the boundary, using the boundary values +template +BoutReal interpolate_boundary_o2(const Iter& point, const function_accessor auto& func, + CELL_LOC loc = CELL_CENTRE) { + return point.current(func) * (1 - point.length(loc)) + + point.next(func) * point.length(loc); +} +/// Extrapolate to the first boundary value freely +template +BoutReal extrapolate_next_o1(const Iter& point, const Field3D& f) { + return point.current(f); +} +/// Extrapolate to the first boundary value freely +template +BoutReal extrapolate_next_o2(const Iter& point, const Field3D& f) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return extrapolate_next_o1(point, f); + } + return point.current(f) * 2 - point.prev(f); +} + +/// Extrapolate to the first boundary value freely +template +BoutReal extrapolate_next_o1(const Iter& point, const function_accessor auto& func) { + return point.current(func); +} +/// Extrapolate to the first boundary value freely +template +BoutReal extrapolate_next_o2(const Iter& point, const function_accessor auto& func) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return extrapolate_next_o1(func); + } + return point.current(func) * 2 - prev(func); +} + +/// extrapolate the gradient into the boundary +template +BoutReal extrapolate_grad_o1([[maybe_unused]] const Iter& point, + [[maybe_unused]] const Field3D& f) { + return 0; +} +/// extrapolate the gradient into the boundary +template +BoutReal extrapolate_grad_o2(const Iter& point, const Field3D& f) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return extrapolate_grad_o1(point, f); + } + return point.current(f) - point.next(f); +} + +template +BoutReal extrapolate_boundary_free(const Iter& point, const Field3D& f, + BoundaryFreeExtrapolation mode) { + BoutReal fac = BoutNaN; + if (point.valid() > 0) { + fac = limitFreeScale(point.prev(f), point.current(f), mode); + } else { + fac = mode == BoundaryFreeExtrapolation::linear ? 0 : 1; + } + const auto val = point.current(f); + const BoutReal next = mode == BoundaryFreeExtrapolation::linear ? val + fac : val * fac; + return val * point.length(f.getLocation()) + next * (1 - point.length(f.getLocation())); +} + +/* + * APPLY BOUNDARY CONDITIONS + */ + +/// Apply a dirichlet boundary condition +template +void dirichlet_o1(const Iter& point, Field3D& f, BoutReal value) { + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = value; + } +} + +/// Apply a dirichlet boundary condition +template +void dirichlet_o2(const Iter& point, Field3D& f, BoutReal value) { + if (point.length(f.getLocation()) < point.smallValue()) { + return dirichlet_o1(point, f, value); + } + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = parallel_stencil::dirichlet_o2( + i + 1, point.current(f), i + 1 - point.length(f.getLocation()), value); + } +} + +/// Apply a dirichlet boundary condition +template +void dirichlet_o3(const Iter& point, Field3D& f, BoutReal value) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return dirichlet_o2(point, f, value); + } + if (point.length(f.getLocation()) < point.smallValue()) { + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = parallel_stencil::dirichlet_o2( + i + 2, point.prev(f), i + 1 - point.length(f.getLocation()), value); + } + } else { + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = + parallel_stencil::dirichlet_o3(i + 2, point.prev(f), i + 1, point.current(f), + i + 1 - point.length(f.getLocation()), value); + } + } +} + +/// Ensure the value in the boundary is at least `value` +template +void limit_at_least(const Iter& point, Field3D& f, BoutReal value) { + for (int i = 0; i < point.boundary_width(); ++i) { + if (point.at(f, -i) < value) { + point.at(f, -i) = value; + } + } +} + +/// Apply neumann boundary condition, where `value` is the gradient in index space + +// neumann_o1 would give second order convergence, given an appropriate one-sided stencil. +// But in general we do not, and thus for normal C2 stencils, this is 1st order. +template +void neumann_o1(const Iter& point, Field3D& f, BoutReal value) { + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = point.current(f) + value * (i + 1); + } +} + +/// Apply neumann boundary condition, where `value` is the gradient in index space +template +void neumann_o2(const Iter& point, Field3D& f, BoutReal value) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return neumann_o1(point, f, value); + } + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = point.prev(f) + (2 + i) * value; + } +} + +/// Apply neumann boundary condition, where `value` is the gradient in index space +template +void neumann_o3(const Iter& point, Field3D& f, BoutReal value) { + ASSERT3(point.valid() >= 0); + if (point.valid() < 1) { + return neumann_o2(point, f, value); + } + for (int i = 0; i < point.boundary_width(); ++i) { + point.at(f, -i) = + parallel_stencil::neumann_o3(i + 1 - point.length(f.getLocation()), value, i + 1, + point.current(f), 2, point.prev(f)); + } +} + +template +void set_free(const Iter& point, Field3D& f, BoundaryFreeExtrapolation mode) { + BoutReal fac = BoutNaN; + if (point.valid() > 0) { + fac = limitFreeScale(point.prev(f), point.current(f), mode); + } else { + fac = mode == BoundaryFreeExtrapolation::linear ? 0 : 1; + } + auto val = point.current(f); + if (mode == BoundaryFreeExtrapolation::linear) { + for (int i = 0; i < point.boundary_width(); ++i) { + val += fac; + point.at(f, -i) = val; + } + } else { + for (int i = 0; i < point.boundary_width(); ++i) { + val *= fac; + point.at(f, -i) = val; + } + } +} + +} // namespace boundary +} // namespace bout diff --git a/include/bout/boundary_standard.hxx b/include/bout/boundary_standard.hxx index 3cb4b23803..b7848dcf64 100644 --- a/include/bout/boundary_standard.hxx +++ b/include/bout/boundary_standard.hxx @@ -5,9 +5,11 @@ #include "bout/boundary_op.hxx" #include "bout/bout_types.hxx" +#include "bout/sys/expressionparser.hxx" #include "bout/unused.hxx" #include +#include #include /// Dirichlet boundary condition set half way between guard cell and grid cell at 2nd order accuracy diff --git a/include/bout/bout.hxx b/include/bout/bout.hxx index a08696ec66..1c9147ceb6 100644 --- a/include/bout/bout.hxx +++ b/include/bout/bout.hxx @@ -82,6 +82,13 @@ * either by including boutmain.hxx or by including bout/physicsmodel.hxx * and using the BOUTMAIN macro. * + * Outputs + * ------- + * + * Any non-zero return value should halt the simulation. If the return value is + * less than zero, the exit status from BOUT++ is 0, otherwise it is the return + * value of BoutInitialise. + * */ int BoutInitialise(int& argc, char**& argv); diff --git a/include/bout/bout_enum_class.hxx b/include/bout/bout_enum_class.hxx index 585e5b020e..ce088a4628 100644 --- a/include/bout/bout_enum_class.hxx +++ b/include/bout/bout_enum_class.hxx @@ -2,7 +2,7 @@ * Copyright 2019 B.D.Dudson, J.T.Omotani, P.Hill * * Contact Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -22,13 +22,13 @@ #ifndef BOUT_ENUM_CLASS_H #define BOUT_ENUM_CLASS_H -#include "bout/boutexception.hxx" +#include "bout/boutexception.hxx" // IWYU pragma: keep #include "bout/macro_for_each.hxx" -#include "bout/msg_stack.hxx" -#include "bout/options.hxx" +#include "bout/options.hxx" // IWYU pragma: keep -#include -#include +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include // IWYU pragma: keep /// Create some macro magic similar to bout/macro_for_each.hxx, but allowing for the enum /// class name to be passed through to each _call @@ -67,10 +67,10 @@ /// Create an enum class with toString and FromString functions, and an /// Options::as overload to read the enum #define BOUT_ENUM_CLASS(enumname, ...) \ - enum class enumname { __VA_ARGS__ }; \ + enum class enumname : std::uint8_t { __VA_ARGS__ }; \ \ inline std::string toString(enumname e) { \ - AUTO_TRACE(); \ + \ const static std::map toString_map = { \ BOUT_ENUM_CLASS_MAP_ARGS(BOUT_ENUM_CLASS_STR, enumname, __VA_ARGS__)}; \ auto found = toString_map.find(e); \ @@ -81,16 +81,17 @@ } \ \ inline enumname BOUT_MAKE_FROMSTRING_NAME(enumname)(const std::string& s) { \ - AUTO_TRACE(); \ + \ const static std::map fromString_map = { \ BOUT_ENUM_CLASS_MAP_ARGS(BOUT_STR_ENUM_CLASS, enumname, __VA_ARGS__)}; \ auto found = fromString_map.find(s); \ if (found == fromString_map.end()) { \ - std::string valid_values {}; \ + std::string valid_values{}; \ for (auto const& entry : fromString_map) { \ valid_values += std::string(" ") + entry.first; \ } \ - throw BoutException("Did not find enum {:s}. Valid values: {:s}", s, valid_values); \ + throw BoutException("Did not find enum {:s}. Valid values: {:s}", s, \ + valid_values); \ } \ return found->second; \ } \ @@ -104,4 +105,48 @@ return out << toString(e); \ } +/// Create an enum class with toString and FromString functions, and an +/// Options::as overload to read the enum +#define BOUT_ENUM_CLASS_NS(ns, enumname, ...) \ + namespace ns { \ + enum class enumname : std::uint8_t { __VA_ARGS__ }; \ + } \ + \ + inline std::string toString(ns::enumname e) { \ + \ + const static std::map toString_map = { \ + BOUT_ENUM_CLASS_MAP_ARGS(BOUT_ENUM_CLASS_STR, ns::enumname, __VA_ARGS__)}; \ + auto found = toString_map.find(e); \ + if (found == toString_map.end()) { \ + throw BoutException("Did not find enum {:d}", static_cast(e)); \ + } \ + return found->second; \ + } \ + namespace ns { \ + inline enumname BOUT_MAKE_FROMSTRING_NAME(enumname)(const std::string& s) { \ + const static std::map fromString_map = { \ + BOUT_ENUM_CLASS_MAP_ARGS(BOUT_STR_ENUM_CLASS, enumname, __VA_ARGS__)}; \ + auto found = fromString_map.find(s); \ + if (found == fromString_map.end()) { \ + std::string valid_values{}; \ + for (auto const& entry : fromString_map) { \ + valid_values += std::string(" ") + entry.first; \ + } \ + throw BoutException("Did not find enum {:s}. Valid values: {:s}", s, \ + valid_values); \ + } \ + return found->second; \ + } \ + } \ + \ + template <> \ + inline ns::enumname Options::as(const ns::enumname&) const { \ + return ns::BOUT_MAKE_FROMSTRING_NAME(enumname)(this->as()); \ + } \ + namespace ns { \ + inline std::ostream& operator<<(std::ostream& out, const enumname& e) { \ + return out << toString(e); \ + } \ + } + #endif // BOUT_ENUM_CLASS_H diff --git a/include/bout/bout_types.hxx b/include/bout/bout_types.hxx index c1f06fca7c..1d8b459c0c 100644 --- a/include/bout/bout_types.hxx +++ b/include/bout/bout_types.hxx @@ -1,8 +1,8 @@ /************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors + * + * Contact Ben Dudson, dudson2@llnl.gov * - * Contact Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -22,7 +22,10 @@ #ifndef BOUT_TYPES_H #define BOUT_TYPES_H +#include "bout/build_config.hxx" + #include +#include #include /// Size of real numbers @@ -140,4 +143,21 @@ struct enumWrapper { /// Boundary condition function using FuncPtr = BoutReal (*)(BoutReal t, BoutReal x, BoutReal y, BoutReal z); +template +struct Constant { + T val; + struct View { + T v; + View(T v) : v(v) {} + BOUT_HOST_DEVICE T operator()(int) const { return v; } + BOUT_HOST_DEVICE bool hasParallelSlices() const { return false; } + BOUT_HOST_DEVICE int numberParallelSlices() const { return 0; } + BOUT_HOST_DEVICE View yup(int = 0) const { return *this; } + BOUT_HOST_DEVICE View ydown(int = 0) const { return *this; } + + std::optional getRegionID() const { return {}; } + }; + operator View() const { return {val}; } +}; + #endif // BOUT_TYPES_H diff --git a/include/bout/boutcomm.hxx b/include/bout/boutcomm.hxx index 68c7559fee..29bff53087 100644 --- a/include/bout/boutcomm.hxx +++ b/include/bout/boutcomm.hxx @@ -4,9 +4,9 @@ * * ************************************************************************** -* Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu +* Copyright 2010 - 2026 BOUT++ contributors * -* Contact: Ben Dudson, bd512@york.ac.uk +* Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -49,6 +49,8 @@ public: static int rank(); ///< Rank: my processor number static int size(); ///< Size: number of processors + static void abort(int errorcode); ///< MPI abort + // Setting options void setComm(MPI_Comm c); diff --git a/include/bout/boutexception.hxx b/include/bout/boutexception.hxx index 238c88654c..735f98c7d6 100644 --- a/include/bout/boutexception.hxx +++ b/include/bout/boutexception.hxx @@ -1,13 +1,11 @@ #ifndef BOUT_EXCEPTION_H #define BOUT_EXCEPTION_H -#include "bout/build_defines.hxx" - -#include #include #include #include +#include "fmt/base.h" #include "fmt/core.h" /// Throw BoutRhsFail with \p message if any one process has non-zero @@ -16,11 +14,16 @@ void BoutParallelThrowRhsFail(int status, const char* message); class BoutException : public std::exception { public: + BoutException(const BoutException&) = default; + BoutException(BoutException&&) = delete; + BoutException& operator=(const BoutException&) = default; + BoutException& operator=(BoutException&&) = delete; BoutException(std::string msg); - template - BoutException(const S& format, const Args&... args) - : BoutException(fmt::format(format, args...)) {} + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + BoutException(fmt::format_string format, Args&&... args) + : BoutException(fmt::vformat(format, fmt::make_format_args(args...))) {} ~BoutException() override; @@ -30,32 +33,31 @@ public: /// backtrace (if available) std::string getBacktrace() const; + static void enableBacktrace() { show_backtrace = true; } + static void disableBacktrace() { show_backtrace = false; } + private: std::string message; -#if BOUT_USE_BACKTRACE - static constexpr unsigned int TRACE_MAX = 128; - std::array trace{}; - int trace_size; - char** messages; -#endif - void makeBacktrace(); + static bool show_backtrace; }; class BoutRhsFail : public BoutException { public: BoutRhsFail(std::string message) : BoutException(std::move(message)) {} - template - BoutRhsFail(const S& format, const Args&... args) - : BoutRhsFail(fmt::format(format, args...)) {} + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + BoutRhsFail(fmt::format_string format, Args&&... args) + : BoutRhsFail(fmt::vformat(format, fmt::make_format_args(args...))) {} }; class BoutIterationFail : public BoutException { public: BoutIterationFail(std::string message) : BoutException(std::move(message)) {} - template - BoutIterationFail(const S& format, const Args&... args) - : BoutIterationFail(fmt::format(format, args...)) {} + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + BoutIterationFail(fmt::format_string format, Args&&... args) + : BoutIterationFail(fmt::vformat(format, fmt::make_format_args(args...))) {} }; #endif diff --git a/include/bout/build_config.hxx b/include/bout/build_config.hxx index 08158d00e9..0fed934af0 100644 --- a/include/bout/build_config.hxx +++ b/include/bout/build_config.hxx @@ -30,6 +30,7 @@ constexpr auto has_uuid_system_generator = static_cast(BOUT_HAS_UUID_SYSTEM_GENERATOR); constexpr auto has_slepc = static_cast(BOUT_HAS_SLEPC); constexpr auto has_sundials = static_cast(BOUT_HAS_SUNDIALS); +constexpr auto has_sundials_manyvector = static_cast(BOUT_HAS_SUNDIALS_MANYVECTOR); constexpr auto use_backtrace = static_cast(BOUT_USE_BACKTRACE); constexpr auto use_color = static_cast(BOUT_USE_COLOR); constexpr auto use_openmp = static_cast(BOUT_USE_OPENMP); @@ -47,14 +48,59 @@ constexpr auto use_msgstack = static_cast(BOUT_USE_MSGSTACK); #undef STRINGIFY1 #undef STRINGIFY +// NOLINTBEGIN(cppcoreguidelines-macro-usage) +// These defines are used to provide compiler-specific flags #if BOUT_HAS_CUDA && defined(__CUDACC__) #define BOUT_HOST_DEVICE __host__ __device__ #define BOUT_HOST __host__ #define BOUT_DEVICE __device__ +#define BOUT_FORCEINLINE __forceinline__ +#elif defined(_MSC_VER) +#define BOUT_HOST_DEVICE +#define BOUT_HOST +#define BOUT_DEVICE +#define BOUT_FORCEINLINE __forceinline +#elif defined(__clang__) || defined(__GNUC__) +#define BOUT_HOST_DEVICE +#define BOUT_HOST +#define BOUT_DEVICE +#define BOUT_FORCEINLINE inline __attribute__((always_inline)) #else #define BOUT_HOST_DEVICE #define BOUT_HOST #define BOUT_DEVICE +#define BOUT_FORCEINLINE inline +#endif + +#if defined(__has_cpp_attribute) && __has_cpp_attribute(assume) >= 202207L +#define BOUT_ASSUME(condition) [[assume(condition)]] +#elif defined(_MSC_VER) +#define BOUT_ASSUME(condition) __assume(condition) +#elif defined(__clang__) +#if __has_builtin(__builtin_assume) +#define BOUT_ASSUME(condition) __builtin_assume(condition) +#else +#define BOUT_ASSUME(condition) ((void)0) +#endif +#elif defined(__GNUC__) +#define BOUT_ASSUME(condition) \ + do { \ + if (!(condition)) { \ + __builtin_unreachable(); \ + } \ + } while (false) +#else +#define BOUT_ASSUME(condition) ((void)0) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define BOUT_UNREACHABLE() __builtin_unreachable() +#elif defined(_MSC_VER) +#define BOUT_UNREACHABLE() __assume(false) +#else +// Cannot call std::abort in device code +#define BOUT_UNREACHABLE() #endif +// NOLINTEND(cppcoreguidelines-macro-usage) #endif // BOUT_BUILD_OPTIONS_HXX diff --git a/include/bout/christoffel_symbols.hxx b/include/bout/christoffel_symbols.hxx new file mode 100644 index 0000000000..db88b8688e --- /dev/null +++ b/include/bout/christoffel_symbols.hxx @@ -0,0 +1,63 @@ +#ifndef BOUT_CHRISTOFFELSYMBOLS_HXX +#define BOUT_CHRISTOFFELSYMBOLS_HXX + +#include + +class Coordinates; + +class ChristoffelSymbols { + +public: + explicit ChristoffelSymbols(const Coordinates& coordinates); + + const bout::FieldMetric& G1_11() const { return G1_11_m; } + const bout::FieldMetric& G1_22() const { return G1_22_m; } + const bout::FieldMetric& G1_33() const { return G1_33_m; } + const bout::FieldMetric& G1_12() const { return G1_12_m; } + const bout::FieldMetric& G1_13() const { return G1_13_m; } + const bout::FieldMetric& G1_23() const { return G1_23_m; } + + const bout::FieldMetric& G2_11() const { return G2_11_m; } + const bout::FieldMetric& G2_22() const { return G2_22_m; } + const bout::FieldMetric& G2_33() const { return G2_33_m; } + const bout::FieldMetric& G2_12() const { return G2_12_m; } + const bout::FieldMetric& G2_13() const { return G2_13_m; } + const bout::FieldMetric& G2_23() const { return G2_23_m; } + + const bout::FieldMetric& G3_11() const { return G3_11_m; } + const bout::FieldMetric& G3_22() const { return G3_22_m; } + const bout::FieldMetric& G3_33() const { return G3_33_m; } + const bout::FieldMetric& G3_12() const { return G3_12_m; } + const bout::FieldMetric& G3_13() const { return G3_13_m; } + const bout::FieldMetric& G3_23() const { return G3_23_m; } + + // Transforms the ChristoffelSymbols by applying the given function to every element + template + void map(F function) { + G1_11_m = function(G1_11_m); + G1_22_m = function(G1_22_m); + G1_33_m = function(G1_33_m); + G1_12_m = function(G1_12_m); + G1_13_m = function(G1_13_m); + G1_23_m = function(G1_23_m); + G2_11_m = function(G2_11_m); + G2_22_m = function(G2_22_m); + G2_33_m = function(G2_33_m); + G2_12_m = function(G2_12_m); + G2_13_m = function(G2_13_m); + G2_23_m = function(G2_23_m); + G3_11_m = function(G3_11_m); + G3_22_m = function(G3_22_m); + G3_33_m = function(G3_33_m); + G3_12_m = function(G3_12_m); + G3_13_m = function(G3_13_m); + G3_23_m = function(G3_23_m); + } + +private: + bout::FieldMetric G1_11_m, G1_22_m, G1_33_m, G1_12_m, G1_13_m, G1_23_m; + bout::FieldMetric G2_11_m, G2_22_m, G2_33_m, G2_12_m, G2_13_m, G2_23_m; + bout::FieldMetric G3_11_m, G3_22_m, G3_33_m, G3_12_m, G3_13_m, G3_23_m; +}; + +#endif //BOUT_CHRISTOFFELSYMBOLS_HXX diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index d7c80ed8bc..a090dcd959 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -1,18 +1,11 @@ /************************************************************************** * Describes coordinate systems * - * ChangeLog - * ========= - * - * 2014-11-10 Ben Dudson - * * Created by separating metric from Mesh - * - * ************************************************************************** - * Copyright 2014-2025 BOUT++ contributors + * Copyright 2014-2026 BOUT++ contributors * * Contact: Ben Dudson, dudson2@llnl.gov - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -33,25 +26,38 @@ #ifndef BOUT_COORDINATES_H #define BOUT_COORDINATES_H -#include "bout/bout_types.hxx" -#include "bout/field2d.hxx" -#include "bout/field3d.hxx" -#include "bout/paralleltransform.hxx" +#include "bout/field_data.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include class Mesh; +struct MetricNormaliser; + +namespace bout::boundary { +class YBoundary; +} /*! * Represents a coordinate system, and associated operators - * - * This is a container for a collection of metric tensor components */ class Coordinates { public: -#if BOUT_USE_METRIC_3D - using FieldMetric = Field3D; -#else - using FieldMetric = Field2D; -#endif + using FieldMetric = bout::FieldMetric; /// Standard constructor from input Coordinates(Mesh* mesh, Options* options = nullptr); @@ -62,8 +68,8 @@ public: /// force_interpolate_from_centre argument to true to always interpolate /// (useful if CELL_CENTRE Coordinates have been changed, so reading from file /// would not be correct). - Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, - const Coordinates* coords_in, bool force_interpolate_from_centre = false); + Coordinates(Mesh* mesh, Options* options, CELL_LOC loc, const Coordinates* coords_in, + bool force_interpolate_from_centre = false); /// A constructor useful for testing purposes. To use it, inherit /// from Coordinates. If \p calculate_geometry is true (default), @@ -74,53 +80,333 @@ public: FieldMetric g_22, FieldMetric g_33, FieldMetric g_12, FieldMetric g_13, FieldMetric g_23, FieldMetric ShiftTorsion, FieldMetric IntShiftTorsion); - Coordinates& operator=(Coordinates&&) = default; - - ~Coordinates() = default; - /// Add variables to \p output_options, for post-processing void outputVars(Options& output_options); - FieldMetric dx, dy, dz; ///< Mesh spacing in x, y and z + ///< Mesh spacing in x, y and z + const FieldMetric& dx() const { return dx_; } + const FieldMetric& dy() const { return dy_; } + const FieldMetric& dz() const { return dz_; } + + const BoutReal& dx(int x, int y, int z) const { return dx_(x, y, z); } + const BoutReal& dy(int x, int y, int z) const { return dy_(x, y, z); } + const BoutReal& dz(int x, int y, int z) const { return dz_(x, y, z); } + +#if BOUT_USE_METRIC_3D + const BoutReal* dx(int x, int y) const { return dx_(x, y); } + const BoutReal* dy(int x, int y) const { return dy_(x, y); } + const BoutReal* dz(int x, int y) const { return dz_(x, y); } +#else + const BoutReal& dx(int x, int y) const { return dx_(x, y); } + const BoutReal& dy(int x, int y) const { return dy_(x, y); } + const BoutReal& dz(int x, int y) const { return dz_(x, y); } +#endif + + const BoutReal& IntShiftTorsion(int x, int y, int z) const { + return IntShiftTorsion_(x, y, z); + } + +#if not(BOUT_USE_METRIC_3D) + const BoutReal& IntShiftTorsion(int x, int y) const { return IntShiftTorsion_(x, y); } +#endif + + const BoutReal& J(int x, int y, int z) const { return J()(x, y, z); } + +#if not(BOUT_USE_METRIC_3D) + const BoutReal& J(int x, int y) const { return J()(x, y); } +#endif + + const BoutReal& Bxy(int x, int y, int z) const { return Bxy()(x, y, z); } +#if not(BOUT_USE_METRIC_3D) + const BoutReal& Bxy(int x, int y) const { return Bxy()(x, y); } +#endif + + void setDx(FieldMetric dx, bool communicate = true); + void setDy(FieldMetric dy, bool communicate = true); + void setDz(FieldMetric dz, bool communicate = true); + + void setD1_dx(FieldMetric d1_dx) { d1_dx_ = std::move(d1_dx); } + void setD1_dy(FieldMetric d1_dy) { d1_dy_ = std::move(d1_dy); } + void setD1_dz(FieldMetric d1_dz) { d1_dz_ = std::move(d1_dz); } /// Length of the Z domain. Used for FFTs const Field2D& zlength() const; + const BoutReal& zlength(int x, int y) const { return zlength()(x, y); } + /// True if corrections for non-uniform mesh spacing should be included in operators - bool non_uniform; + bool non_uniform() const { return non_uniform_; } + void setNon_uniform(bool non_uniform) { non_uniform_ = non_uniform; } + /// 2nd-order correction for non-uniform meshes d/di(1/dx), d/di(1/dy) and d/di(1/dz) - FieldMetric d1_dx, d1_dy, d1_dz; + const FieldMetric& d1_dx() const { return d1_dx_; } + const FieldMetric& d1_dy() const { return d1_dy_; } + const FieldMetric& d1_dz() const { return d1_dz_; } - FieldMetric J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz +#if BOUT_USE_METRIC_3D + const BoutReal& d1_dx(int x, int y, int z) const { return d1_dx_(x, y, z); } + const BoutReal& d1_dy(int x, int y, int z) const { return d1_dy_(x, y, z); } + const BoutReal& d1_dz(int x, int y, int z) const { return d1_dz_(x, y, z); } +#else + const BoutReal& d1_dx(int x, int y) const { return d1_dx_(x, y); } + const BoutReal& d1_dy(int x, int y) const { return d1_dy_(x, y); } + const BoutReal& d1_dz(int x, int y) const { return d1_dz_(x, y); } +#endif - FieldMetric Bxy; ///< Magnitude of B = nabla z times nabla x + /// Covariant metric tensor + const FieldMetric& g_11() const { return covariantMetricTensor.g11(); } + const FieldMetric& g_22() const { return covariantMetricTensor.g22(); } + const FieldMetric& g_33() const { return covariantMetricTensor.g33(); } + const FieldMetric& g_12() const { return covariantMetricTensor.g12(); } + const FieldMetric& g_13() const { return covariantMetricTensor.g13(); } + const FieldMetric& g_23() const { return covariantMetricTensor.g23(); } + + /// get g_22 at the cell faces; + const FieldMetric& g_22_ylow() const; + const FieldMetric& g_22_yhigh() const; + // Cell Areas + const FieldMetric& cell_area_xlow() const { + if (_cell_area_xlow.has_value()) { + return *_cell_area_xlow; + } + _compute_cell_area_x(); + ASSERT2(_cell_area_xlow.has_value()); + return *_cell_area_xlow; + } + const FieldMetric& cell_area_xhigh() const { + if (_cell_area_xhigh.has_value()) { + return *_cell_area_xhigh; + } + _compute_cell_area_x(); + ASSERT2(_cell_area_xhigh.has_value()); + return *_cell_area_xhigh; + } + const FieldMetric& cell_area_ylow() const { + if (_cell_area_ylow.has_value()) { + return *_cell_area_ylow; + } + _compute_cell_area_y(); + ASSERT2(_cell_area_ylow.has_value()); + return *_cell_area_ylow; + } + const FieldMetric& cell_area_yhigh() const { + if (_cell_area_yhigh.has_value()) { + return *_cell_area_yhigh; + } + _compute_cell_area_y(); + ASSERT2(_cell_area_yhigh.has_value()); + return *_cell_area_yhigh; + } + const FieldMetric& cell_area_zlow() const { + if (_cell_area_zlow.has_value()) { + return *_cell_area_zlow; + } + _compute_cell_area_z(); + ASSERT2(_cell_area_zlow.has_value()); + return *_cell_area_zlow; + } + const FieldMetric& cell_area_zhigh() const { + if (_cell_area_zhigh.has_value()) { + return *_cell_area_zhigh; + } + _compute_cell_area_z(); + ASSERT2(_cell_area_zhigh.has_value()); + return *_cell_area_zhigh; + } + FieldMetric& cell_area_xlow() { + if (_cell_area_xlow.has_value()) { + return *_cell_area_xlow; + } + _compute_cell_area_x(); + ASSERT2(_cell_area_xlow.has_value()); + return *_cell_area_xlow; + } + FieldMetric& cell_area_xhigh() { + if (_cell_area_xhigh.has_value()) { + return *_cell_area_xhigh; + } + _compute_cell_area_x(); + ASSERT2(_cell_area_xhigh.has_value()); + return *_cell_area_xhigh; + } + FieldMetric& cell_area_ylow() { + if (_cell_area_ylow.has_value()) { + return *_cell_area_ylow; + } + _compute_cell_area_y(); + ASSERT2(_cell_area_ylow.has_value()); + return *_cell_area_ylow; + } + FieldMetric& cell_area_yhigh() { + if (_cell_area_yhigh.has_value()) { + return *_cell_area_yhigh; + } + _compute_cell_area_y(); + ASSERT2(_cell_area_yhigh.has_value()); + return *_cell_area_yhigh; + } + FieldMetric& cell_area_zlow() { + if (_cell_area_zlow.has_value()) { + return *_cell_area_zlow; + } + _compute_cell_area_z(); + ASSERT2(_cell_area_zlow.has_value()); + return *_cell_area_zlow; + } + FieldMetric& cell_area_zhigh() { + if (_cell_area_zhigh.has_value()) { + return *_cell_area_zhigh; + } + _compute_cell_area_z(); + ASSERT2(_cell_area_zhigh.has_value()); + return *_cell_area_zhigh; + } + // Cell Volume + const FieldMetric& cell_volume() const { + if (_cell_volume.has_value()) { + return *_cell_volume; + } + _compute_cell_volume(); + ASSERT2(_cell_volume.has_value()); + return *_cell_volume; + } + FieldMetric& cell_volume() { + if (_cell_volume.has_value()) { + return *_cell_volume; + } + _compute_cell_volume(); + ASSERT2(_cell_volume.has_value()); + return *_cell_volume; + } + +private: + mutable std::optional _g_22_ylow, _g_22_yhigh; + mutable std::optional _cell_area_xlow, _cell_area_xhigh; + mutable std::optional _cell_area_ylow, _cell_area_yhigh; + mutable std::optional _cell_area_zlow, _cell_area_zhigh; + mutable std::optional _cell_volume; + void _compute_cell_area_x() const; + void _compute_cell_area_y() const; + void _compute_cell_area_z() const; + void _compute_cell_volume() const; +public: /// Contravariant metric tensor (g^{ij}) - FieldMetric g11, g22, g33, g12, g13, g23; + const FieldMetric& g11() const { return contravariantMetricTensor.g11(); } + const FieldMetric& g22() const { return contravariantMetricTensor.g22(); } + const FieldMetric& g33() const { return contravariantMetricTensor.g33(); } + const FieldMetric& g12() const { return contravariantMetricTensor.g12(); } + const FieldMetric& g13() const { return contravariantMetricTensor.g13(); } + const FieldMetric& g23() const { return contravariantMetricTensor.g23(); } /// Covariant metric tensor - FieldMetric g_11, g_22, g_33, g_12, g_13, g_23; + const BoutReal& g_11(int x, int y, int z) const { + return covariantMetricTensor.g11(x, y, z); + } + const BoutReal& g_22(int x, int y, int z) const { + return covariantMetricTensor.g22(x, y, z); + } + const BoutReal& g_33(int x, int y, int z) const { + return covariantMetricTensor.g33(x, y, z); + } + const BoutReal& g_12(int x, int y, int z) const { + return covariantMetricTensor.g12(x, y, z); + } + const BoutReal& g_13(int x, int y, int z) const { + return covariantMetricTensor.g13(x, y, z); + } + const BoutReal& g_23(int x, int y, int z) const { + return covariantMetricTensor.g23(x, y, z); + } - /// Christoffel symbol of the second kind (connection coefficients) - FieldMetric G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; - FieldMetric G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; - FieldMetric G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; +#if not(BOUT_USE_METRIC_3D) + const BoutReal& g_11(int x, int y) const { return covariantMetricTensor.g11(x, y); } + const BoutReal& g_22(int x, int y) const { return covariantMetricTensor.g22(x, y); } + const BoutReal& g_33(int x, int y) const { return covariantMetricTensor.g33(x, y); } + const BoutReal& g_12(int x, int y) const { return covariantMetricTensor.g12(x, y); } + const BoutReal& g_13(int x, int y) const { return covariantMetricTensor.g13(x, y); } + const BoutReal& g_23(int x, int y) const { return covariantMetricTensor.g23(x, y); } +#endif + + /// Contravariant metric tensor (g^{ij}) + const BoutReal& g11(int x, int y, int z) const { + return contravariantMetricTensor.g11(x, y, z); + } + const BoutReal& g22(int x, int y, int z) const { + return contravariantMetricTensor.g22(x, y, z); + } + const BoutReal& g33(int x, int y, int z) const { + return contravariantMetricTensor.g33(x, y, z); + } + const BoutReal& g12(int x, int y, int z) const { + return contravariantMetricTensor.g12(x, y, z); + } + const BoutReal& g13(int x, int y, int z) const { + return contravariantMetricTensor.g13(x, y, z); + } + const BoutReal& g23(int x, int y, int z) const { + return contravariantMetricTensor.g23(x, y, z); + } + +#if not(BOUT_USE_METRIC_3D) + const BoutReal& g11(int x, int y) const { return contravariantMetricTensor.g11(x, y); } + const BoutReal& g22(int x, int y) const { return contravariantMetricTensor.g22(x, y); } + const BoutReal& g33(int x, int y) const { return contravariantMetricTensor.g33(x, y); } + const BoutReal& g12(int x, int y) const { return contravariantMetricTensor.g12(x, y); } + const BoutReal& g13(int x, int y) const { return contravariantMetricTensor.g13(x, y); } + const BoutReal& g23(int x, int y) const { return contravariantMetricTensor.g23(x, y); } +#endif + + const ContravariantMetricTensor& getContravariantMetricTensor() const { + return contravariantMetricTensor; + } + + const CovariantMetricTensor& getCovariantMetricTensor() const { + return covariantMetricTensor; + } + + void setContravariantMetricTensor(const ContravariantMetricTensor& metric_tensor, + const std::string& region = "RGN_ALL", + bool recalculate_staggered = true, + bool force_interpolate_from_centre = false); + + void setCovariantMetricTensor(const CovariantMetricTensor& metric_tensor, + const std::string& region = "RGN_ALL", + bool recalculate_staggered = true, + bool force_interpolate_from_centre = false); + + void setMetricTensor(const ContravariantMetricTensor& contravariant_metric_tensor, + const CovariantMetricTensor& covariant_metric_tensor); + + void setMetricTensorJB(const ContravariantMetricTensor& contravariant_metric_tensor, + const CovariantMetricTensor& covariant_metric_tensor, + const FieldMetric& J, const FieldMetric& Bxy); + + void communicateMetricTensor(); + + void communicateDz(); + + void normaliseMetric(const MetricNormaliser& norm); - FieldMetric G1, G2, G3; + ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz + const FieldMetric& J() const; + + ///< Magnitude of B = nabla z times nabla x + const FieldMetric& Bxy() const { return Bxy_; } + + void setJ(const FieldMetric& J, bool communicate = true); + + void setBxy(FieldMetric Bxy, bool communicate = true); /// d pitch angle / dx. Needed for vector differentials (Curl) - FieldMetric ShiftTorsion; + const FieldMetric& ShiftTorsion() const { return ShiftTorsion_; } - FieldMetric IntShiftTorsion; ///< Integrated shear (I in BOUT notation) + ///< Integrated shear (I in BOUT notation) + const FieldMetric& IntShiftTorsion() const { return IntShiftTorsion_; } - /// Calculate differential geometry quantities from the metric tensor - int geometry(bool recalculate_staggered = true, - bool force_interpolate_from_centre = false); - /// Invert contravatiant metric to get covariant components - int calcCovariant(const std::string& region = "RGN_ALL"); - /// Invert covariant metric to get contravariant components - int calcContravariant(const std::string& region = "RGN_ALL"); - int jacobian(); ///< Calculate J and Bxy + void setIntShiftTorsion(FieldMetric IntShiftTorsion) { + IntShiftTorsion_ = std::move(IntShiftTorsion); + } /////////////////////////////////////////////////////////// // Parallel transforms @@ -139,127 +425,156 @@ public: return *transform; } - /////////////////////////////////////////////////////////// - // Operators - /////////////////////////////////////////////////////////// + /// Christoffel symbol of the second kind (connection coefficients) + const FieldMetric& G1_11() const { return christoffel_symbols().G1_11(); } + const FieldMetric& G1_22() const { return christoffel_symbols().G1_22(); } + const FieldMetric& G1_33() const { return christoffel_symbols().G1_33(); } + const FieldMetric& G1_12() const { return christoffel_symbols().G1_12(); } + const FieldMetric& G1_13() const { return christoffel_symbols().G1_13(); } + const FieldMetric& G1_23() const { return christoffel_symbols().G1_23(); } + const FieldMetric& G2_11() const { return christoffel_symbols().G2_11(); } + const FieldMetric& G2_22() const { return christoffel_symbols().G2_22(); } + const FieldMetric& G2_33() const { return christoffel_symbols().G2_33(); } + const FieldMetric& G2_12() const { return christoffel_symbols().G2_12(); } + const FieldMetric& G2_13() const { return christoffel_symbols().G2_13(); } + const FieldMetric& G2_23() const { return christoffel_symbols().G2_23(); } + const FieldMetric& G3_11() const { return christoffel_symbols().G3_11(); } + const FieldMetric& G3_22() const { return christoffel_symbols().G3_22(); } + const FieldMetric& G3_33() const { return christoffel_symbols().G3_33(); } + const FieldMetric& G3_12() const { return christoffel_symbols().G3_12(); } + const FieldMetric& G3_13() const { return christoffel_symbols().G3_13(); } + const FieldMetric& G3_23() const { return christoffel_symbols().G3_23(); } + + const FieldMetric& G1() const { return g_values().G1(); } + const FieldMetric& G2() const { return g_values().G2(); } + const FieldMetric& G3() const { return g_values().G3(); } + + const BoutReal& G1(int x, int y, int z) const { return G1()(x, y, z); } + const BoutReal& G2(int x, int y, int z) const { return G2()(x, y, z); } + const BoutReal& G3(int x, int y, int z) const { return G3()(x, y, z); } + +#if not(BOUT_USE_METRIC_3D) + const BoutReal& G1(int x, int y) const { return G1()(x, y); } + const BoutReal& G2(int x, int y) const { return G2()(x, y); } + const BoutReal& G3(int x, int y) const { return G3()(x, y); } +#endif + + const FieldMetric& Grad2_par2_DDY_invSg(CELL_LOC outloc, + const std::string& method) const; + + const FieldMetric& invSg() const; + + const ChristoffelSymbols& christoffel_symbols() const; + + GValues& g_values() const; - FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); - - FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY") const; - - FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); - - Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); - - Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY") const; - - Field3D DDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); - - /// Gradient along magnetic field b.Grad(f) - FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - /// Advection along magnetic field V*b.Grad(f) - FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - /// Divergence along magnetic field Div(b*f) = B.Grad(f/B) - FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - // Second derivative along magnetic field - FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - - Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - // Perpendicular Laplacian operator, using only X-Z derivatives - // NOTE: This might be better bundled with the Laplacian inversion code - // since it makes use of the same coefficients and FFT routines - FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); - Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); - FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); - - // Full parallel Laplacian operator on scalar field - // Laplace_par(f) = Div( b (b dot Grad(f)) ) - FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); - Field3D Laplace_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); - - // Full Laplacian operator on scalar field - FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_conditions = "free_o3", - const std::string& dfdy_dy_region = ""); - Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_conditions = "free_o3", - const std::string& dfdy_dy_region = ""); - - // Full perpendicular Laplacian, in form of inverse of Laplacian operator in LaplaceXY - // solver - Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); + void recalculateAndReset(bool recalculate_staggered, + bool force_interpolate_from_centre); + + FieldMetric recalculateJacobian() const; + + const bout::boundary::YBoundary& + getYBoundary(YBndryType type = YBndryType::sheath) const; private: int nz; // Size of mesh in Z. This is mesh->ngz-1 Mesh* localmesh; + Options* localoptions{nullptr}; CELL_LOC location; + /// True if corrections for non-uniform mesh spacing should be included in operators + bool non_uniform_{}; + + FieldMetric dx_, dy_, dz_; ///< Mesh spacing in x, y and z + + /// 2nd-order correction for non-uniform meshes d/di(1/dx), d/di(1/dy) and d/di(1/dz) + FieldMetric d1_dx_, d1_dy_, d1_dz_; + + /// d pitch angle / dx. Needed for vector differentials (Curl) + FieldMetric ShiftTorsion_; + + ///< Integrated shear (I in BOUT notation) + FieldMetric IntShiftTorsion_; + /// Handles calculation of yup and ydown std::unique_ptr transform{nullptr}; /// Cache variable for `zlength`. Invalidated when - /// `Coordinates::geometry` is called + /// `Coordinates::recalculateAndReset` is called mutable std::unique_ptr zlength_cache{nullptr}; /// Cache variable for Grad2_par2 mutable std::map> Grad2_par2_DDY_invSgCache; mutable std::unique_ptr invSgCache{nullptr}; + ContravariantMetricTensor contravariantMetricTensor; + CovariantMetricTensor covariantMetricTensor; + + /// Christoffel symbol of the second kind (connection coefficients) + mutable std::unique_ptr christoffel_symbols_cache{nullptr}; + + /// `g_values` needs renaming, when we know what the name should be + mutable std::unique_ptr g_values_cache{nullptr}; + + mutable std::unique_ptr jacobian_cache{nullptr}; + + FieldMetric Bxy_; ///< Magnitude of B = nabla z times nabla x + /// Set the parallel (y) transform from the options file. /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); - const FieldMetric& invSg() const; - const FieldMetric& Grad2_par2_DDY_invSg(CELL_LOC outloc, - const std::string& method) const; - // check that covariant tensors are positive (if expected) and finite (always) void checkCovariant(); // check that contravariant tensors are positive (if expected) and finite (always) void checkContravariant(); + void invalidateMetricCaches(); + void invalidateJacobianCaches(); + void invalidateCellGeometryCaches(); + void invalidateAccessorCache() const; + + mutable std::array, 3> ybndrys; + + FieldMetric recalculateBxy() const; + + /// Non-uniform meshes. Need to use DDX, DDY + void correctionForNonUniformMeshes(bool force_interpolate_from_centre); + + void interpolateFromCoordinates(Options* options, const Coordinates* coords_in); + + /// Read quantities with given suffix from `Mesh` + void readFromMesh(Options* options, const std::string& suffix); + + /// Read parallel slices of metric components from `Mesh` + void readParallelMetricComponents(); + +protected: + /// For testing purposes only; inherit and make this public + void splitBxyParallelSlices(); }; -/* -/// Standard coordinate system for tokamak simulations -class TokamakCoordinates : public Coordinates { -public: - TokamakCoordinates(Mesh *mesh) : Coordinates(mesh) { - - } -private: - +namespace bout { +std::string parallelSliceFieldName(std::string_view field, int offset); +} + +/// Represents a way to normalise the coordinate system +/// If a component returns nothing, no normalisation is performed. +/// Coordinate values are divided by the respective component from +/// MetricNormaliser, with the exception of the contravariant metric +/// tensor, which is multiplied by the normalisation factor. +struct MetricNormaliser { + std::optional g = std::nullopt; + std::optional g11 = std::nullopt; + std::optional g22 = std::nullopt; + std::optional g33 = std::nullopt; + std::optional g12 = std::nullopt; + std::optional g13 = std::nullopt; + std::optional g23 = std::nullopt; + std::optional dx = std::nullopt; + std::optional dy = std::nullopt; + std::optional dz = std::nullopt; + std::optional J = std::nullopt; + std::optional Bxy = std::nullopt; }; -*/ #endif // BOUT_COORDINATES_H diff --git a/include/bout/coordinates_accessor.hxx b/include/bout/coordinates_accessor.hxx index 532351d57a..2376ab5039 100644 --- a/include/bout/coordinates_accessor.hxx +++ b/include/bout/coordinates_accessor.hxx @@ -31,7 +31,7 @@ /// -> If Coordinates data is changed, the cache should be cleared /// by calling CoordinatesAccessor::clear() struct CoordinatesAccessor { - CoordinatesAccessor() = delete; + CoordinatesAccessor() {} /// Constructor from Coordinates /// Copies data from coords, doesn't modify it diff --git a/include/bout/cyclic_reduction.hxx b/include/bout/cyclic_reduction.hxx index d4c0920910..cf54b63059 100644 --- a/include/bout/cyclic_reduction.hxx +++ b/include/bout/cyclic_reduction.hxx @@ -47,7 +47,6 @@ //#define DIAGNOSE 1 #include "mpi.h" -#include "bout/msg_stack.hxx" #include "bout/utils.hxx" #include @@ -118,7 +117,6 @@ public: /// @param[in] b Diagonal values. Should have size [nsys][N] /// @param[in] c Right diagonal. Should have size [nsys][N] void setCoefs(const Matrix& a, const Matrix& b, const Matrix& c) { - TRACE("CyclicReduce::setCoefs"); int nsys = std::get<0>(a.shape()); @@ -169,7 +167,7 @@ public: /// @param[in] rhs Matrix storing Values of the rhs for each system /// @param[out] x Matrix storing the result for each system void solve(const Matrix& rhs, Matrix& x) { - TRACE("CyclicReduce::solve"); + ASSERT2(static_cast(std::get<0>(rhs.shape())) == Nsys); ASSERT2(static_cast(std::get<0>(x.shape())) == Nsys); ASSERT2(static_cast(std::get<1>(rhs.shape())) == N); diff --git a/include/bout/dcomplex.hxx b/include/bout/dcomplex.hxx index 75bc9d26ff..2d3e0c5ca7 100644 --- a/include/bout/dcomplex.hxx +++ b/include/bout/dcomplex.hxx @@ -7,12 +7,12 @@ * * 2015-03-09 Ben Dudson * o Removed, redefined in terms of std::complex - * + * ************************************************************************** * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -27,7 +27,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with BOUT++. If not, see . - * + * */ #ifndef BOUT_DCOMPLEX_H #define BOUT_DCOMPLEX_H @@ -37,7 +37,9 @@ using dcomplex = std::complex; -const dcomplex Im(0, 1); // 1i +/// Imaginary unit, ``1i`` +//NOLINTNEXTLINE(readability-identifier-length) +constexpr dcomplex Im{0, 1}; /// Complex type for passing data to/from FORTRAN struct fcmplx { diff --git a/include/bout/deriv_store.hxx b/include/bout/deriv_store.hxx index 6dc44c76ad..7c08802cae 100644 --- a/include/bout/deriv_store.hxx +++ b/include/bout/deriv_store.hxx @@ -29,16 +29,18 @@ #ifndef __DERIV_STORE_HXX__ #define __DERIV_STORE_HXX__ +#include #include #include #include +#include #include +#include "bout/field3d.hxx" #include #include #include -#include #include /// Here we have a templated singleton that is used to store DerivativeFunctions @@ -75,21 +77,14 @@ struct DerivativeStore { } /// Report if store has any registered methods - bool isEmpty() const { - AUTO_TRACE(); - return registeredMethods.empty(); - }; + bool isEmpty() const { return registeredMethods.empty(); }; /// Report if store has any registered methods for specific type determined by key - bool isEmpty(std::size_t key) const { - AUTO_TRACE(); - return registeredMethods.count(key) == 0; - } + bool isEmpty(std::size_t key) const { return registeredMethods.count(key) == 0; } /// Report if store has any registered methods for specific type bool isEmpty(DERIV derivType, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); // Get the key auto key = getKey(direction, stagger, toString(derivType)); @@ -100,7 +95,6 @@ struct DerivativeStore { /// specified derivative type, direction and stagger. std::set getAvailableMethods(DERIV derivType, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); // Get the key auto key = getKey(direction, stagger, toString(derivType)); @@ -115,7 +109,6 @@ struct DerivativeStore { /// specified derivative type, direction and stagger. void listAvailableMethods(DERIV derivType, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); // Introductory information output_info << "Available methods for derivative type '"; @@ -134,7 +127,7 @@ struct DerivativeStore { /// depends on the derivType input. void registerDerivative(standardFunc func, DERIV derivType, DIRECTION direction, STAGGER stagger, std::string methodName) { - AUTO_TRACE(); + const auto key = getKey(direction, stagger, methodName); switch (derivType) { @@ -176,7 +169,7 @@ struct DerivativeStore { /// depends on the derivType input. void registerDerivative(upwindFunc func, DERIV derivType, DIRECTION direction, STAGGER stagger, std::string methodName) { - AUTO_TRACE(); + const auto key = getKey(direction, stagger, methodName); switch (derivType) { @@ -210,14 +203,14 @@ struct DerivativeStore { template void registerDerivative(standardFunc func, Direction direction, Stagger stagger, Method method) { - AUTO_TRACE(); + registerDerivative(func, method.meta.derivType, direction.lookup(), stagger.lookup(), method.meta.key); } template void registerDerivative(upwindFunc func, Direction direction, Stagger stagger, Method method) { - AUTO_TRACE(); + registerDerivative(func, method.meta.derivType, direction.lookup(), stagger.lookup(), method.meta.key); } @@ -231,7 +224,6 @@ struct DerivativeStore { STAGGER stagger = STAGGER::None, DERIV derivType = DERIV::Standard) const { - AUTO_TRACE(); const auto realName = nameLookup( name, defaultMethods.at(getKey(direction, stagger, toString(derivType)))); const auto key = getKey(direction, stagger, realName); @@ -262,20 +254,20 @@ struct DerivativeStore { standardFunc getStandard2ndDerivative(std::string name, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); + return getStandardDerivative(name, direction, stagger, DERIV::StandardSecond); }; standardFunc getStandard4thDerivative(std::string name, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); + return getStandardDerivative(name, direction, stagger, DERIV::StandardFourth); }; flowFunc getFlowDerivative(std::string name, DIRECTION direction, STAGGER stagger = STAGGER::None, DERIV derivType = DERIV::Upwind) const { - AUTO_TRACE(); + const auto realName = nameLookup( name, defaultMethods.at(getKey(direction, stagger, toString(derivType)))); const auto key = getKey(direction, stagger, realName); @@ -305,18 +297,17 @@ struct DerivativeStore { upwindFunc getUpwindDerivative(std::string name, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); + return getFlowDerivative(name, direction, stagger, DERIV::Upwind); }; fluxFunc getFluxDerivative(std::string name, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); + return getFlowDerivative(name, direction, stagger, DERIV::Flux); }; void initialise(Options* options) { - AUTO_TRACE(); // To replicate the existing behaviour we first search for a section called //"dd?" and if the option isn't in there we search a section called "diff" @@ -490,7 +481,7 @@ private: std::string getMethodName(std::string name, DIRECTION direction, STAGGER stagger = STAGGER::None) const { - AUTO_TRACE(); + return name + " (" + toString(direction) + ", " + toString(stagger) + ")"; }; @@ -506,7 +497,7 @@ private: /// methods with the same function interface in the same map, which /// might be nice. std::size_t getKey(DIRECTION direction, STAGGER stagger, std::string key) const { - AUTO_TRACE(); + // Note this key is indepedent of the field type (and hence the // key is the same for 3D/2D fields) as we have to use different // maps to store the different field types as the signature is @@ -524,7 +515,7 @@ private: /// that can be used to account for run-time choices template std::size_t getKey() const { - AUTO_TRACE(); + // Note this key is indepedent of the field type (and hence the // key is the same for 3D/2D fields) as we have to use different // maps to store the different field types as the signature is @@ -533,4 +524,13 @@ private: } }; +template +auto& getStore() { + if constexpr (std::is_same::value) { + return DerivativeStore::getInstance(); + } else { + return DerivativeStore::getInstance(); + } +} + #endif diff --git a/include/bout/derivs.hxx b/include/bout/derivs.hxx index 1c360bb9cd..37cb6e1911 100644 --- a/include/bout/derivs.hxx +++ b/include/bout/derivs.hxx @@ -29,12 +29,15 @@ #ifndef BOUT_DERIVS_H #define BOUT_DERIVS_H +#include "bout/bout_types.hxx" #include "bout/field2d.hxx" #include "bout/field3d.hxx" +#include "bout/metric_tensor.hxx" #include "bout/vector2d.hxx" #include "bout/vector3d.hxx" -#include "bout/bout_types.hxx" +#include +#include ////////// FIRST DERIVATIVES ////////// @@ -66,9 +69,9 @@ Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate first partial derivative in Y /// @@ -82,10 +85,17 @@ Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +template +std::enable_if_t && !bout::utils::is_Field3D_v, const Field3D> +DDY(const E& expr, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDY(Field3D{Field3DParallel{expr}}, outloc, method, region); +} + /// Calculate first partial derivative in Y /// /// \f$\partial / \partial y\f$ @@ -98,9 +108,9 @@ Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate first partial derivative in Z /// @@ -130,9 +140,9 @@ Field3D DDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate first partial derivative in Z /// @@ -146,7 +156,7 @@ Coordinates::FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Vector3D DDZ(const Vector3D& f, CELL_LOC outloc = CELL_DEFAULT, +Vector3D DDZ(const Vector3D& v, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); @@ -162,7 +172,7 @@ Vector3D DDZ(const Vector3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Vector2D DDZ(const Vector2D& f, CELL_LOC outloc = CELL_DEFAULT, +Vector2D DDZ(const Vector2D& v, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); @@ -196,9 +206,9 @@ Field3D D2DX2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate second partial derivative in Y /// @@ -228,9 +238,9 @@ Field3D D2DY2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate second partial derivative in Z /// @@ -260,9 +270,9 @@ Field3D D2DZ2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); ////////// FOURTH DERIVATIVES ////////// @@ -294,9 +304,9 @@ Field3D D4DX4(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate forth partial derivative in Y /// @@ -326,9 +336,9 @@ Field3D D4DY4(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate forth partial derivative in Z /// @@ -358,9 +368,9 @@ Field3D D4DZ4(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// For terms of form v * grad(f) /// @@ -392,10 +402,9 @@ Field3D VDDX(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// For terms of form v * grad(f) /// @@ -410,7 +419,7 @@ Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Field3D VDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D VDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); @@ -427,10 +436,9 @@ Field3D VDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric VDDY(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// For terms of form v * grad(f) /// @@ -462,10 +470,9 @@ Field3D VDDZ(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric VDDZ(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// For terms of form v * grad(f) /// @@ -480,10 +487,9 @@ Coordinates::FieldMetric VDDZ(const Field2D& v, const Field2D& f, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric VDDZ(const Field3D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// for terms of form div(v * f) /// @@ -515,10 +521,9 @@ Field3D FDDX(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// for terms of form div(v * f) /// @@ -533,7 +538,7 @@ Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Field3D FDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D FDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); @@ -550,10 +555,9 @@ Field3D FDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric FDDY(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// for terms of form div(v * f) /// @@ -585,10 +589,9 @@ Field3D FDDZ(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric FDDZ(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate mixed partial derivative in x and y /// @@ -631,11 +634,11 @@ Field3D D2DXDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// (default) then the same as the region for the calculation as a /// whole. If dfdy_region < region in size then this will cause /// errors. -Coordinates::FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY", - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +bout::FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY", + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); /// Calculate mixed partial derivative in x and z /// @@ -665,9 +668,9 @@ Field3D D2DXDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Calculate mixed partial derivative in y and z /// @@ -697,8 +700,8 @@ Field3D D2DYDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::FieldMetric D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); +bout::FieldMetric D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); #endif // BOUT_DERIVS_H diff --git a/include/bout/difops.hxx b/include/bout/difops.hxx index 71053d454a..0b3320c1f1 100644 --- a/include/bout/difops.hxx +++ b/include/bout/difops.hxx @@ -1,11 +1,11 @@ /*!****************************************************************************** * \file difops.hxx - * + * * Differential operators * * Changelog: * - * 2009-01 Ben Dudson + * 2009-01 Ben Dudson * * Added two optional parameters which can be put in any order * These determine the method to use (DIFF_METHOD) * and CELL_LOC location of the result. @@ -15,7 +15,7 @@ * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -30,17 +30,23 @@ * * You should have received a copy of the GNU Lesser General Public License * along with BOUT++. If not, see . - * + * *******************************************************************************/ #ifndef BOUT_DIFOPS_H #define BOUT_DIFOPS_H +#include "bout/bout_enum_class.hxx" +#include "bout/bout_types.hxx" +#include "bout/coordinates.hxx" #include "bout/field2d.hxx" #include "bout/field3d.hxx" +#include "bout/metric_tensor.hxx" -#include "bout/bout_types.hxx" -#include "bout/solver.hxx" +#include +#include + +class Solver; /*! * Parallel derivative (central differencing) in Y @@ -51,14 +57,14 @@ * enabled) * @param[in] method The method to use. The default is set in the options. */ -Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -inline Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc, - DIFF_METHOD method) { +bout::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +inline bout::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc, + DIFF_METHOD method) { return Grad_par(var, outloc, toString(method)); } -Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, +Field3D Grad_par(const Field3DParallel& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); /*! @@ -71,7 +77,7 @@ Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, * Combines the parallel and perpendicular calculation to include * grid-points at the corners. */ -Field3D Grad_parP(const Field3D& apar, const Field3D& f); +Field3D Grad_parP(const Field3D& apar, const Field3DParallel& f); /*! * vpar times parallel derivative along unperturbed B-field (upwinding) @@ -79,7 +85,7 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f); * \f[ * v\mathbf{b}_0 \cdot \nabla f * \f] - * + * * * @param[in] v The velocity in y direction * @param[in] f The scalar field to be differentiated @@ -87,20 +93,21 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f); * @param[in] method The numerical method to use. The default is set in the options * */ -Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +bout::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); -inline Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc, DIFF_METHOD method) { +inline bout::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D Vpar_Grad_par(const Field3DParallel& v, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, - DIFF_METHOD method) { +inline Field3D Vpar_Grad_par(const Field3DParallel& v, const Field3DParallel& f, + CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } @@ -116,18 +123,17 @@ inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc * @param[in] method The numerical method to use * */ -Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +bout::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); -inline Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { +inline bout::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Div_par(f, outloc, toString(method)); } -Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D Div_par(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -inline Field3D Div_par(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { +inline Field3D Div_par(const Field3DParallel& f, CELL_LOC outloc, DIFF_METHOD method) { return Div_par(f, outloc, toString(method)); } @@ -135,22 +141,23 @@ inline Field3D Div_par(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { // Both f and v are interpolated onto cell boundaries // using 2nd order central difference, then multiplied together // to get the flux at the boundary. -Field3D Div_par(const Field3D& f, const Field3D& v); +Field3D Div_par(const Field3DParallel& f, const Field3DParallel& v); // Flux methods. Model divergence of flux: df/dt = Div(v * f) // TODO : Should we add Field2D versions? -Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D Div_par_flux(const Field3DParallel& v, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -inline Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc, - DIFF_METHOD method) { +inline Field3D Div_par_flux(const Field3DParallel& v, const Field3DParallel& f, + CELL_LOC outloc, DIFF_METHOD method) { return Div_par_flux(v, f, outloc, toString(method)); } /*! - * second parallel derivative + * Second parallel derivative: * \f[ - * (\mathbf{b} dot \nabla)(\mathbf{b} dot \nabla) + * (\mathbf{b} \cdot \nabla)(\mathbf{b} \cdot \nabla) * \f] * * Note: For parallel Laplacian use LaplacePar @@ -158,22 +165,22 @@ inline Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc, * @param[in] f The field to be differentiated * @param[in] outloc The cell location of the result */ -Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -inline Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { +bout::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +inline bout::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Grad2_par2(f, outloc, toString(method)); } -Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D Grad2_par2(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -inline Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { +inline Field3D Grad2_par2(const Field3DParallel& f, CELL_LOC outloc, DIFF_METHOD method) { return Grad2_par2(f, outloc, toString(method)); } /*! * Parallel divergence of diffusive flux, K*Grad_par - * + * * \f[ * \nabla \cdot ( \mathbf{b}_0 kY (\mathbf{b}_0 \cdot \nabla) f ) * \f] @@ -181,41 +188,66 @@ inline Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) * @param[in] kY The diffusion coefficient * @param[in] f The field whose gradient drives a flux */ -Coordinates::FieldMetric Div_par_K_Grad_par(BoutReal kY, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); -Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); -Coordinates::FieldMetric Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); -Field3D Div_par_K_Grad_par(const Field2D& kY, const Field3D& f, +bout::FieldMetric Div_par_K_Grad_par(BoutReal kY, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(BoutReal kY, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT); -Field3D Div_par_K_Grad_par(const Field3D& kY, const Field2D& f, +bout::FieldMetric Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field2D& kY, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT); -Field3D Div_par_K_Grad_par(const Field3D& kY, const Field3D& f, +Field3D Div_par_K_Grad_par(const Field3DParallel& kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field3DParallel& kY, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT); + +/// enum class bout::ConductionMethod +/// --------------------------------- +/// +/// Original: +/// Separately averages :math:`K`, :math:`J`, :math:`g_{22}`, and +/// :math:`dy` at the face and then multiplies them together. +/// +/// ProductJK: +/// Uses the same stencil as ``Original`` but averages :math:`J K` +/// together before applying the face gradient. +/// +/// Harmonic: +/// Uses a harmonic average of the half-cell conductances +/// :math:`K J / (g_{22} dy)`. This better matches a series-resistance +/// interpretation of two adjacent half-cells and can give noticeably +/// different results when coefficients or cell sizes vary strongly. +BOUT_ENUM_CLASS_NS(bout, ConductionMethod, Original, ProductJK, Harmonic); + +/// Version with energy flow diagnostic +/// For FCI fields, `flow_ylow` is currently returned as zero. +Field3D +Div_par_K_Grad_par_mod(const Field3DParallel& k, const Field3DParallel& f, + Field3D& flow_ylow, bool bndry_flux = true, + bout::ConductionMethod method = bout::ConductionMethod::Original); /*! * Perpendicular Laplacian operator * * This version only includes terms in X and Z, dropping - * derivatives in Y. This is the inverse operation to - * the Laplacian inversion class. + * derivatives in Y. This is the inverse operation to + * the Laplacian inversion class. * * For the full perpendicular Laplacian, use Laplace_perp */ -Coordinates::FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - bool useFFT = true); +bout::FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); /*! * Perpendicular Laplacian, keeping y derivatives * - * + * */ -Coordinates::FieldMetric -Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +bout::FieldMetric Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -224,16 +256,16 @@ Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, * Parallel Laplacian operator * */ -Coordinates::FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); -Field3D Laplace_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); +bout::FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); +Field3D Laplace_par(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT); /*! * Full Laplacian operator (par + perp) */ -Coordinates::FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); -Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +bout::FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); +Field3D Laplace(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -244,45 +276,43 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); /*! * Terms of form b0 x Grad(phi) dot Grad(A) - * + * */ -Coordinates::FieldMetric b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, - CELL_LOC outloc = CELL_DEFAULT); +bout::FieldMetric b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, + CELL_LOC outloc = CELL_DEFAULT); /*! - * Terms of form + * Terms of form * * \f[ * \mathbf{b}_0 \times \nabla \phi \cdot \nabla A * \f] - * + * * @param[in] phi The scalar potential * @param[in] A The field being advected * @param[in] outloc The cell location where the result is defined. By default the same as A. */ -Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field2D& A, +Field3D b0xGrad_dot_Grad(const Field3DParallel& phi, const Field2D& A, CELL_LOC outloc = CELL_DEFAULT); Field3D b0xGrad_dot_Grad(const Field2D& phi, const Field3D& A, CELL_LOC outloc = CELL_DEFAULT); -Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, +Field3D b0xGrad_dot_Grad(const Field3DParallel& phi, const Field3D& A, CELL_LOC outloc = CELL_DEFAULT); /*! * Poisson bracket methods */ enum class BRACKET_METHOD { - standard, ///< Use b0xGrad_dot_Grad - simple, ///< Keep only terms in X-Z - arakawa, ///< Arakawa method in X-Z (optimised) - ctu, ///< Corner Transport Upwind (CTU) method. Explicit method only, needs the - /// timestep from the solver - arakawa_old ///< Older version, for regression testing of optimised version. + standard, ///< Use b0xGrad_dot_Grad + simple, ///< Keep only terms in X-Z + arakawa, ///< Arakawa method in X-Z + ctu, ///< Corner Transport Upwind (CTU) method. Explicit method only, needs the + /// timestep from the solver }; constexpr BRACKET_METHOD BRACKET_STD = BRACKET_METHOD::standard; constexpr BRACKET_METHOD BRACKET_SIMPLE = BRACKET_METHOD::simple; constexpr BRACKET_METHOD BRACKET_ARAKAWA = BRACKET_METHOD::arakawa; constexpr BRACKET_METHOD BRACKET_CTU = BRACKET_METHOD::ctu; -constexpr BRACKET_METHOD BRACKET_ARAKAWA_OLD = BRACKET_METHOD::arakawa_old; /*! * Compute advection operator terms, which can be cast as @@ -291,18 +321,17 @@ constexpr BRACKET_METHOD BRACKET_ARAKAWA_OLD = BRACKET_METHOD::arakawa_old; * \f[ * [f, g] = (1/B) \mathbf{b}_0 \times \nabla f \cdot \nabla g * \f] - * + * * @param[in] f The potential * @param[in] g The field being advected * @param[in] method The method to use * @param[in] outloc The cell location where the result is defined. Default is the same as g * @param[in] solver Pointer to the time integration solver - * + * */ -Coordinates::FieldMetric bracket(const Field2D& f, const Field2D& g, - BRACKET_METHOD method = BRACKET_STD, - CELL_LOC outloc = CELL_DEFAULT, - Solver* solver = nullptr); +bout::FieldMetric bracket(const Field2D& f, const Field2D& g, + BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); Field3D bracket(const Field2D& f, const Field3D& g, BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method = BRACKET_STD, diff --git a/include/bout/expr.hxx b/include/bout/expr.hxx deleted file mode 100644 index 267af202ed..0000000000 --- a/include/bout/expr.hxx +++ /dev/null @@ -1,208 +0,0 @@ -/************************************************************************** - * - * Operators, and support for template expressions - * - * Originally based on article by Klaus Kreft & Angelika Langer - * http://www.angelikalanger.com/Articles/Cuj/ExpressionTemplates/ExpressionTemplates.htm - * - * Parts adapted from Blitz++ library - * - **************************************************************************/ - -#ifndef BOUT_EXPR_H -#define BOUT_EXPR_H - -#warning expr.hxx is deprecated. Do not use! - -#include -#include -#include - -/// Literal class to capture BoutReal values in expressions -class Literal { -public: - /// Type of this expression - using type = Literal; - - Literal(BoutReal v) : val(v) {} - ~Literal() {} - BoutReal operator()(int x, int y, int z) const { return val; } - -private: - const BoutReal val; -}; - -class Field3DExpr { -public: - using type = Field3D; - - Field3DExpr(const Field3D& f) : data(&f(0, 0, 0)) {} - const BoutReal& operator()(int x, int y, int z) const { - return data[(x * bout::globals::mesh->LocalNy + y) * bout::globals::mesh->LocalNz - + z]; - } - -private: - const BoutReal* data; -}; - -class Field2DExpr { -public: - using type = Field2D; - - Field2DExpr(const Field2D& f) : data(&f(0, 0)) {} - const BoutReal& operator()(int x, int y, int z) const { - return data[x * bout::globals::mesh->LocalNy + y]; - } - -private: - const BoutReal* data; -}; - -/// Expression traits, to convert doubles etc. to Literal - -template -struct exprTraits { - using expr_type = ExprT; -}; - -template <> -struct exprTraits { - using expr_type = Literal; -}; - -template <> -struct exprTraits { - using expr_type = Literal; -}; - -template <> -struct exprTraits { - using expr_type = Literal; -}; - -/////////////////////////////////////////////// -// asExpr: convert objects to expressions - -template -struct asExpr { - using type = T; - static const T& getExpr(const T& x) { return x; } -}; - -template <> -struct asExpr { - using type = Literal; - static const Literal getExpr(const int& x) { return Literal(x); } -}; - -template <> -struct asExpr { - using type = Literal; - static const Literal getExpr(const double& x) { return Literal(x); } -}; - -template <> -struct asExpr { - using type = Literal; - static const Literal getExpr(const float& x) { return Literal(x); } -}; - -template <> -struct asExpr { - using type = Field3DExpr; - static const Field3DExpr getExpr(const Field3D& x) { return Field3DExpr(x); } -}; - -///////////////////////////////////////////////////////////// -// Type promotion. Work out the type of a calculation, -// based on the type of the arguments - -template // If in doubt, convert to Field3D -struct PromoteType { - using type = Field3D; -}; - -///////////////////////////////////////////////////////////// -// Binary expressions - -template -class BinaryExpr { -public: - BinaryExpr(const ExprT1& e1, const ExprT2& e2) : _expr1(e1), _expr2(e2) {} - - // Work out the type of the inputs - using ltype = typename exprTraits::expr_type; - using rtype = typename exprTraits::expr_type; - - /// Type of the resulting expression - using type = typename PromoteType::type; - - BoutReal operator()(int x, int y, int z) const { - return BinOp::apply((_expr1)(x, y, z), (_expr2)(x, y, z)); - } - -private: - ltype const _expr1; - rtype const _expr2; -}; - -template -struct BinaryResult { - using arg1 = typename asExpr::type; - using arg2 = typename asExpr::type; - using type = BinaryExpr; -}; - -/// Binary operator classes - -#define DEFINE_BINARY_OP(name, op) \ - struct name { \ - template \ - static inline T apply(T a, T b) { \ - return a op b; \ - } \ - }; - -DEFINE_BINARY_OP(Add, +) -DEFINE_BINARY_OP(Subtract, -) -DEFINE_BINARY_OP(Multiply, *) -DEFINE_BINARY_OP(Divide, /) - -struct Power { - template - static inline T apply(T a, T b) { - return pow(a, b); - } -}; - -/// Define functions add, mul which use operator structs -#define DEFINE_OVERLOAD_FUNC(name, func) \ - template \ - typename BinaryResult::type func(const ExprT1& e1, \ - const ExprT2& e2) { \ - using type = typename BinaryResult::type; \ - return type(asExpr::getExpr(e1), asExpr::getExpr(e2)); \ - } - -/// Addition of two Expressions -DEFINE_OVERLOAD_FUNC(Add, add); -/// Multiplication of two Expressions -DEFINE_OVERLOAD_FUNC(Multiply, mul); - -/// A function to evaluate expressions -template -const Field3D eval3D(Expr e) { - Field3D result; - result.allocate(); - for (int i = 0; i < bout::globals::mesh->LocalNx; i++) { - for (int j = 0; j < bout::globals::mesh->LocalNy; j++) { - for (int k = 0; k < bout::globals::mesh->LocalNz; k++) { - result(i, j, k) = e(i, j, k); - } - } - } - return result; -} - -#endif // BOUT_EXPR_H diff --git a/include/bout/fft.hxx b/include/bout/fft.hxx index fdec8b7bec..b7d36d2166 100644 --- a/include/bout/fft.hxx +++ b/include/bout/fft.hxx @@ -28,10 +28,15 @@ #ifndef BOUT_FFT_H #define BOUT_FFT_H -#include "bout/dcomplex.hxx" +#include "bout/build_defines.hxx" + #include #include +#include + +#include +class Mesh; class Options; BOUT_ENUM_CLASS(FFT_MEASUREMENT_FLAG, estimate, measure, exhaustive); @@ -111,6 +116,16 @@ Array rfft(const Array& in); /// Expects that `in.size() == (length / 2) + 1` Array irfft(const Array& in, int length); +/// Check simulation is using 1 processor in Z, throw exception if not +/// +/// Generally, FFTs must be done over the full Z domain. Currently, most +/// methods using FFTs don't handle parallelising in Z +#if BOUT_CHECK_LEVEL > 0 +void assertZSerial(const Mesh& mesh, std::string_view name); +#else +inline void assertZSerial([[maybe_unused]] const Mesh& mesh, + [[maybe_unused]] std::string_view name) {} +#endif } // namespace fft } // namespace bout diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 61edff6723..8ab6f09f65 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -3,10 +3,10 @@ * \brief field base class definition for differencing methods * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors + * + * Contact: Ben Dudson, dudson2@llnl.gov * - * Contact: Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -31,19 +31,23 @@ class Field; #include #include +#include #include +#include #include "bout/bout_types.hxx" #include "bout/boutcomm.hxx" #include "bout/boutexception.hxx" +#include "bout/build_config.hxx" #include "bout/field_data.hxx" -#include "bout/msg_stack.hxx" #include "bout/region.hxx" #include "bout/traits.hxx" #include "bout/utils.hxx" #include #include +#include "bout/fieldops.hxx" + class Mesh; /// Base class for scalar fields @@ -127,6 +131,21 @@ public: swap(first.directions, second.directions); } + /// Dummy functions to increase portability + virtual void setRegion([[maybe_unused]] size_t regionID) {} + virtual void setRegion([[maybe_unused]] std::optional regionID) {} + virtual void setRegion([[maybe_unused]] const std::string& region_name) {} + virtual void resetRegion() {} + virtual void resetRegionParallel([[maybe_unused]] bool force) {}; + virtual std::optional getRegionID() const { return {}; } + virtual bool hasParallelSlices() const { return true; } + virtual void calcParallelSlices() {} + virtual void splitParallelSlices() {} + virtual void clearParallelSlices() {} + virtual size_t numberParallelSlices() const { return 0; } + virtual bool areCalcParallelSlicesAllowed() const { return false; } + virtual void disallowCalcParallelSlices() {} + private: /// Labels for the type of coordinate system this field is defined over DirectionTypes directions{YDirectionType::Standard, ZDirectionType::Standard}; @@ -169,8 +188,30 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { #field2, toString((field2).getDirections())); \ } +#define ASSERT1_EXPR_COMPATIBLE(expr1, expr2) \ + if ((expr1).getLocation() != (expr2).getLocation()) { \ + throw BoutException("Error in {:s}:{:d}\nFields at different position:" \ + "`{:s}` at {:s}, `{:s}` at {:s}", \ + __FILE__, __LINE__, #expr1, toString((expr1).getLocation()), \ + #expr2, toString((expr2).getLocation())); \ + } \ + if ((expr1).getMesh() != (expr2).getMesh()) { \ + throw BoutException("Error in {:s}:{:d}\nFields are on different Meshes:" \ + "`{:s}` at {:p}, `{:s}` at {:p}", \ + __FILE__, __LINE__, #expr1, \ + static_cast((expr1).getMesh()), #expr2, \ + static_cast((expr2).getMesh())); \ + } \ + if (!areDirectionsCompatible((expr1).getDirections(), (expr2).getDirections())) { \ + throw BoutException("Error in {:s}:{:d}\nFields at different directions:" \ + "`{:s}` at {:s}, `{:s}` at {:s}", \ + __FILE__, __LINE__, #expr1, toString((expr1).getDirections()), \ + #expr2, toString((expr2).getDirections())); \ + } + #else #define ASSERT1_FIELDS_COMPATIBLE(field1, field2) ; +#define ASSERT1_EXPR_COMPATIBLE(expr1, expr2) ; #endif /// Return an empty shell field of some type derived from Field, with metadata @@ -178,7 +219,8 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { template inline T emptyFrom(const T& f) { static_assert(bout::utils::is_Field_v, "emptyFrom only works on Fields"); - return T(f.getMesh(), f.getLocation(), {f.getDirectionY(), f.getDirectionZ()}) + return T(f.getMesh(), f.getLocation(), + DirectionTypes{f.getDirectionY(), f.getDirectionZ()}, f.getRegionID()) .allocate(); } @@ -239,7 +281,6 @@ namespace bout { template inline void checkFinite(const T& f, const std::string& name = "field", const std::string& rgn = "RGN_ALL") { - AUTO_TRACE(); if (!f.isAllocated()) { throw BoutException("{:s} is not allocated", name); @@ -263,7 +304,6 @@ inline void checkFinite(const T& f, const std::string& name = "field", template inline void checkPositive(const T& f, const std::string& name = "field", const std::string& rgn = "RGN_ALL") { - AUTO_TRACE(); if (!f.isAllocated()) { throw BoutException("{:s} is not allocated", name); @@ -285,6 +325,7 @@ inline void checkPositive(const T& f, const std::string& name = "field", template inline T toFieldAligned(const T& f, const std::string& region = "RGN_ALL") { static_assert(bout::utils::is_Field_v, "toFieldAligned only works on Fields"); + ASSERT3(f.getCoordinates() != nullptr); return f.getCoordinates()->getParallelTransform().toFieldAligned(f, region); } @@ -292,6 +333,7 @@ inline T toFieldAligned(const T& f, const std::string& region = "RGN_ALL") { template inline T fromFieldAligned(const T& f, const std::string& region = "RGN_ALL") { static_assert(bout::utils::is_Field_v, "fromFieldAligned only works on Fields"); + ASSERT3(f.getCoordinates() != nullptr); return f.getCoordinates()->getParallelTransform().fromFieldAligned(f, region); } @@ -307,7 +349,6 @@ inline T fromFieldAligned(const T& f, const std::string& region = "RGN_ALL") { template > inline BoutReal min(const T& f, bool allpe = false, const std::string& rgn = "RGN_NOBNDRY") { - AUTO_TRACE(); checkData(f); @@ -329,6 +370,24 @@ inline BoutReal min(const T& f, bool allpe = false, return result; } +template +inline BoutReal min(const BinaryExpr& f, bool allpe = false, + const std::string& rgn = "RGN_NOBNDRY") { + const auto& region = f.getMesh()->template getRegion(rgn); + const auto reduction_view = + makeReductionView(static_cast::View>(f), + region.getLinearIndices()); + BoutReal result = + bout::reduce::Min::finalize(reduceExpr(reduction_view)); + + if (allpe) { + BoutReal localresult = result; + MPI_Allreduce(&localresult, &result, 1, MPI_DOUBLE, MPI_MIN, BoutComm::get()); + } + + return result; +} + /// Returns true if all elements of \p f over \p region are equal. By /// default only checks the local processor, use \p allpe to check /// globally @@ -392,7 +451,6 @@ inline BoutReal getUniform(const T& f, [[maybe_unused]] bool allpe = false, template > inline BoutReal max(const T& f, bool allpe = false, const std::string& rgn = "RGN_NOBNDRY") { - AUTO_TRACE(); checkData(f); @@ -414,6 +472,24 @@ inline BoutReal max(const T& f, bool allpe = false, return result; } +template +inline BoutReal max(const BinaryExpr& f, bool allpe = false, + const std::string& rgn = "RGN_NOBNDRY") { + const auto& region = f.getMesh()->template getRegion(rgn); + const auto reduction_view = + makeReductionView(static_cast::View>(f), + region.getLinearIndices()); + BoutReal result = + bout::reduce::Max::finalize(reduceExpr(reduction_view)); + + if (allpe) { + BoutReal localresult = result; + MPI_Allreduce(&localresult, &result, 1, MPI_DOUBLE, MPI_MAX, BoutComm::get()); + } + + return result; +} + /// Mean of \p f, excluding the boundary/guard cells by default (can /// be changed with \p rgn argument). /// @@ -426,7 +502,6 @@ inline BoutReal max(const T& f, bool allpe = false, template > inline BoutReal mean(const T& f, bool allpe = false, const std::string& rgn = "RGN_NOBNDRY") { - AUTO_TRACE(); checkData(f); @@ -450,56 +525,252 @@ inline BoutReal mean(const T& f, bool allpe = false, return result / static_cast(count); } +template +inline BoutReal mean(const BinaryExpr& f, bool allpe = false, + const std::string& rgn = "RGN_NOBNDRY") { + const auto& region = f.getMesh()->template getRegion(rgn); + const auto reduction_view = + makeReductionView(static_cast::View>(f), + region.getLinearIndices()); + auto state = reduceExpr(reduction_view); + + if (allpe) { + BoutReal localsum = state.sum; + int localcount = state.count; + MPI_Allreduce(&localsum, &state.sum, 1, MPI_DOUBLE, MPI_SUM, BoutComm::get()); + MPI_Allreduce(&localcount, &state.count, 1, MPI_INT, MPI_SUM, BoutComm::get()); + } + + return bout::reduce::Mean::finalize(state); +} + +namespace bout::op { +struct Pow { + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + return ::pow(L(idx), R(idx)); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal a, BoutReal b) const { + return ::pow(a, b); + } +}; +}; // namespace bout::op + +namespace bout::detail { +template +std::optional getPerpYIndex(const T& value); + +template +std::optional getPerpYIndex(const BinaryExpr& expr); + +template +std::optional getPowRegionID(const Mesh* mesh, const std::string& region_name) { + if constexpr (std::is_same_v) { + return bout::detail::getField3DRegionID(mesh, region_name); + } else { + return std::nullopt; + } +} + +template +auto makePowExpr(const LView& lhs_view, const RView& rhs_view, Mesh* mesh, + CELL_LOC location, DirectionTypes directions, + std::optional regionID, const Region& region, + std::optional yindex = std::nullopt) { + return BinaryExpr{lhs_view, rhs_view, bout::op::Pow{}, + mesh, location, directions, + regionID, region, yindex}; +} +} // namespace bout::detail + /// Exponent: pow(lhs, lhs) is \p lhs raised to the power of \p rhs /// /// This loops over the entire domain, including guard/boundary cells by /// default (can be changed using the \p rgn argument) /// If CHECK >= 3 then the result will be checked for non-finite numbers -template > -T pow(const T& lhs, const T& rhs, const std::string& rgn = "RGN_ALL") { - AUTO_TRACE(); +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + return bout::detail::makePowExpr( + static_cast(lhs), static_cast(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), std::nullopt, + lhs.getMesh()->getRegion2D("RGN_ALL")); +} - ASSERT1(areFieldsCompatible(lhs, rhs)); +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs, const std::string& rgn) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + return bout::detail::makePowExpr( + static_cast(lhs), static_cast(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), std::nullopt, + lhs.getMesh()->getRegion2D(rgn)); +} + +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + auto regionID = lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID()); + return bout::detail::makePowExpr( + static_cast(lhs), static_cast(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), regionID, + (regionID.has_value() ? lhs.getMesh()->getRegion(regionID.value()) + : lhs.getMesh()->getRegion("RGN_ALL")), + bout::detail::getPerpYIndex(lhs)); +} - T result{emptyFrom(lhs)}; +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs, const std::string& rgn) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + return bout::detail::makePowExpr( + static_cast(lhs), static_cast(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), + bout::detail::getPowRegionID(lhs.getMesh(), rgn), + lhs.getMesh()->getRegion(rgn), bout::detail::getPerpYIndex(lhs)); +} - BOUT_FOR(i, result.getRegion(rgn)) { result[i] = ::pow(lhs[i], rhs[i]); } +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + int mesh_nz = lhs.getMesh()->LocalNz; + return bout::detail::makePowExpr( + static_cast(lhs), + static_cast(rhs).setScale(1, mesh_nz), lhs.getMesh(), + lhs.getLocation(), lhs.getDirections(), lhs.getRegionID(), + lhs.getMesh()->getRegion("RGN_ALL"), bout::detail::getPerpYIndex(lhs)); +} - checkData(result); - return result; +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs, const std::string& rgn) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + int mesh_nz = lhs.getMesh()->LocalNz; + return bout::detail::makePowExpr( + static_cast(lhs), + static_cast(rhs).setScale(1, mesh_nz), lhs.getMesh(), + lhs.getLocation(), lhs.getDirections(), + bout::detail::getPowRegionID(lhs.getMesh(), rgn), + lhs.getMesh()->getRegion(rgn), bout::detail::getPerpYIndex(lhs)); } -template > -T pow(const T& lhs, BoutReal rhs, const std::string& rgn = "RGN_ALL") { - AUTO_TRACE(); +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + int mesh_nz = rhs.getMesh()->LocalNz; + return bout::detail::makePowExpr( + static_cast(lhs).setScale(1, mesh_nz), + static_cast(rhs), rhs.getMesh(), rhs.getLocation(), + rhs.getDirections(), rhs.getRegionID(), rhs.getMesh()->getRegion("RGN_ALL"), + bout::detail::getPerpYIndex(rhs)); +} - // Check if the inputs are allocated - checkData(lhs); - checkData(rhs); +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr> +pow(const L& lhs, const R& rhs, const std::string& rgn) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + int mesh_nz = rhs.getMesh()->LocalNz; + return bout::detail::makePowExpr( + static_cast(lhs).setScale(1, mesh_nz), + static_cast(rhs), rhs.getMesh(), rhs.getLocation(), + rhs.getDirections(), bout::detail::getPowRegionID(rhs.getMesh(), rgn), + rhs.getMesh()->getRegion(rgn), bout::detail::getPerpYIndex(rhs)); +} - T result{emptyFrom(lhs)}; +template +std::enable_if_t && is_expr_constant_v, + BinaryExpr, bout::op::Pow>> +pow(const L& lhs, R rhs) { + return bout::detail::makePowExpr>( + static_cast(lhs), static_cast::View>(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), std::nullopt, + lhs.getMesh()->getRegion2D("RGN_ALL")); +} - BOUT_FOR(i, result.getRegion(rgn)) { result[i] = ::pow(lhs[i], rhs); } +template +std::enable_if_t && is_expr_constant_v, + BinaryExpr, bout::op::Pow>> +pow(const L& lhs, R rhs, const std::string& rgn) { + return bout::detail::makePowExpr>( + static_cast(lhs), static_cast::View>(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), std::nullopt, + lhs.getMesh()->getRegion2D(rgn)); +} - checkData(result); - return result; +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr, R, bout::op::Pow>> +pow(L lhs, const R& rhs) { + return bout::detail::makePowExpr, R>( + static_cast::View>(lhs), static_cast(rhs), + rhs.getMesh(), rhs.getLocation(), rhs.getDirections(), std::nullopt, + rhs.getMesh()->getRegion2D("RGN_ALL")); } -template > -T pow(BoutReal lhs, const T& rhs, const std::string& rgn = "RGN_ALL") { - AUTO_TRACE(); +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr, R, bout::op::Pow>> +pow(L lhs, const R& rhs, const std::string& rgn) { + return bout::detail::makePowExpr, R>( + static_cast::View>(lhs), static_cast(rhs), + rhs.getMesh(), rhs.getLocation(), rhs.getDirections(), std::nullopt, + rhs.getMesh()->getRegion2D(rgn)); +} - // Check if the inputs are allocated - checkData(lhs); - checkData(rhs); +template +std::enable_if_t && is_expr_constant_v, + BinaryExpr, bout::op::Pow>> +pow(const L& lhs, R rhs) { + return bout::detail::makePowExpr>( + static_cast(lhs), static_cast::View>(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), lhs.getRegionID(), + lhs.getMesh()->getRegion("RGN_ALL"), bout::detail::getPerpYIndex(lhs)); +} - // Define and allocate the output result - T result{emptyFrom(rhs)}; +template +std::enable_if_t && is_expr_constant_v, + BinaryExpr, bout::op::Pow>> +pow(const L& lhs, R rhs, const std::string& rgn) { + return bout::detail::makePowExpr>( + static_cast(lhs), static_cast::View>(rhs), + lhs.getMesh(), lhs.getLocation(), lhs.getDirections(), + bout::detail::getPowRegionID(lhs.getMesh(), rgn), + lhs.getMesh()->getRegion(rgn), bout::detail::getPerpYIndex(lhs)); +} - BOUT_FOR(i, result.getRegion(rgn)) { result[i] = ::pow(lhs, rhs[i]); } +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr, R, bout::op::Pow>> +pow(L lhs, const R& rhs) { + return bout::detail::makePowExpr, R>( + static_cast::View>(lhs), static_cast(rhs), + rhs.getMesh(), rhs.getLocation(), rhs.getDirections(), rhs.getRegionID(), + rhs.getMesh()->getRegion("RGN_ALL"), bout::detail::getPerpYIndex(rhs)); +} - checkData(result); - return result; +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr, R, bout::op::Pow>> +pow(L lhs, const R& rhs, const std::string& rgn) { + return bout::detail::makePowExpr, R>( + static_cast::View>(lhs), static_cast(rhs), + rhs.getMesh(), rhs.getLocation(), rhs.getDirections(), + bout::detail::getPowRegionID(rhs.getMesh(), rgn), + rhs.getMesh()->getRegion(rgn), bout::detail::getPerpYIndex(rhs)); } /*! @@ -518,23 +789,172 @@ T pow(BoutReal lhs, const T& rhs, const std::string& rgn = "RGN_ALL") { * result for non-finite numbers * */ +class Field3DParallel; +class FieldPerp; + +namespace bout::detail { +template +using UnaryFieldResult_t = + std::conditional_t, ::Field3DParallel>, ::Field3D, + std::decay_t>; + +template +std::optional getUnaryRegionID(const Mesh* mesh, const std::string& region_name) { + if constexpr (std::is_same_v, ::Field3D>) { + return bout::detail::getField3DRegionID(mesh, region_name); + } else { + return std::nullopt; + } +} + +template +std::optional getPerpYIndex(const T& value) { + if constexpr (std::is_same_v, ::FieldPerp>) { + return value.getIndex(); + } else { + return std::nullopt; + } +} + +template +std::optional getPerpYIndex(const BinaryExpr& expr) { + if constexpr (std::is_same_v) { + return expr.getIndex(); + } else { + return std::nullopt; + } +} +} // namespace bout::detail + #ifdef FIELD_FUNC #error This macro has already been defined #else -#define FIELD_FUNC(name, func) \ - template > \ - inline T name(const T& f, const std::string& rgn = "RGN_ALL") { \ - AUTO_TRACE(); \ - /* Check if the input is allocated */ \ - checkData(f); \ - /* Define and allocate the output result */ \ - T result{emptyFrom(f)}; \ - BOUT_FOR(d, result.getRegion(rgn)) { result[d] = func(f[d]); } \ - checkData(result); \ - return result; \ +#define FIELD_FUNC(name, func) \ + namespace bout::op { \ + struct name { \ + template \ + BOUT_HOST_DEVICE BoutReal operator()(int idx, const LView& L, const RView&) const { \ + return func(L(idx)); \ + } \ + }; \ + }; \ + template > \ + inline auto name(const T& f, const std::string& rgn = "RGN_ALL") { \ + using ResT = bout::detail::UnaryFieldResult_t; \ + return BinaryExpr{ \ + static_cast(f), \ + static_cast(f), \ + bout::op::name{}, \ + f.getMesh(), \ + f.getLocation(), \ + f.getDirections(), \ + bout::detail::getUnaryRegionID(f.getMesh(), rgn), \ + f.getMesh()->template getRegion(rgn), \ + bout::detail::getPerpYIndex(f)}; \ + } \ + template \ + inline auto name(const BinaryExpr& f) { \ + using UnaryResT = bout::detail::UnaryFieldResult_t; \ + return BinaryExpr, \ + BinaryExpr, bout::op::name>{ \ + static_cast::View>(f), \ + static_cast::View>(f), \ + bout::op::name{}, \ + f.getMesh(), \ + f.getLocation(), \ + f.getDirections(), \ + f.getRegionID(), \ + f.indices, \ + bout::detail::getPerpYIndex(f)}; \ + } \ + template \ + inline auto name(const BinaryExpr& f, const std::string& rgn) { \ + using UnaryResT = bout::detail::UnaryFieldResult_t; \ + return BinaryExpr, \ + BinaryExpr, bout::op::name>{ \ + static_cast::View>(f), \ + static_cast::View>(f), \ + bout::op::name{}, \ + f.getMesh(), \ + f.getLocation(), \ + f.getDirections(), \ + bout::detail::getUnaryRegionID(f.getMesh(), rgn), \ + f.getMesh()->template getRegion(rgn), \ + bout::detail::getPerpYIndex(f)}; \ } #endif +namespace bout::op { +struct Square { + template + BOUT_HOST_DEVICE BoutReal operator()(int idx, const LView& L, const RView&) const { + const BoutReal value = L(idx); + return ::SQ(value); + } +}; + +struct Floor { + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + const BoutReal value = L(idx); + const BoutReal floor_value = R(idx); + return value < floor_value ? floor_value : value; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal value, + BoutReal floor_value) const { + return value < floor_value ? floor_value : value; + } +}; +}; // namespace bout::op + +template > +inline auto SQ(const T& f, const std::string& rgn = "RGN_ALL") { + using ResT = bout::detail::UnaryFieldResult_t; + return BinaryExpr{ + static_cast(f), + static_cast(f), + bout::op::Square{}, + f.getMesh(), + f.getLocation(), + f.getDirections(), + bout::detail::getUnaryRegionID(f.getMesh(), rgn), + f.getMesh()->template getRegion(rgn), + bout::detail::getPerpYIndex(f)}; +} + +template +inline auto SQ(const BinaryExpr& f) { + using UnaryResT = bout::detail::UnaryFieldResult_t; + return BinaryExpr, BinaryExpr, + bout::op::Square>{ + static_cast::View>(f), + static_cast::View>(f), + bout::op::Square{}, + f.getMesh(), + f.getLocation(), + f.getDirections(), + f.getRegionID(), + f.indices, + bout::detail::getPerpYIndex(f)}; +} + +template +inline auto SQ(const BinaryExpr& f, const std::string& rgn) { + using UnaryResT = bout::detail::UnaryFieldResult_t; + return BinaryExpr, BinaryExpr, + bout::op::Square>{ + static_cast::View>(f), + static_cast::View>(f), + bout::op::Square{}, + f.getMesh(), + f.getLocation(), + f.getDirections(), + bout::detail::getUnaryRegionID(f.getMesh(), rgn), + f.getMesh()->template getRegion(rgn), + bout::detail::getPerpYIndex(f)}; +} + /// Square root of \p f over region \p rgn /// /// This loops over the entire domain, including guard/boundary cells by @@ -560,7 +980,7 @@ FIELD_FUNC(exp, ::exp) /// Natural logarithm of \p f over region \p rgn, inverse of /// exponential /// -/// \f$\ln(\exp(f)) = f\f$ +/// \f[\ln(\exp(f)) = f\f] /// /// This loops over the entire domain, including guard/boundary cells by /// default (can be changed using the rgn argument) @@ -632,7 +1052,6 @@ FIELD_FUNC(tanh, ::tanh) /// default (can be changed using the \p rgn argument template > inline bool finite(const T& f, const std::string& rgn = "RGN_ALL") { - AUTO_TRACE(); if (!f.isAllocated()) { return false; @@ -656,6 +1075,8 @@ T copy(const T& f) { return result; } +class Field3DParallel; + /// Apply a floor value \p f to a field \p var. Any value lower than /// the floor is set to the floor. /// @@ -663,17 +1084,51 @@ T copy(const T& f) { /// @param[in] f The floor value /// @param[in] rgn The region to calculate the result over template > -inline T floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { - checkData(var); - T result = copy(var); +inline auto floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { + using ResT = bout::detail::UnaryFieldResult_t; + return BinaryExpr, bout::op::Floor>{ + static_cast(var), + static_cast::View>(f), + bout::op::Floor{}, + var.getMesh(), + var.getLocation(), + var.getDirections(), + bout::detail::getUnaryRegionID(var.getMesh(), rgn), + var.getMesh()->template getRegion(rgn), + bout::detail::getPerpYIndex(var)}; +} - BOUT_FOR(d, var.getRegion(rgn)) { - if (result[d] < f) { - result[d] = f; - } - } +template +inline auto floor(const BinaryExpr& var, BoutReal f) { + using UnaryResT = bout::detail::UnaryFieldResult_t; + return BinaryExpr, Constant, + bout::op::Floor>{ + static_cast::View>(var), + static_cast::View>(f), + bout::op::Floor{}, + var.getMesh(), + var.getLocation(), + var.getDirections(), + var.getRegionID(), + var.indices, + bout::detail::getPerpYIndex(var)}; +} - return result; +template +inline auto floor(const BinaryExpr& var, BoutReal f, + const std::string& rgn) { + using UnaryResT = bout::detail::UnaryFieldResult_t; + return BinaryExpr, Constant, + bout::op::Floor>{ + static_cast::View>(var), + static_cast::View>(f), + bout::op::Floor{}, + var.getMesh(), + var.getLocation(), + var.getDirections(), + bout::detail::getUnaryRegionID(var.getMesh(), rgn), + var.getMesh()->template getRegion(rgn), + bout::detail::getPerpYIndex(var)}; } #undef FIELD_FUNC diff --git a/include/bout/field2d.hxx b/include/bout/field2d.hxx index 92658f1bbf..13a26faa38 100644 --- a/include/bout/field2d.hxx +++ b/include/bout/field2d.hxx @@ -4,9 +4,9 @@ * \brief Definition of 2D scalar field class * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -24,6 +24,8 @@ * along with BOUT++. If not, see . * */ +#include "bout/utils.hxx" +#include class Field2D; #pragma once @@ -31,12 +33,23 @@ class Field2D; #define BOUT_FIELD2D_H #include "bout/array.hxx" +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" #include "bout/build_config.hxx" +#include "bout/build_defines.hxx" #include "bout/field.hxx" #include "bout/field_data.hxx" #include "bout/fieldperp.hxx" #include "bout/region.hxx" -#include "bout/unused.hxx" + +#include +#include +#include +#include +#include + +#include "bout/fieldops.hxx" #if BOUT_HAS_RAJA #include "RAJA/RAJA.hpp" // using RAJA lib @@ -45,6 +58,15 @@ class Field2D; class Field3D; class Mesh; +template +struct is_expr_field2d> + : std::integral_constant> + && is_expr_field2d_v>) + || (is_expr_constant_v> + && is_expr_field2d_v>) + || (is_expr_field2d_v> + && is_expr_constant_v>)> {}; + /*! * \brief 2D X-Y scalar fields * @@ -66,7 +88,8 @@ public: */ Field2D(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Average}); + ZDirectionType::Average}, + std::optional regionID = {}); /*! * Copy constructor. After this both fields @@ -91,6 +114,14 @@ public: DirectionTypes directions_in = {YDirectionType::Standard, ZDirectionType::Average}); + template < + typename ResT, typename L, typename R, typename Func, + typename = std::enable_if_t<(is_expr_field2d_v && is_expr_field2d_v) + || (is_expr_constant_v && is_expr_field2d_v) + || (is_expr_field2d_v && is_expr_constant_v)>> + Field2D(const BinaryExpr& expr) + : Field2D(evaluateBinaryExpr(expr), expr.getMesh(), expr.getLocation(), + expr.getDirections()) {} /*! * Destructor */ @@ -133,21 +164,14 @@ public: return *this; } - /// Check if this field has yup and ydown fields - bool hasParallelSlices() const { return true; } - - Field2D& yup(std::vector::size_type UNUSED(index) = 0) { return *this; } - const Field2D& yup(std::vector::size_type UNUSED(index) = 0) const { - return *this; - } + Field2D& yup([[maybe_unused]] size_t index = 0) { return *this; } + const Field2D& yup([[maybe_unused]] size_t index = 0) const { return *this; } - Field2D& ydown(std::vector::size_type UNUSED(index) = 0) { return *this; } - const Field2D& ydown(std::vector::size_type UNUSED(index) = 0) const { - return *this; - } + Field2D& ydown([[maybe_unused]] size_t index = 0) { return *this; } + const Field2D& ydown([[maybe_unused]] size_t index = 0) const { return *this; } - Field2D& ynext(int UNUSED(dir)) { return *this; } - const Field2D& ynext(int UNUSED(dir)) const { return *this; } + Field2D& ynext([[maybe_unused]] int dir) { return *this; } + const Field2D& ynext([[maybe_unused]] int dir) const { return *this; } // Operators @@ -166,6 +190,21 @@ public: */ Field2D& operator=(BoutReal rhs); + template + std::enable_if_t, Field2D&> + operator=(const BinaryExpr& expr) { + if (!isAllocated() || getMesh() != expr.getMesh()) { + *this = Field2D{expr}; + return *this; + } + + setLocation(expr.getLocation()); + setDirections(expr.getDirections()); + allocate(); + expr.evaluate(&data[0]); + return *this; + } + ///////////////////////////////////////////////////////// // Data access @@ -209,7 +248,7 @@ public: } #endif - return data[jx * ny + jy]; + return data[(jx * ny) + jy]; } inline const BoutReal& operator()(int jx, int jy) const { #if CHECK > 2 && !BOUT_HAS_CUDA @@ -223,38 +262,49 @@ public: } #endif - return data[jx * ny + jy]; + return data[(jx * ny) + jy]; } /*! * DIrect access to underlying array. This version is for compatibility * with Field3D objects */ - BoutReal& operator()(int jx, int jy, int UNUSED(jz)) { return operator()(jx, jy); } - const BoutReal& operator()(int jx, int jy, int UNUSED(jz)) const { + BoutReal& operator()(int jx, int jy, [[maybe_unused]] int jz) { + return operator()(jx, jy); + } + const BoutReal& operator()(int jx, int jy, [[maybe_unused]] int jz) const { return operator()(jx, jy); } - /// In-place addition. Copy-on-write used if data is shared + Field2D& operator*=(const Field2D& rhs); + Field2D& operator/=(const Field2D& rhs); Field2D& operator+=(const Field2D& rhs); - /// In-place addition. Copy-on-write used if data is shared - Field2D& operator+=(BoutReal rhs); - /// In-place subtraction. Copy-on-write used if data is shared Field2D& operator-=(const Field2D& rhs); - /// In-place subtraction. Copy-on-write used if data is shared - Field2D& operator-=(BoutReal rhs); - /// In-place multiplication. Copy-on-write used if data is shared - Field2D& operator*=(const Field2D& rhs); - /// In-place multiplication. Copy-on-write used if data is shared Field2D& operator*=(BoutReal rhs); - /// In-place division. Copy-on-write used if data is shared - Field2D& operator/=(const Field2D& rhs); - /// In-place division. Copy-on-write used if data is shared Field2D& operator/=(BoutReal rhs); + Field2D& operator+=(BoutReal rhs); + Field2D& operator-=(BoutReal rhs); - // FieldData virtual functions +#define FIELD2D_OP_EQUALS(OP_SYM) \ + template \ + std::enable_if_t || is_expr_constant_v, Field2D&> \ + operator OP_SYM## = (R rhs) { \ + if (data.unique()) { \ + auto expr = (*this)OP_SYM rhs; \ + expr.evaluate(&data[0]); \ + } else { \ + (*this) = (*this)OP_SYM rhs; \ + } \ + return *this; \ + } + + FIELD2D_OP_EQUALS(+) + FIELD2D_OP_EQUALS(-) + FIELD2D_OP_EQUALS(*) + FIELD2D_OP_EQUALS(/) - bool is3D() const override { return false; } + // FieldData virtual functions + FieldType field_type() const override { return FieldType::field2d; } #if CHECK > 0 void doneComms() override { bndry_xin = bndry_xout = bndry_yup = bndry_ydown = true; } @@ -272,11 +322,57 @@ public: void applyTDerivBoundary() override; void setBoundaryTo(const Field2D& f2d); ///< Copy the boundary region + void swapData(Field2D& other); friend void swap(Field2D& first, Field2D& second) noexcept; - int size() const override { return nx * ny; }; + int size() const override { return nx * ny; } + + /// Return a field that can be used to perform parallel (Y) derivatives. + /// This is used to write generic FA/FCI code. + Field2D& asField3DParallel() { return *this; } + const Field2D& asField3DParallel() const { return *this; } + + struct View { + BoutReal* data; + int mul = 1; + int div = 1; + + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx) const { + return data[(idx * mul / div)]; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal& operator[](int idx) const { + return data[(idx * mul) / div]; + } + + View& setScale(int mul, int div) { + this->mul = mul; + this->div = div; + return *this; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE bool hasParallelSlices() const { return false; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int numberParallelSlices() const { return 0; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE View yup(int = 0) const { return *this; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE View ydown(int = 0) const { return *this; } + + std::optional getRegionID() const { return {}; } + }; + operator View() { return View{&data[0]}; } + operator View() const { return View{const_cast(&data[0])}; } + + BOUT_DEVICE inline BoutReal operator()(int i) { return View()(i); } + BOUT_DEVICE inline BoutReal operator()(int i) const { return View()(i); } private: + template + static Array evaluateBinaryExpr(const BinaryExpr& expr) { + const auto* mesh = expr.getMesh(); + ASSERT1(mesh != nullptr); + + Array data{mesh->LocalNx * mesh->LocalNy}; + expr.evaluate(&data[0]); + return data; + } + /// Internal data array. Handles allocation/freeing of memory Array data; @@ -288,42 +384,192 @@ private: }; // Non-member overloaded operators +FieldPerp operator+(const Field2D& lhs, const FieldPerp& rhs); +FieldPerp operator-(const Field2D& lhs, const FieldPerp& rhs); +FieldPerp operator*(const Field2D& lhs, const FieldPerp& rhs); +FieldPerp operator/(const Field2D& lhs, const FieldPerp& rhs); + +#define FIELD2D_FIELD2D_FIELD2D_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_field2d_v, \ + BinaryExpr> \ + operator OP_SYM(const L& lhs, const R& rhs) { \ + return BinaryExpr{ \ + static_cast(lhs), \ + static_cast(rhs), \ + bout::op::OP_TYPE{}, \ + lhs.getMesh(), \ + lhs.getLocation(), \ + lhs.getDirections(), \ + std::nullopt, \ + lhs.getMesh()->getRegion2D("RGN_ALL")}; \ + } -Field2D operator+(const Field2D& lhs, const Field2D& rhs); -Field2D operator-(const Field2D& lhs, const Field2D& rhs); -Field2D operator*(const Field2D& lhs, const Field2D& rhs); -Field2D operator/(const Field2D& lhs, const Field2D& rhs); +FIELD2D_FIELD2D_FIELD2D_OP(+, Add) +FIELD2D_FIELD2D_FIELD2D_OP(-, Sub) +FIELD2D_FIELD2D_FIELD2D_OP(*, Mul) +FIELD2D_FIELD2D_FIELD2D_OP(/, Div) + +#define FIELD3D_FIELD2D_FIELD3D_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_field3d_v, \ + BinaryExpr> \ + operator OP_SYM(const L& lhs, const R& rhs) { \ + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); \ + auto regionID = rhs.getRegionID(); \ + int mesh_nz = rhs.getMesh()->LocalNz; \ + return BinaryExpr{ \ + static_cast(lhs).setScale(1, mesh_nz), \ + static_cast(rhs), \ + bout::op::OP_TYPE{}, \ + rhs.getMesh(), \ + rhs.getLocation(), \ + rhs.getDirections(), \ + regionID, \ + rhs.getMesh()->getRegion("RGN_ALL")}; \ + } -Field3D operator+(const Field2D& lhs, const Field3D& rhs); -Field3D operator-(const Field2D& lhs, const Field3D& rhs); -Field3D operator*(const Field2D& lhs, const Field3D& rhs); -Field3D operator/(const Field2D& lhs, const Field3D& rhs); +FIELD3D_FIELD2D_FIELD3D_OP(+, Add) +FIELD3D_FIELD2D_FIELD3D_OP(-, Sub) +FIELD3D_FIELD2D_FIELD3D_OP(*, Mul) +FIELD3D_FIELD2D_FIELD3D_OP(/, Div) + +#define FIELD2D_FIELD2D_BOUTREAL_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_constant_v, \ + BinaryExpr, bout::op::OP_TYPE>> \ + operator OP_SYM(const L& lhs, R rhs) { \ + return BinaryExpr, bout::op::OP_TYPE>{ \ + static_cast(lhs), \ + static_cast::View>(rhs), \ + bout::op::OP_TYPE{}, \ + lhs.getMesh(), \ + lhs.getLocation(), \ + lhs.getDirections(), \ + std::nullopt, \ + lhs.getMesh()->getRegion2D("RGN_ALL")}; \ + } -Field2D operator+(const Field2D& lhs, BoutReal rhs); -Field2D operator-(const Field2D& lhs, BoutReal rhs); -Field2D operator*(const Field2D& lhs, BoutReal rhs); -Field2D operator/(const Field2D& lhs, BoutReal rhs); +FIELD2D_FIELD2D_BOUTREAL_OP(+, Add) +FIELD2D_FIELD2D_BOUTREAL_OP(-, Sub) +FIELD2D_FIELD2D_BOUTREAL_OP(*, Mul) +FIELD2D_FIELD2D_BOUTREAL_OP(/, Div) + +#define FIELD2D_BOUTREAL_FIELD2D_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_field2d_v, \ + BinaryExpr, R, bout::op::OP_TYPE>> \ + operator OP_SYM(L lhs, const R& rhs) { \ + return BinaryExpr, R, bout::op::OP_TYPE>{ \ + static_cast::View>(lhs), \ + static_cast(rhs), \ + bout::op::OP_TYPE{}, \ + rhs.getMesh(), \ + rhs.getLocation(), \ + rhs.getDirections(), \ + std::nullopt, \ + rhs.getMesh()->getRegion2D("RGN_ALL")}; \ + } -Field2D operator+(BoutReal lhs, const Field2D& rhs); -Field2D operator-(BoutReal lhs, const Field2D& rhs); -Field2D operator*(BoutReal lhs, const Field2D& rhs); -Field2D operator/(BoutReal lhs, const Field2D& rhs); +FIELD2D_BOUTREAL_FIELD2D_OP(+, Add) +FIELD2D_BOUTREAL_FIELD2D_OP(-, Sub) +FIELD2D_BOUTREAL_FIELD2D_OP(*, Mul) +FIELD2D_BOUTREAL_FIELD2D_OP(/, Div) + +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr> +if_else(bool condition, const L& lhs, const R& rhs) { + return BinaryExpr{ + static_cast(lhs), + static_cast(rhs), + bout::op::IfElse{condition}, + lhs.getMesh(), + lhs.getLocation(), + lhs.getDirections(), + std::nullopt, + lhs.getMesh()->getRegion2D("RGN_ALL")}; +} + +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr> +if_else(bool condition, const L& lhs, const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + auto regionID = rhs.getRegionID(); + int mesh_nz = rhs.getMesh()->LocalNz; + return BinaryExpr{ + static_cast(lhs).setScale(1, mesh_nz), + static_cast(rhs), + bout::op::IfElse{condition}, + rhs.getMesh(), + rhs.getLocation(), + rhs.getDirections(), + regionID, + rhs.getMesh()->getRegion("RGN_ALL")}; +} + +template +std::enable_if_t && is_expr_constant_v, + BinaryExpr, bout::op::IfElse>> +if_else(bool condition, const L& lhs, R rhs) { + return BinaryExpr, bout::op::IfElse>{ + static_cast(lhs), + static_cast::View>(rhs), + bout::op::IfElse{condition}, + lhs.getMesh(), + lhs.getLocation(), + lhs.getDirections(), + std::nullopt, + lhs.getMesh()->getRegion2D("RGN_ALL")}; +} + +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr, R, bout::op::IfElse>> +if_else(bool condition, L lhs, const R& rhs) { + return BinaryExpr, R, bout::op::IfElse>{ + static_cast::View>(lhs), + static_cast(rhs), + bout::op::IfElse{condition}, + rhs.getMesh(), + rhs.getLocation(), + rhs.getDirections(), + std::nullopt, + rhs.getMesh()->getRegion2D("RGN_ALL")}; +} + +template || is_expr_field3d_v>> +auto if_else_zero(bool condition, const L& lhs) { + return if_else(condition, lhs, 0.0); +} /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. */ -Field2D operator-(const Field2D& f); +inline auto operator-(const Field2D& f) { + return BinaryExpr, Field2D, bout::op::Mul>{ + static_cast::View>(-1.0), + static_cast(f), + bout::op::Mul{}, + f.getMesh(), + f.getLocation(), + f.getDirections(), + std::nullopt, + f.getRegion("RGN_ALL")}; +} // Non-member functions inline Field2D toFieldAligned(const Field2D& f, - const std::string& UNUSED(region) = "RGN_ALL") { + [[maybe_unused]] const std::string& region = "RGN_ALL") { return f; } inline Field2D fromFieldAligned(const Field2D& f, - const std::string& UNUSED(region) = "RGN_ALL") { + [[maybe_unused]] const std::string& region = "RGN_ALL") { return f; } @@ -334,15 +580,15 @@ inline Field2D fromFieldAligned(const Field2D& f, /// default (can be changed using the \p rgn argument void checkData(const Field2D& f, const std::string& region = "RGN_NOBNDRY"); #else -inline void checkData(const Field2D& UNUSED(f), - std::string UNUSED(region) = "RGN_NOBNDRY") {} +inline void checkData([[maybe_unused]] const Field2D& f, + [[maybe_unused]] std::string region = "RGN_NOBNDRY") {} #endif /// Force guard cells of passed field \p var to NaN #if CHECK > 2 void invalidateGuards(Field2D& var); #else -inline void invalidateGuards(Field2D& UNUSED(var)) {} +inline void invalidateGuards([[maybe_unused]] Field2D& var) {} #endif /// Average in the Z direction @@ -358,7 +604,7 @@ inline Field2D& ddt(Field2D& f) { return *(f.timeDeriv()); } /// toString template specialisation /// Defined in utils.hxx template <> -inline std::string toString<>(const Field2D& UNUSED(val)) { +inline std::string toString<>([[maybe_unused]] const Field2D& val) { return ""; } diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index a75e38df36..62486dded9 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -1,8 +1,8 @@ /************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors + * + * Contact: Ben Dudson, dudson2@llnl.gov * - * Contact: Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -20,6 +20,8 @@ * **************************************************************************/ +#include "bout/utils.hxx" +#include class Field3D; #pragma once @@ -29,15 +31,29 @@ class Field3D; #include "bout/array.hxx" #include "bout/assert.hxx" #include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/build_config.hxx" #include "bout/field.hxx" #include "bout/field2d.hxx" +#include "bout/field_data.hxx" #include "bout/fieldperp.hxx" #include "bout/region.hxx" +#include "bout/traits.hxx" +#include +#include #include +#include +#include +#include +#include #include class Mesh; +class Options; +class Field3DParallel; + +#include "bout/fieldops.hxx" /// Class for 3D X-Y-Z scalar fields /*! @@ -166,7 +182,8 @@ public: */ Field3D(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Standard}); + ZDirectionType::Standard}, + std::optional regionID = {}); /*! * Copy constructor @@ -183,8 +200,15 @@ public: Field3D(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, DirectionTypes directions_in = {YDirectionType::Standard, ZDirectionType::Standard}); + template || is_expr_field3d_v>> + Field3D(const BinaryExpr& expr) + : Field3D(evaluateBinaryExpr(expr), expr.getMesh(), expr.getLocation(), + expr.getDirections()) { + setRegion(expr.getRegionID()); + } /// Destructor - ~Field3D() override; + ~Field3D() override { delete deriv; } /// Data type stored in this field using value_type = BoutReal; @@ -234,15 +258,15 @@ public: * Ensure that this field has separate fields * for yup and ydown. */ - void splitParallelSlices(); + void splitParallelSlices() override; /*! * Clear the parallel slices, yup and ydown */ - void clearParallelSlices(); + void clearParallelSlices() override; /// Check if this field has yup and ydown fields - bool hasParallelSlices() const { + bool hasParallelSlices() const override { #if CHECK > 2 if (yup_fields.size() != ydown_fields.size()) { throw BoutException( @@ -257,26 +281,33 @@ public: #endif } + size_t numberParallelSlices() const override { +#if CHECK > 0 + hasParallelSlices(); +#endif + return yup_fields.size(); + } + /// Check if this field has yup and ydown fields /// Return reference to yup field - Field3D& yup(std::vector::size_type index = 0) { + Field3D& yup(size_t index = 0) { ASSERT2(index < yup_fields.size()); return yup_fields[index]; } /// Return const reference to yup field - const Field3D& yup(std::vector::size_type index = 0) const { + const Field3D& yup(size_t index = 0) const { ASSERT2(index < yup_fields.size()); return yup_fields[index]; } /// Return reference to ydown field - Field3D& ydown(std::vector::size_type index = 0) { + Field3D& ydown(size_t index = 0) { ASSERT2(index < ydown_fields.size()); return ydown_fields[index]; } /// Return const reference to ydown field - const Field3D& ydown(std::vector::size_type index = 0) const { + const Field3D& ydown(size_t index = 0) const { ASSERT2(index < ydown_fields.size()); return ydown_fields[index]; } @@ -291,6 +322,17 @@ public: /// cuts on closed field lines? bool requiresTwistShift(bool twist_shift_enabled); + /// Enable a special tracking mode for debugging + /// Save all changes that, are done to the field, to tracking + Field3D& enableTracking(const std::string& name, std::weak_ptr tracking); + + /// Disable tracking + Field3D& disableTracking() { + tracking.reset(); + tracking_state = 0; + return *this; + } + ///////////////////////////////////////////////////////// // Data access @@ -312,11 +354,12 @@ public: const Region& getRegion(const std::string& region_name) const; /// Use region provided by the default, and if none is set, use the provided one const Region& getValidRegionWithDefault(const std::string& region_name) const; - void setRegion(const std::string& region_name); - void resetRegion() { regionID.reset(); }; - void setRegion(size_t id) { regionID = id; }; - void setRegion(std::optional id) { regionID = id; }; - std::optional getRegionID() const { return regionID; }; + void setRegion(const std::string& region_name) override; + void resetRegion() override { regionID.reset(); }; + void resetRegionParallel(bool force = false) override; + void setRegion(size_t id) override { regionID = id; }; + void setRegion(std::optional id) override { regionID = id; }; + std::optional getRegionID() const override { return regionID; }; /// Return a Region reference to use to iterate over the x- and /// y-indices of this field @@ -330,6 +373,14 @@ public: return std::end(getRegion("RGN_ALL")); }; + /// Convert (x, y, z) to an Ind3D + /// Requires mesh size. + Ind3D indexAt(int x, int y, int z) const { + const int ny = this->getNy(); + const int nz = this->getNz(); + return Ind3D{(((x * ny) + y) * nz) + z, ny, nz}; + } + BoutReal& operator[](const Ind3D& d) { return data[d.ind]; } const BoutReal& operator[](const Ind3D& d) const { return data[d.ind]; } @@ -343,7 +394,7 @@ public: * Direct access to the underlying data array * * If CHECK > 2 then bounds checking is performed - * + * * If CHECK <= 2 then no checks are performed, to * allow inlining and optimisation of inner loops */ @@ -360,7 +411,7 @@ public: jz, nx, ny, nz); } #endif - return data[(jx * ny + jy) * nz + jz]; + return data[(((jx * ny) + jy) * nz) + jz]; } inline const BoutReal& operator()(int jx, int jy, int jz) const { @@ -375,7 +426,7 @@ public: jz, nx, ny, nz); } #endif - return data[(jx * ny + jy) * nz + jz]; + return data[(((jx * ny) + jy) * nz) + jz]; } /*! @@ -413,39 +464,141 @@ public: return &data[(jx * ny + jy) * nz]; } + struct View { + BoutReal* data; + const Field3D* yup_fields{nullptr}; + const Field3D* ydown_fields{nullptr}; + int num_parallel_slices{0}; + std::optional regionID; + + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx) const { + return data[idx]; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal& operator[](int idx) const { + return data[idx]; + } + + template + View& setScale(Mul /*unused*/, Div /*unused*/) { + static_assert(!std::is_same_v, + "Field3D::View does not support setScale()"); + return *this; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE bool hasParallelSlices() const { + return num_parallel_slices > 0; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int numberParallelSlices() const { + return num_parallel_slices; + } + /// Not a DEVICE function because it dereferences a Field3D pointer + BOUT_FORCEINLINE View yup(int slice = 0) const { + ASSERT2(slice < num_parallel_slices); + ASSERT2(yup_fields[slice].isAllocated()); + return static_cast(yup_fields[slice]); + } + /// Not a DEVICE function because it dereferences a Field3D pointer + BOUT_FORCEINLINE View ydown(int slice = 0) const { + ASSERT2(slice < num_parallel_slices); + ASSERT2(ydown_fields[slice].isAllocated()); + return static_cast(ydown_fields[slice]); + } + + std::optional getRegionID() const { return regionID; } + }; + operator View() { + return View{&data[0], yup_fields.data(), ydown_fields.data(), + static_cast(numberParallelSlices()), regionID}; + } + operator View() const { + return View{const_cast(&data[0]), yup_fields.data(), ydown_fields.data(), + static_cast(numberParallelSlices()), regionID}; + } + //operator View() const { return View{&data[0]}; } + ///////////////////////////////////////////////////////// // Operators /// Assignment operators ///@{ Field3D& operator=(const Field3D& rhs); - Field3D& operator=(Field3D&& rhs); + Field3D& operator=(Field3D&& rhs) noexcept { + track(rhs, "operator="); + + // Move parallel slices or delete existing ones. + yup_fields = std::move(rhs.yup_fields); + ydown_fields = std::move(rhs.ydown_fields); + + // Move the data and data sizes + nx = rhs.nx; + ny = rhs.ny; + nz = rhs.nz; + regionID = rhs.regionID; + + data = std::move(rhs.data); + + // Move base slice last + Field::operator=(std::move(rhs)); + + return *this; + } Field3D& operator=(const Field2D& rhs); /// return void, as only part initialised void operator=(const FieldPerp& rhs); Field3D& operator=(BoutReal val); - ///@} + template + std::enable_if_t, Field3D&> + operator=(const BinaryExpr& expr) { + if (!isAllocated() || getMesh() != expr.getMesh()) { + *this = Field3D{expr}; + return *this; + } + + clearParallelSlices(); + setRegion(expr.getRegionID()); + setLocation(expr.getLocation()); + setDirections(expr.getDirections()); + allocate(); + expr.evaluate(&data[0]); + return *this; + } - /// Addition operators - ///@{ - Field3D& operator+=(const Field3D& rhs); - Field3D& operator+=(const Field2D& rhs); - Field3D& operator+=(BoutReal rhs); ///@} - /// Subtraction operators - ///@{ - Field3D& operator-=(const Field3D& rhs); - Field3D& operator-=(const Field2D& rhs); - Field3D& operator-=(BoutReal rhs); +#define FIELD3D_OP_EQUALS(OP_SYM) \ + template \ + std::enable_if_t< \ + is_expr_field3d_v || is_expr_field2d_v || is_expr_constant_v, Field3D&> \ + operator OP_SYM## = (const R& rhs) { \ + if (data.unique()) { \ + clearParallelSlices(); \ + auto expr = (*this)OP_SYM rhs; \ + expr.evaluate(&data[0]); \ + } else { \ + (*this) = (*this)OP_SYM rhs; \ + } \ + return *this; \ + } + + FIELD3D_OP_EQUALS(+) + FIELD3D_OP_EQUALS(-) + FIELD3D_OP_EQUALS(*) + FIELD3D_OP_EQUALS(/) + ///@} - /// Multiplication operators - ///@{ Field3D& operator*=(const Field3D& rhs); + Field3D& operator+=(const Field3D& rhs); + Field3D& operator-=(const Field3D& rhs); + Field3D& operator*=(const Field3DParallel& rhs); + Field3D& operator/=(const Field3DParallel& rhs); + Field3D& operator+=(const Field3DParallel& rhs); + Field3D& operator-=(const Field3DParallel& rhs); Field3D& operator*=(const Field2D& rhs); + Field3D& operator+=(const Field2D& rhs); + Field3D& operator-=(const Field2D& rhs); Field3D& operator*=(BoutReal rhs); - ///@} + Field3D& operator+=(BoutReal rhs); + Field3D& operator-=(BoutReal rhs); /// Division operators ///@{ @@ -454,8 +607,21 @@ public: Field3D& operator/=(BoutReal rhs); ///@} + Field3D& update_multiplication_inplace(const Field3D& rhs); + Field3D& update_division_inplace(const Field3D& rhs); + Field3D& update_addition_inplace(const Field3D& rhs); + Field3D& update_subtraction_inplace(const Field3D& rhs); + Field3D& update_multiplication_inplace(const Field2D& rhs); + Field3D& update_division_inplace(const Field2D& rhs); + Field3D& update_addition_inplace(const Field2D& rhs); + Field3D& update_subtraction_inplace(const Field2D& rhs); + Field3D& update_multiplication_inplace(BoutReal rhs); + Field3D& update_division_inplace(BoutReal rhs); + Field3D& update_addition_inplace(BoutReal rhs); + Field3D& update_subtraction_inplace(BoutReal rhs); + // FieldData virtual functions - bool is3D() const override { return true; } + FieldType field_type() const override { return FieldType::field3d; } #if CHECK > 0 void doneComms() override { bndry_xin = bndry_xout = bndry_yup = bndry_ydown = true; } @@ -466,7 +632,9 @@ public: friend class Vector3D; friend class Vector2D; - Field3D& calcParallelSlices(); + void calcParallelSlices() override; + bool areCalcParallelSlicesAllowed() const override { return _allowCalcParallelSlices; }; + void disallowCalcParallelSlices() override { _allowCalcParallelSlices = false; }; void applyBoundary(bool init = false) override; void applyBoundary(BoutReal t); @@ -479,8 +647,11 @@ public: /// This uses 2nd order central differences to set the value /// on the boundary to the value on the boundary in field \p f3d. /// Note: does not just copy values in boundary region. - void setBoundaryTo(const Field3D& f3d); + void setBoundaryTo(const Field3D& f3d) { setBoundaryTo(f3d, true); } + void setBoundaryTo(const Field3D& f3d, bool copyParallelSlices, + bool forceLegacy = false); + using FieldData::applyParallelBoundary; void applyParallelBoundary() override; void applyParallelBoundary(BoutReal t) override; void applyParallelBoundary(const std::string& condition) override; @@ -489,11 +660,17 @@ public: void applyParallelBoundary(const std::string& region, const std::string& condition, Field3D* f); + void swapData(Field3D& other); friend void swap(Field3D& first, Field3D& second) noexcept; int size() const override { return nx * ny * nz; }; -private: + std::weak_ptr getTracking() { return tracking; }; + + inline Field3DParallel asField3DParallel(); + inline Field3DParallel asField3DParallel() const; + +protected: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null int nx{-1}, ny{-1}, nz{-1}; @@ -508,41 +685,224 @@ private: /// RegionID over which the field is valid std::optional regionID; + + /// counter for tracking, to assign unique names to the variable names + int tracking_state{0}; + std::weak_ptr tracking; + + bool _allowCalcParallelSlices{true}; + // name is changed if we assign to the variable, while selfname is a + // non-changing copy that is used for the variable names in the dump files + std::string selfname; + template + void track(const T& change, const std::string& operation) { + if (tracking_state != 0) { + _track(change, operation); + } + } + template > + void _track(const T& change, std::string operation); + void _track(const BoutReal& change, std::string operation); + + template + static Array evaluateBinaryExpr(const BinaryExpr& expr) { + const auto* mesh = expr.getMesh(); + ASSERT1(mesh != nullptr); + + Array data{mesh->LocalNx * mesh->LocalNy * mesh->LocalNz}; + expr.evaluate(&data[0]); + return data; + } }; // Non-member overloaded operators +template +constexpr bool always_false = false; + // Binary operators FieldPerp operator+(const Field3D& lhs, const FieldPerp& rhs); FieldPerp operator-(const Field3D& lhs, const FieldPerp& rhs); FieldPerp operator*(const Field3D& lhs, const FieldPerp& rhs); FieldPerp operator/(const Field3D& lhs, const FieldPerp& rhs); -Field3D operator+(const Field3D& lhs, const Field3D& rhs); -Field3D operator-(const Field3D& lhs, const Field3D& rhs); -Field3D operator*(const Field3D& lhs, const Field3D& rhs); -Field3D operator/(const Field3D& lhs, const Field3D& rhs); +#define FIELD3D_FIELD3D_FIELD3D_OP(OP_SYM, OP_TYPE) \ + template && is_expr_field3d_v>> \ + BinaryExpr operator OP_SYM(const L& lhs, \ + const R& rhs) { \ + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); \ + auto regionID = \ + lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID()); \ + return BinaryExpr{ \ + static_cast(lhs), \ + static_cast(rhs), \ + bout::op::OP_TYPE{}, \ + lhs.getMesh(), \ + lhs.getLocation(), \ + lhs.getDirections(), \ + regionID, \ + (regionID.has_value() ? lhs.getMesh()->getRegion(regionID.value()) \ + : lhs.getMesh()->getRegion("RGN_ALL"))}; \ + } -Field3D operator+(const Field3D& lhs, const Field2D& rhs); -Field3D operator-(const Field3D& lhs, const Field2D& rhs); -Field3D operator*(const Field3D& lhs, const Field2D& rhs); -Field3D operator/(const Field3D& lhs, const Field2D& rhs); +FIELD3D_FIELD3D_FIELD3D_OP(+, Add) +FIELD3D_FIELD3D_FIELD3D_OP(-, Sub) +FIELD3D_FIELD3D_FIELD3D_OP(*, Mul) +FIELD3D_FIELD3D_FIELD3D_OP(/, Div) + +#define FIELD3D_FIELD3D_FIELD2D_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_field2d_v, \ + BinaryExpr> \ + operator OP_SYM(const L& lhs, const R& rhs) { \ + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); \ + auto regionID = lhs.getRegionID(); \ + int mesh_nz = lhs.getMesh()->LocalNz; \ + return BinaryExpr{ \ + static_cast(lhs), \ + static_cast(rhs).setScale(1, mesh_nz), \ + bout::op::OP_TYPE{}, \ + lhs.getMesh(), \ + lhs.getLocation(), \ + lhs.getDirections(), \ + regionID, \ + lhs.getMesh()->getRegion("RGN_ALL")}; \ + } -Field3D operator+(const Field3D& lhs, BoutReal rhs); -Field3D operator-(const Field3D& lhs, BoutReal rhs); -Field3D operator*(const Field3D& lhs, BoutReal rhs); -Field3D operator/(const Field3D& lhs, BoutReal rhs); +FIELD3D_FIELD3D_FIELD2D_OP(+, Add) +FIELD3D_FIELD3D_FIELD2D_OP(-, Sub) +FIELD3D_FIELD3D_FIELD2D_OP(*, Mul) +FIELD3D_FIELD3D_FIELD2D_OP(/, Div) + +#define FIELD3D_FIELD3D_BOUTREAL_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_constant_v, \ + BinaryExpr, bout::op::OP_TYPE>> \ + operator OP_SYM(const L& lhs, R rhs) { \ + auto regionID = lhs.getRegionID(); \ + return BinaryExpr, bout::op::OP_TYPE>{ \ + static_cast(lhs), \ + static_cast::View>(rhs), \ + bout::op::OP_TYPE{}, \ + lhs.getMesh(), \ + lhs.getLocation(), \ + lhs.getDirections(), \ + regionID, \ + lhs.getMesh()->getRegion("RGN_ALL")}; \ + } -Field3D operator+(BoutReal lhs, const Field3D& rhs); -Field3D operator-(BoutReal lhs, const Field3D& rhs); -Field3D operator*(BoutReal lhs, const Field3D& rhs); -Field3D operator/(BoutReal lhs, const Field3D& rhs); +FIELD3D_FIELD3D_BOUTREAL_OP(+, Add) +FIELD3D_FIELD3D_BOUTREAL_OP(-, Sub) +FIELD3D_FIELD3D_BOUTREAL_OP(*, Mul) +FIELD3D_FIELD3D_BOUTREAL_OP(/, Div) + +#define FIELD3D_BOUTREAL_FIELD3D_OP(OP_SYM, OP_TYPE) \ + template \ + std::enable_if_t && is_expr_field3d_v, \ + BinaryExpr, R, bout::op::OP_TYPE>> \ + operator OP_SYM(const L& lhs, const R& rhs) { \ + auto regionID = rhs.getRegionID(); \ + return BinaryExpr, R, bout::op::OP_TYPE>{ \ + static_cast::View>(lhs), \ + static_cast(rhs), \ + bout::op::OP_TYPE{}, \ + rhs.getMesh(), \ + rhs.getLocation(), \ + rhs.getDirections(), \ + regionID, \ + rhs.getMesh()->getRegion("RGN_ALL")}; \ + } + +FIELD3D_BOUTREAL_FIELD3D_OP(+, Add) +FIELD3D_BOUTREAL_FIELD3D_OP(-, Sub) +FIELD3D_BOUTREAL_FIELD3D_OP(*, Mul) +FIELD3D_BOUTREAL_FIELD3D_OP(/, Div) + +template && is_expr_field3d_v>> +BinaryExpr if_else(bool condition, const L& lhs, + const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + auto regionID = lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID()); + return BinaryExpr{ + static_cast(lhs), + static_cast(rhs), + bout::op::IfElse{condition}, + lhs.getMesh(), + lhs.getLocation(), + lhs.getDirections(), + regionID, + (regionID.has_value() ? lhs.getMesh()->getRegion(regionID.value()) + : lhs.getMesh()->getRegion("RGN_ALL"))}; +} + +template +std::enable_if_t && is_expr_field2d_v, + BinaryExpr> +if_else(bool condition, const L& lhs, const R& rhs) { + ASSERT1_EXPR_COMPATIBLE(lhs, rhs); + auto regionID = lhs.getRegionID(); + int mesh_nz = lhs.getMesh()->LocalNz; + return BinaryExpr{ + static_cast(lhs), + static_cast(rhs).setScale(1, mesh_nz), + bout::op::IfElse{condition}, + lhs.getMesh(), + lhs.getLocation(), + lhs.getDirections(), + regionID, + lhs.getMesh()->getRegion("RGN_ALL")}; +} + +template +std::enable_if_t && is_expr_constant_v, + BinaryExpr, bout::op::IfElse>> +if_else(bool condition, const L& lhs, R rhs) { + auto regionID = lhs.getRegionID(); + return BinaryExpr, bout::op::IfElse>{ + static_cast(lhs), + static_cast::View>(rhs), + bout::op::IfElse{condition}, + lhs.getMesh(), + lhs.getLocation(), + lhs.getDirections(), + regionID, + lhs.getMesh()->getRegion("RGN_ALL")}; +} + +template +std::enable_if_t && is_expr_field3d_v, + BinaryExpr, R, bout::op::IfElse>> +if_else(bool condition, const L& lhs, const R& rhs) { + auto regionID = rhs.getRegionID(); + return BinaryExpr, R, bout::op::IfElse>{ + static_cast::View>(lhs), + static_cast(rhs), + bout::op::IfElse{condition}, + rhs.getMesh(), + rhs.getLocation(), + rhs.getDirections(), + regionID, + rhs.getMesh()->getRegion("RGN_ALL")}; +} /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. */ -Field3D operator-(const Field3D& f); +inline auto operator-(const Field3D& f) { + auto regionID = f.getRegionID(); + return BinaryExpr, Field3D, bout::op::Mul>{ + static_cast::View>(-1.0), + static_cast(f), + bout::op::Mul{}, + f.getMesh(), + f.getLocation(), + f.getDirections(), + regionID, + f.getRegion("RGN_ALL")}; +} // Non-member functions @@ -553,7 +913,6 @@ Field3D operator-(const Field3D& f); /// This loops over the entire domain, including guard/boundary cells by /// default (can be changed using the \p rgn argument). /// If CHECK >= 3 then the result will be checked for non-finite numbers -Field3D pow(const Field3D& lhs, const Field2D& rhs, const std::string& rgn = "RGN_ALL"); FieldPerp pow(const Field3D& lhs, const FieldPerp& rhs, const std::string& rgn = "RGN_ALL"); @@ -566,8 +925,8 @@ void checkData(const Field3D& f, const std::string& region = "RGN_NOBNDRY"); #else /// Ignored with disabled CHECK; Throw an exception if \p f is not /// allocated or if any elements are non-finite (for CHECK > 2) -inline void checkData(const Field3D& UNUSED(f), - const std::string& UNUSED(region) = "RGN_NOBNDRY"){}; +inline void checkData([[maybe_unused]] const Field3D& f, + [[maybe_unused]] const std::string& region = "RGN_NOBNDRY") {}; #endif /// Fourier filtering, removes all except one mode @@ -599,7 +958,7 @@ lowPass(const Field3D& var, int zmax, int keep_zonal, REGION rgn = RGN_ALL) { /// @param[in] var Variable to apply filter to /// @param[in] zmax Maximum mode in Z /// @param[in] rgn The region to calculate the result over -inline Field3D lowPass(const Field3D& var, int zmax, const std::string rgn = "RGN_ALL") { +inline Field3D lowPass(const Field3D& var, int zmax, const std::string& rgn = "RGN_ALL") { return lowPass(var, zmax, true, rgn); } @@ -628,7 +987,7 @@ Field2D DC(const Field3D& f, const std::string& rgn = "RGN_ALL"); #if CHECK > 2 void invalidateGuards(Field3D& var); #else -inline void invalidateGuards(Field3D& UNUSED(var)) {} +inline void invalidateGuards([[maybe_unused]] Field3D& var) {} #endif /// Returns a reference to the time-derivative of a field \p f @@ -639,7 +998,7 @@ inline Field3D& ddt(Field3D& f) { return *(f.timeDeriv()); } /// toString template specialisation /// Defined in utils.hxx template <> -inline std::string toString<>(const Field3D& UNUSED(val)) { +inline std::string toString<>([[maybe_unused]] const Field3D& val) { return ""; } @@ -650,4 +1009,229 @@ bool operator==(const Field3D& a, const Field3D& b); /// Output a string describing a Field3D to a stream std::ostream& operator<<(std::ostream& out, const Field3D& value); +inline Field3D copy(const Field3D& f) { + Field3D result{f}; + result.allocate(); + for (size_t i = 0; i < result.numberParallelSlices(); ++i) { + result.yup(i).allocate(); + result.ydown(i).allocate(); + } + return result; +} + +/// Field3DParallel is intended to behave like Field3D, but preserve parallel +/// Fields. +/// Operations on Field3D, like multiplication, exp and floor only work on the +/// "main" field, Field3DParallel will retain the parallel slices. +class Field3DParallel : public Field3D { +public: + template + explicit Field3DParallel(Types... args) : Field3D(std::move(args)...) { + ensureFieldAligned(); + } + template || is_expr_field3d_v>> + Field3DParallel(const BinaryExpr& expr) + : Field3DParallel(expr.getMesh(), expr.getLocation(), expr.getDirections(), + expr.getRegionID()) { + *this = expr; + } + Field3DParallel(const Field3D& f) : Field3D(f) { ensureFieldAligned(); } + Field3DParallel(const Field3D& f, bool isRef) : Field3D(f), isRef(isRef) { + ensureFieldAligned(); + } + Field3DParallel(const Field2D& f) : Field3D(f) { ensureFieldAligned(); } + // Explicitly needed, as DirectionTypes is sometimes constructed from a + // brace enclosed list + explicit Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}, + std::optional regionID = {}) + : Field3D(localmesh, location_in, directions_in, regionID) { + if (isFci()) { + splitParallelSlices(); + } + ensureFieldAligned(); + } + explicit Field3DParallel(Array data, Mesh* localmesh, + CELL_LOC location = CELL_CENTRE, + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}) + : Field3D(std::move(data), localmesh, location, directions_in) { + ensureFieldAligned(); + } + explicit Field3DParallel(BoutReal, Mesh* mesh = nullptr); + Field3D& asField3D() { return *this; } + const Field3D& asField3D() const { return *this; } + + struct View { + Field3D::View base; + + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx) const { + return base(idx); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal& operator[](int idx) const { + return base[idx]; + } + + template + View& setScale(Mul /*unused*/, Div /*unused*/) { + static_assert(!std::is_same_v, + "Field3DParallel::View does not support setScale()"); + return *this; + } + + BOUT_FORCEINLINE bool hasParallelSlices() const { return base.hasParallelSlices(); } + BOUT_FORCEINLINE int numberParallelSlices() const { + return base.numberParallelSlices(); + } + /// Not a DEVICE function because it dereferences a Field3D pointer + BOUT_FORCEINLINE View yup(int slice = 0) const { + ASSERT2(slice < base.num_parallel_slices); + ASSERT2(base.yup_fields[slice].isAllocated()); + return View{static_cast(base.yup_fields[slice])}; + } + /// Not a DEVICE function because it dereferences a Field3D pointer + BOUT_FORCEINLINE View ydown(int slice = 0) const { + ASSERT2(slice < base.num_parallel_slices); + ASSERT2(base.ydown_fields[slice].isAllocated()); + return View{static_cast(base.ydown_fields[slice])}; + } + + std::optional getRegionID() const { return base.regionID; } + }; + + operator View() { return View{static_cast(*this)}; } + operator View() const { return View{static_cast(*this)}; } + + Field3DParallel& operator*=(const Field3D&); + Field3DParallel& operator/=(const Field3D&); + Field3DParallel& operator+=(const Field3D&); + Field3DParallel& operator-=(const Field3D&); + Field3DParallel& operator*=(const Field3DParallel&); + Field3DParallel& operator/=(const Field3DParallel&); + Field3DParallel& operator+=(const Field3DParallel&); + Field3DParallel& operator-=(const Field3DParallel&); + Field3DParallel& operator*=(BoutReal); + Field3DParallel& operator/=(BoutReal); + Field3DParallel& operator+=(BoutReal); + Field3DParallel& operator-=(BoutReal); + Field3DParallel& operator=(const Field3D& rhs) { + Field3D::operator=(rhs); + ensureFieldAligned(); + return *this; + } + Field3DParallel& operator=(Field3D&& rhs) { + Field3D::operator=(std::move(rhs)); + ensureFieldAligned(); + return *this; + } + template + std::enable_if_t || is_expr_field3d_v, Field3DParallel&> + operator=(const BinaryExpr& expr) { + if (getMesh() != expr.getMesh()) { + clearParallelSlices(); + fieldmesh = expr.getMesh(); + data = Array{}; + } + if (isFci()) { + if (!hasParallelSlices()) { + splitParallelSlices(); + } + } else if (hasParallelSlices()) { + clearParallelSlices(); + } + + setRegion(expr.getRegionID()); + setLocation(expr.getLocation()); + setDirections(expr.getDirections()); + allocate(); + expr.evaluate(static_cast(*this).data); + + if (isFci()) { + ASSERT2(expr.hasParallelSlices()); + ASSERT2(expr.numberParallelSlices() == static_cast(numberParallelSlices())); + for (int i = 0; i < expr.numberParallelSlices(); ++i) { + yup(i).allocate(); + ydown(i).allocate(); + auto expr_yup = expr.yup(i); + auto expr_ydown = expr.ydown(i); + yup(i).setRegion(expr_yup.getRegionID()); + ydown(i).setRegion(expr_ydown.getRegionID()); + expr_yup.evaluate(static_cast(yup(i)).data); + expr_ydown.evaluate(static_cast(ydown(i)).data); + } + } + + return *this; + } + Field3DParallel& operator=(BoutReal); + Field3DParallel& allocate(); + +private: + void ensureFieldAligned(); + bool isRef{false}; +}; + +Field3DParallel Field3D::asField3DParallel() { + if (isAllocated()) { + allocate(); + for (size_t i = 0; i < numberParallelSlices(); ++i) { + if (yup(i).isAllocated()) { + yup(i).allocate(); + } + if (ydown(i).isAllocated()) { + ydown(i).allocate(); + } + } + } + return Field3DParallel(*this, true); +} +Field3DParallel Field3D::asField3DParallel() const { return Field3DParallel(*this); } + +inline Field3D& Field3D::operator*=(const Field3DParallel& rhs) { + return (*this) *= rhs.asField3D(); +} + +inline Field3D& Field3D::operator/=(const Field3DParallel& rhs) { + return (*this) /= rhs.asField3D(); +} + +inline Field3D& Field3D::operator+=(const Field3DParallel& rhs) { + return (*this) += rhs.asField3D(); +} + +inline Field3D& Field3D::operator-=(const Field3DParallel& rhs) { + return (*this) -= rhs.asField3D(); +} + +template +struct is_expr_field3d> + : std::integral_constant>::value + || is_expr_field3d_v>> {}; + +inline Field3DParallel +filledFrom(const Field3DParallel& f, + const std::function& func) { + auto result{emptyFrom(f)}; + if (f.isFci()) { + BOUT_FOR(i, result.getRegion("RGN_NOY")) { result[i] = func(0, i); } + + for (size_t i = 0; i < result.numberParallelSlices(); ++i) { + result.yup(i).allocate(); + BOUT_FOR(d, result.yup(i).getValidRegionWithDefault("RGN_INVALID")) { + result.yup(i)[d] = func(i + 1, d); + } + result.ydown(i).allocate(); + BOUT_FOR(d, result.ydown(i).getValidRegionWithDefault("RGN_INVALID")) { + result.ydown(i)[d] = func(-i - 1, d); + } + } + } else { + BOUT_FOR(i, result.getRegion("RGN_ALL")) { result[i] = func(0, i); } + } + + return result; +} + #endif /* BOUT_FIELD3D_H */ diff --git a/include/bout/field_accessor.hxx b/include/bout/field_accessor.hxx index 69b58da979..35e1c7f417 100644 --- a/include/bout/field_accessor.hxx +++ b/include/bout/field_accessor.hxx @@ -1,7 +1,8 @@ +/// \file +/// /// FieldAccessor /// /// Provides quick but unsafe access to field and coordinate system data -/// #pragma once #ifndef FIELD_ACCESSOR_H__ @@ -57,10 +58,16 @@ struct FieldAccessor { /// Constructor from Field3D /// /// @param[in] f The field to access. Must already be allocated - explicit FieldAccessor(FieldType& f) : coords(f.getCoordinates()) { + explicit FieldAccessor(FieldType& f) { ASSERT0(f.getLocation() == location); ASSERT0(f.isAllocated()); + if (auto* Coords = f.getCoordinates()) { + coords = CoordinatesAccessor{Coords}; + } else { + coords = CoordinatesAccessor{}; + } + data = BoutRealArray{&f(0, 0, 0)}; // Field size @@ -81,15 +88,20 @@ struct FieldAccessor { ddt = BoutRealArray{&(f.timeDeriv()->operator()(0, 0, 0))}; } + explicit FieldAccessor(const FieldType& f) : FieldAccessor(const_cast(f)) {} + /// Provide shorthand for access to field data. /// Does not convert between 3D and 2D indices, /// so fa[i] is equivalent to fa.data[i]. /// BOUT_HOST_DEVICE inline const BoutReal& operator[](int ind) const { return data[ind]; } + BOUT_HOST_DEVICE inline BoutReal& operator[](int ind) { return data[ind]; } + BOUT_DEVICE inline BoutReal operator()(int i) const { return data[i]; } BOUT_HOST_DEVICE inline const BoutReal& operator[](const Ind3D& ind) const { return data[ind.ind]; } + BOUT_HOST_DEVICE inline BoutReal& operator[](const Ind3D& ind) { return data[ind.ind]; } // Pointers to the field data arrays // These are wrapped in BoutRealArray types so they can be indexed with Ind3D or int @@ -115,13 +127,16 @@ struct FieldAccessor { template using Field2DAccessor = FieldAccessor; +template +using Field3DAccessor = FieldAccessor; + /// Syntactic sugar for time derivative of a field /// /// Usage: /// -/// ddt(fa)[i] = +/// ddt(fa)[i] = /* expression */ /// -/// where fa is a FieldAccessor, and i is an int +/// where ``fa`` is a FieldAccessor, and ``i`` is an int /// template BOUT_HOST_DEVICE inline BoutRealArray& ddt(const FieldAccessor& fa) { @@ -130,4 +145,28 @@ BOUT_HOST_DEVICE inline BoutRealArray& ddt(const FieldAccessor(fa.ddt); } +struct FieldPerpAccessor { + FieldPerpAccessor() = delete; + + int nx, nz; + int yindex; + BoutReal* data; + + explicit FieldPerpAccessor(const FieldPerp& f) { + ASSERT0(f.isAllocated()); + + data = BoutRealArray{const_cast(&f(0, 0, 0))}; + + // Field size + nx = f.getNx(); + nz = f.getNz(); + + yindex = f.getIndex(); + } + + BOUT_HOST_DEVICE int getIndex() const { return yindex; } + BOUT_HOST_DEVICE inline const BoutReal& operator[](int ind) const { return data[ind]; } + BOUT_HOST_DEVICE inline BoutReal& operator[](int ind) { return data[ind]; } +}; + #endif diff --git a/include/bout/field_data.hxx b/include/bout/field_data.hxx index 185dcabf2d..c5e60011f1 100644 --- a/include/bout/field_data.hxx +++ b/include/bout/field_data.hxx @@ -6,7 +6,7 @@ * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -30,9 +30,12 @@ class FieldData; #ifndef FIELD_DATA_H #define FIELD_DATA_H +#include "bout/boundary_region.hxx" #include "bout/bout_types.hxx" +#include "bout/sys/expressionparser.hxx" #include "bout/unused.hxx" +#include #include #include #include @@ -40,14 +43,13 @@ class FieldData; class BoundaryOp; class BoundaryOpPar; +namespace bout::boundary { +class BoundaryRegionFCI; +} class Coordinates; class Mesh; -#include "bout/boundary_region.hxx" -class BoundaryRegionPar; -enum class BndryLoc; - -#include "bout/sys/expressionparser.hxx" +enum class BndryLoc : std::int8_t; /// Base class for both scalar and vector fields, holds common /// information about the grid, coordinates, and boundaries @@ -71,13 +73,22 @@ public: /// Get variable location virtual CELL_LOC getLocation() const; + /// Enum to distinguish the different kinds of Fields + enum class FieldType : std::uint8_t { field3d, field2d, fieldperp }; + /// Is this an instance of `Field3D`, `Field2D`, or `FieldPerp`? + virtual FieldType field_type() const = 0; + // Defines interface which must be implemented /// True if variable is 3D - virtual bool is3D() const = 0; + [[deprecated("Use `field_type()` instead")]] + bool is3D() const { + return field_type() == FieldType::field3d; + } + /// Number of BoutReals in one element virtual int elementSize() const { return 1; } - virtual void doneComms(){}; // Notifies that communications done + virtual void doneComms() {}; // Notifies that communications done // Boundary conditions void setBoundary(const std::string& name); ///< Set the boundary conditions @@ -86,13 +97,13 @@ public: copyBoundary(const FieldData& f); ///< Copy the boundary conditions from another field virtual void applyBoundary(bool UNUSED(init) = false) {} - virtual void applyTDerivBoundary(){}; + virtual void applyTDerivBoundary() {}; - virtual void applyParallelBoundary(){}; - virtual void applyParallelBoundary(BoutReal UNUSED(t)){}; - virtual void applyParallelBoundary(const std::string& UNUSED(condition)){}; + virtual void applyParallelBoundary() {}; + virtual void applyParallelBoundary(BoutReal UNUSED(t)) {}; + virtual void applyParallelBoundary(const std::string& UNUSED(condition)) {}; virtual void applyParallelBoundary(const std::string& UNUSED(region), - const std::string& UNUSED(condition)){}; + const std::string& UNUSED(condition)) {}; // JMAD void addBndryFunction(FuncPtr userfunc, BndryLoc location); void addBndryGenerator(FieldGeneratorPtr gen, BndryLoc location); diff --git a/include/bout/fieldgroup.hxx b/include/bout/fieldgroup.hxx index 184766c6b8..440655e7ce 100644 --- a/include/bout/fieldgroup.hxx +++ b/include/bout/fieldgroup.hxx @@ -1,22 +1,23 @@ #ifndef BOUT_FIELDGROUP_H #define BOUT_FIELDGROUP_H -#include "bout/field_data.hxx" -#include - +#include #include #include #include -#include +class Field2D; +class Field3D; +class FieldPerp; +class Field; /// Group together fields for easier communication /// -/// Note: The FieldData class is used as a base class, -/// which is inherited by Field2D, Field3D, Vector2D and Vector3D -/// however Vector2D and Vector3D are stored by reference to their -/// components (x,y,z) as Field2D or Field3D objects. +/// Note: The `Field` class is used as a base class, +/// which is inherited by `Field2D`, `Field3D`, `FieldPerp`; +/// however `Vector2D` and `Vector3D` are stored by reference to their +/// components ``(x, y, z)`` as `Field2D` or `Field3D` objects. class FieldGroup { public: FieldGroup() = default; @@ -24,11 +25,9 @@ public: FieldGroup(FieldGroup&& other) = default; FieldGroup& operator=(const FieldGroup& other) = default; FieldGroup& operator=(FieldGroup&& other) = default; + ~FieldGroup() = default; - /// Constructor with a single FieldData \p f - FieldGroup(FieldData& f) { fvec.push_back(&f); } - - /// Constructor with a single Field3D \p f + FieldGroup(Field& f) { fvec.push_back(&f); } FieldGroup(Field3D& f) { fvec.push_back(&f); f3vec.push_back(&f); @@ -56,7 +55,7 @@ public: } /// Variadic constructor. Allows an arbitrary number of - /// FieldData arguments + /// Field arguments /// /// The explicit keyword prevents FieldGroup being constructed with arbitrary /// types. In particular arguments to add() cannot be implicitly converted @@ -78,12 +77,12 @@ public: return *this; } - /// Add a FieldData \p f to the group. + /// Add a Field \p f to the group. /// /// A pointer to this field will be stored internally, /// so the lifetime of this variable should be longer /// than the lifetime of this group. - void add(FieldData& f) { fvec.push_back(&f); } + void add(Field& f) { fvec.push_back(&f); } // Add a 3D field \p f, which goes into both vectors. // @@ -121,12 +120,8 @@ public: } /// Add multiple fields to this group - /// - /// This is a variadic template which allows Field3D objects to be - /// treated as a special case. An arbitrary number of fields can be - /// added. template - void add(FieldData& t, Ts&... ts) { + void add(Field& t, Ts&... ts) { add(t); // Add the first using functions above add(ts...); // Add the rest } @@ -165,16 +160,14 @@ public: } /// Iteration over all fields - using iterator = std::vector::iterator; - iterator begin() { return fvec.begin(); } - iterator end() { return fvec.end(); } + auto begin() { return fvec.begin(); } + auto end() { return fvec.end(); } /// Const iteration over all fields - using const_iterator = std::vector::const_iterator; - const_iterator begin() const { return fvec.begin(); } - const_iterator end() const { return fvec.end(); } + auto begin() const { return fvec.cbegin(); } + auto end() const { return fvec.cend(); } - const std::vector& get() const { return fvec; } + const std::vector& get() const { return fvec; } /// Iteration over 3D fields const std::vector& field3d() const { return f3vec; } @@ -183,8 +176,8 @@ public: void makeUnique(); private: - std::vector fvec; // Vector of fields - std::vector f3vec; // Vector of 3D fields + std::vector fvec; // Vector of fields + std::vector f3vec; // Vector of 3D fields }; /// Combine two FieldGroups diff --git a/include/bout/fieldops.hxx b/include/bout/fieldops.hxx new file mode 100644 index 0000000000..b12c1d1046 --- /dev/null +++ b/include/bout/fieldops.hxx @@ -0,0 +1,552 @@ +#pragma once +#ifndef BOUT_FIELDOPS_HXX +#define BOUT_FIELDOPS_HXX + +#include "bout/array.hxx" +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/build_config.hxx" +#include "bout/build_defines.hxx" +#include "bout/region.hxx" + +#include +#include +#include +#include +#include + +#if BOUT_HAS_CUDA +#include +#endif + +class Mesh; +class Field3D; +class Field3DParallel; +class Field2D; +class FieldPerp; + +namespace bout::detail { +// This is defined in field3d.cxx +// It is used because Mesh is an incomplete type so methods cannot be called +// in the template functions in this header file. +const Region& getField3DRegion(const Mesh* mesh, std::optional regionID); +size_t getField3DRegionID(const Mesh* mesh, const std::string& region_name); +std::optional meshGetCommonRegionID(Mesh* mesh, std::optional regionID1, + std::optional regionID2); +} // namespace bout::detail + +template +struct is_expr_field2d : std::false_type {}; + +template <> +struct is_expr_field2d : std::true_type {}; + +template +inline constexpr bool is_expr_field2d_v = is_expr_field2d>::value; + +// Base template: nothing is an expression by default +template +struct is_expr_field3d : std::false_type {}; + +template <> +struct is_expr_field3d : std::true_type {}; + +template <> +struct is_expr_field3d : std::true_type {}; + +template +struct is_expr_fieldperp : std::false_type {}; + +template <> +struct is_expr_fieldperp : std::true_type {}; + +template +inline constexpr bool is_expr_fieldperp_v = is_expr_fieldperp>::value; + +// Helper variable template +template +inline constexpr bool is_expr_field3d_v = is_expr_field3d>::value; + +template +struct is_expr_constant : std::bool_constant> {}; + +template +inline constexpr bool is_expr_constant_v = is_expr_constant>::value; + +template +struct is_expr_constant> + : std::integral_constant>> {}; + +constexpr int THREADS = 128; +namespace bout { +namespace op { +struct Assign { + int scale = 1; + int offset = 0; + template + BOUT_HOST_DEVICE void operator()(int idx, BoutReal* out, const Expr& expr) const { + out[(idx * scale) + offset] = expr.lhs(idx) + expr.rhs(idx); + } +}; + +struct Add { + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + return L(idx) + R(idx); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal a, BoutReal b) const { + return a + b; + } +}; +struct Sub { + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + return L(idx) - R(idx); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal a, BoutReal b) const { + return a - b; + } +}; +struct Mul { + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + return L(idx) * R(idx); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal a, BoutReal b) const { + return a * b; + } +}; +struct Div { + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + return L(idx) / R(idx); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal a, BoutReal b) const { + return a / b; + } +}; +struct IfElse { + bool condition; + + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx, const LView& L, + const RView& R) const { + return condition ? L(idx) : R(idx); + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(BoutReal a, BoutReal b) const { + return condition ? a : b; + } +}; +}; // namespace op + +namespace reduce { + +struct Min { + struct State { + BoutReal value; + }; + + BOUT_HOST_DEVICE static State identity() { + return {std::numeric_limits::infinity()}; + } + BOUT_HOST_DEVICE static void accumulate(State& state, BoutReal value) { + state.value = value < state.value ? value : state.value; + } + BOUT_HOST_DEVICE static void combine(State& state, const State& other) { + state.value = other.value < state.value ? other.value : state.value; + } + static BoutReal finalize(const State& state) { return state.value; } +}; + +struct Max { + struct State { + BoutReal value; + }; + + BOUT_HOST_DEVICE static State identity() { + return {-std::numeric_limits::infinity()}; + } + BOUT_HOST_DEVICE static void accumulate(State& state, BoutReal value) { + state.value = value > state.value ? value : state.value; + } + BOUT_HOST_DEVICE static void combine(State& state, const State& other) { + state.value = other.value > state.value ? other.value : state.value; + } + static BoutReal finalize(const State& state) { return state.value; } +}; + +struct Mean { + struct State { + BoutReal sum; + int count; + }; + + BOUT_HOST_DEVICE static State identity() { return {0.0, 0}; } + BOUT_HOST_DEVICE static void accumulate(State& state, BoutReal value) { + state.sum += value; + state.count += 1; + } + BOUT_HOST_DEVICE static void combine(State& state, const State& other) { + state.sum += other.sum; + state.count += other.count; + } + static BoutReal finalize(const State& state) { + return state.sum / static_cast(state.count); + } +}; + +} // namespace reduce +}; // namespace bout + +template +struct ReductionView { + ExprView expr; + const int* indices; + int num_indices; + + BOUT_HOST_DEVICE BOUT_FORCEINLINE int size() const { return num_indices; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal valueAtRegionPos(int idx) const { + return expr(indices[idx]); + } +}; + +template +ReductionView makeReductionView(const ExprView& expr, + const Array& indices) { + return ReductionView{expr, indices.size() > 0 ? &indices[0] : nullptr, + indices.size()}; +} + +#if BOUT_HAS_CUDA && defined(__CUDACC__) +template +__global__ void __launch_bounds__(THREADS) evaluatorExpr(BoutReal* out, const Expr expr) { + int tid = threadIdx.x + blockIdx.x * blockDim.x; + int e = expr.size(); + + // Out-of-bounds version + if (tid >= e) { + return; + } + int idx = expr.regionIdx(tid); + out[idx] = expr(idx); // single‐pass fusion + + // Grid-strided loop + //int stride = blockDim.x * gridDim.x; + //for (int i = tid; i < e; i += stride) { + // int idx = expr.regionIdx(i); + // out[idx] = expr(idx); // single‐pass fusion + //} +} + +template +__global__ void __launch_bounds__(THREADS) + reducerExpr(typename Reducer::State* partials, const ExprView expr) { + using State = typename Reducer::State; + + __shared__ State shared[THREADS]; + + const int tid = threadIdx.x; + const int global = blockIdx.x * blockDim.x + tid; + const int stride = blockDim.x * gridDim.x; + + State local = Reducer::identity(); + + for (int i = global; i < expr.size(); i += stride) { + Reducer::accumulate(local, expr.valueAtRegionPos(i)); + } + + shared[tid] = local; + __syncthreads(); + + for (int offset = blockDim.x / 2; offset > 0; offset /= 2) { + if (tid < offset) { + Reducer::combine(shared[tid], shared[tid + offset]); + } + __syncthreads(); + } + + if (tid == 0) { + partials[blockIdx.x] = shared[0]; + } +} +#endif + +#if BOUT_HAS_CUDA && defined(__CUDACC__) +struct StreamsRAII { + std::vector streams; + + cudaStream_t get() { + cudaStream_t stream = 0; + + if (streams.empty()) { + if (cudaStreamCreate(&stream) != cudaSuccess) { + throw BoutException("Failed to create CUDA stream"); + } + } else { + stream = streams.back(); + streams.pop_back(); + } + + return stream; + } + + void put(cudaStream_t stream) { streams.push_back(stream); } + + ~StreamsRAII() { + for (auto& stream : streams) { + cudaStreamDestroy(stream); + } + } + + StreamsRAII() = default; + StreamsRAII(const StreamsRAII&) = delete; + StreamsRAII(StreamsRAII&&) = delete; + StreamsRAII& operator=(const StreamsRAII&) = delete; + StreamsRAII& operator=(StreamsRAII&&) = delete; +}; +inline struct StreamsRAII streams; +#endif + +template +auto reduceExpr(const ExprView& expr_view) -> typename Reducer::State { + using State = typename Reducer::State; + + ASSERT1(expr_view.size() > 0); + +#if BOUT_HAS_CUDA && defined(__CUDACC__) + cudaStream_t stream = streams.get(); + int blocks = (expr_view.size() + THREADS - 1) / THREADS; + blocks = blocks < 1024 ? blocks : 1024; + Array partials(blocks); + + reducerExpr<<>>(&partials[0], expr_view); + cudaStreamSynchronize(stream); + streams.put(stream); + + State result = Reducer::identity(); + for (int i = 0; i < blocks; ++i) { + Reducer::combine(result, partials[i]); + } + return result; +#else + State result = Reducer::identity(); + for (int i = 0; i < expr_view.size(); ++i) { + Reducer::accumulate(result, expr_view.valueAtRegionPos(i)); + } + return result; +#endif +} + +template +struct BinaryExpr { + typename L::View lhs; + typename R::View rhs; + Array indices; + Func f; + + Mesh* mesh; + CELL_LOC location = CELL_CENTRE; + DirectionTypes directions; + std::optional regionID; + std::optional yindex; + + template + BinaryExpr(const typename L::View& lhs, const typename R::View& rhs, Func f, Mesh* mesh, + CELL_LOC location, DirectionTypes directions, std::optional regionID, + const Region& region, std::optional yindex = std::nullopt) + : lhs(lhs), rhs(rhs), indices(region.getLinearIndices()), f(f), mesh(mesh), + location(location), directions(directions), regionID(regionID), yindex(yindex) {} + + BinaryExpr(const typename L::View& lhs, const typename R::View& rhs, Func f, Mesh* mesh, + CELL_LOC location, DirectionTypes directions, std::optional regionID, + const Array& indices, std::optional yindex = std::nullopt) + : lhs(lhs), rhs(rhs), indices(indices), f(f), mesh(mesh), location(location), + directions(directions), regionID(regionID), yindex(yindex) {} + + BinaryExpr& operator=(const BinaryExpr&) = delete; + BinaryExpr& operator=(BinaryExpr&&) = delete; + + BOUT_FORCEINLINE int size() const { return indices.size(); } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx) const { + return f(idx, lhs, rhs); // single‐pass fusion + } + template + BOUT_HOST_DEVICE BOUT_FORCEINLINE auto operator[](const IndType& d) const + -> decltype(d.ind, BoutReal{}) { + if constexpr (std::is_same_v) { + return operator()(d.ind / d.nz); + } else { + return operator()(d.ind); + } + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int regionIdx(int idx) const { return indices[idx]; } + + bool hasParallelSlices() const { + if constexpr (is_expr_constant_v && is_expr_constant_v) { + return false; + } else if constexpr (is_expr_constant_v) { + return rhs.hasParallelSlices(); + } else if constexpr (is_expr_constant_v) { + return lhs.hasParallelSlices(); + } else { + return lhs.hasParallelSlices() && rhs.hasParallelSlices(); + } + } + int numberParallelSlices() const { + if (!hasParallelSlices()) { + return 0; + } + if constexpr (is_expr_constant_v && is_expr_constant_v) { + return 0; + } else if constexpr (is_expr_constant_v) { + return rhs.numberParallelSlices(); + } else if constexpr (is_expr_constant_v) { + return lhs.numberParallelSlices(); + } else { + ASSERT2(lhs.numberParallelSlices() == rhs.numberParallelSlices()); + return lhs.numberParallelSlices(); + } + } + auto yup(int slice = 0) const { + return BinaryExpr{ + lhs.yup(slice), + rhs.yup(slice), + f, + mesh, + location, + directions, + bout::detail::meshGetCommonRegionID(mesh, lhs.yup(slice).getRegionID(), + rhs.yup(slice).getRegionID()), + indices, + yindex}; + } + auto ydown(int slice = 0) const { + return BinaryExpr{ + lhs.ydown(slice), + rhs.ydown(slice), + f, + mesh, + location, + directions, + bout::detail::meshGetCommonRegionID(mesh, lhs.ydown(slice).getRegionID(), + rhs.ydown(slice).getRegionID()), + indices, + yindex}; + } + + struct View { + typename L::View lhs; + typename R::View rhs; + const int* indices; + int num_indices; + Func f; + std::optional regionID; + int mul = 1; + int div = 1; + + View& setScale(int mul, int div) { + this->mul = mul; + this->div = div; + return *this; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE bool hasParallelSlices() const { + if constexpr (is_expr_constant_v && is_expr_constant_v) { + return false; + } else if constexpr (is_expr_constant_v) { + return rhs.hasParallelSlices(); + } else if constexpr (is_expr_constant_v) { + return lhs.hasParallelSlices(); + } else { + return lhs.hasParallelSlices() && rhs.hasParallelSlices(); + } + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int numberParallelSlices() const { + if (!hasParallelSlices()) { + return 0; + } + if constexpr (is_expr_constant_v && is_expr_constant_v) { + return 0; + } else if constexpr (is_expr_constant_v) { + return rhs.numberParallelSlices(); + } else if constexpr (is_expr_constant_v) { + return lhs.numberParallelSlices(); + } else { + ASSERT2(lhs.numberParallelSlices() == rhs.numberParallelSlices()); + return lhs.numberParallelSlices(); + } + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE auto yup(int slice = 0) const { + auto result = *this; + result.lhs = lhs.yup(slice); + result.rhs = rhs.yup(slice); + return result; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE auto ydown(int slice = 0) const { + auto result = *this; + result.lhs = lhs.ydown(slice); + result.rhs = rhs.ydown(slice); + return result; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int size() const { return num_indices; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int regionIdx(int idx) const { + return indices[idx]; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx) const { + return f((idx * mul) / div, lhs, rhs); // single‐pass fusion + } + + std::optional getRegionID() const { return regionID; } + }; + + operator View() { return View{lhs, rhs, &indices[0], indices.size(), f, regionID}; } + operator View() const { + return View{lhs, rhs, &indices[0], indices.size(), f, regionID}; + } + + void evaluate(BoutReal* data) const { +#if BOUT_HAS_CUDA && defined(__CUDACC__) + cudaStream_t stream = streams.get(); + int blocks = (size() + THREADS - 1) / THREADS; + evaluatorExpr<<>>(&data[0], static_cast(*this)); + cudaStreamSynchronize(stream); + streams.put(stream); +#else + if constexpr (std::is_same_v) { + // Optimize common case of Field3D on CPUs. + // Get the Region without directly using incomplete Mesh type + const auto& region = bout::detail::getField3DRegion(mesh, regionID); + for (auto block = region.getBlocks().cbegin(), end = region.getBlocks().cend(); + block < end; ++block) { + const int block_begin = block->first.ind; + const int block_end = block->second.ind; + + // Help optimizer establish loop bounds + BOUT_ASSUME(block_begin >= 0); + BOUT_ASSUME(block_begin <= block_end); + + for (int idx = block_begin; idx < block_end; ++idx) { + data[idx] = operator()(idx); + } + } + } else { + int e = size(); + for (int i = 0; i < e; ++i) { + int idx = regionIdx(i); + data[idx] = operator()(idx); // single‐pass fusion + } + } +#endif + } + + Mesh* getMesh() const { return mesh; } + CELL_LOC getLocation() const { return location; } + DirectionTypes getDirections() const { return directions; } + std::optional getRegionID() const { return regionID; }; + int getIndex() const { return yindex.value_or(-1); } +}; + +#endif // BOUT_FIELDSOPS_HXX diff --git a/include/bout/fieldperp.hxx b/include/bout/fieldperp.hxx index 6995308dbe..2f8408d82b 100644 --- a/include/bout/fieldperp.hxx +++ b/include/bout/fieldperp.hxx @@ -2,10 +2,10 @@ * Class for 2D X-Z slices * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors + * + * Contact: Ben Dudson, dudson2@llnl.gov * - * Contact: Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -28,24 +28,30 @@ class FieldPerp; #ifndef BOUT_FIELDPERP_H #define BOUT_FIELDPERP_H -#include "bout/field.hxx" - #include "bout/array.hxx" #include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/build_config.hxx" +#include "bout/field.hxx" +#include "bout/fieldops.hxx" #include "bout/region.hxx" - #include "bout/unused.hxx" +#include "bout/utils.hxx" +#include +#include #include #include +#include +#include class Field2D; // #include "bout/field2d.hxx" class Field3D; // #include "bout/field3d.hxx" /*! * Represents a 2D field perpendicular to the magnetic field - * at a particular index in Y, which only varies in X-Z. - * + * at a particular index in Y, which only varies in X-Z. + * * Primarily used inside field solvers */ class FieldPerp : public Field { @@ -58,7 +64,8 @@ public: FieldPerp(Mesh* fieldmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, int yindex_in = -1, DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Standard}); + ZDirectionType::Standard}, + std::optional regionID = {}); /*! * Copy constructor. After this the data @@ -86,6 +93,15 @@ public: DirectionTypes directions_in = {YDirectionType::Standard, ZDirectionType::Standard}); + template < + typename ResT, typename L, typename R, typename Func, + typename = std::enable_if_t<(is_expr_fieldperp_v && is_expr_fieldperp_v) + || (is_expr_constant_v && is_expr_fieldperp_v) + || (is_expr_fieldperp_v && is_expr_constant_v)>> + FieldPerp(const BinaryExpr& expr) + : FieldPerp(evaluateBinaryExpr(expr), expr.getMesh(), expr.getLocation(), + expr.getIndex(), expr.getDirections()) {} + ~FieldPerp() override = default; /*! @@ -94,6 +110,21 @@ public: FieldPerp& operator=(const FieldPerp& rhs); FieldPerp& operator=(FieldPerp&& rhs) = default; FieldPerp& operator=(BoutReal rhs); + template + std::enable_if_t || is_expr_constant_v, FieldPerp&> + operator=(const BinaryExpr& expr) { + if (!isAllocated() || getMesh() != expr.getMesh()) { + *this = FieldPerp{expr}; + return *this; + } + + setLocation(expr.getLocation()); + setDirections(expr.getDirections()); + setIndex(expr.getIndex()); + allocate(); + expr.evaluate(&data[0]); + return *this; + } /// Return a Region reference to use to iterate over this field const Region& getRegion(REGION region) const; @@ -157,6 +188,19 @@ public: return *this; } + FieldPerp& yup(std::vector::size_type UNUSED(index) = 0) { return *this; } + const FieldPerp& yup(std::vector::size_type UNUSED(index) = 0) const { + return *this; + } + + FieldPerp& ydown(std::vector::size_type UNUSED(index) = 0) { return *this; } + const FieldPerp& ydown(std::vector::size_type UNUSED(index) = 0) const { + return *this; + } + + FieldPerp& ynext(int UNUSED(dir)) { return *this; } + const FieldPerp& ynext(int UNUSED(dir)) const { return *this; } + /*! * Ensure that data array is allocated and unique */ @@ -191,7 +235,7 @@ public: /*! * Access to the underlying data array at a given x,z index - * + * * If CHECK > 2 then bounds checking is performed, otherwise * no checks are performed */ @@ -206,7 +250,7 @@ public: jx, jz, nx, nz); } #endif - return data[jx * nz + jz]; + return data[(jx * nz) + jz]; } /*! @@ -223,13 +267,13 @@ public: jx, jz, nx, nz); } #endif - return data[jx * nz + jz]; + return data[(jx * nz) + jz]; } /*! - * Access to the underlying data array. (X,Y,Z) indices for consistency with + * Access to the underlying data array. (X,Y,Z) indices for consistency with * other field types - * + * */ BoutReal& operator()(int jx, int UNUSED(jy), int jz) { return (*this)(jx, jz); } @@ -238,7 +282,7 @@ public: } /*! - * Addition, modifying in-place. + * Addition, modifying in-place. * This loops over the entire domain, including guard/boundary cells */ FieldPerp& operator+=(const FieldPerp& rhs); @@ -247,7 +291,7 @@ public: FieldPerp& operator+=(BoutReal rhs); /*! - * Subtraction, modifying in place. + * Subtraction, modifying in place. * This loops over the entire domain, including guard/boundary cells */ FieldPerp& operator-=(const FieldPerp& rhs); @@ -256,7 +300,7 @@ public: FieldPerp& operator-=(BoutReal rhs); /*! - * Multiplication, modifying in place. + * Multiplication, modifying in place. * This loops over the entire domain, including guard/boundary cells */ FieldPerp& operator*=(const FieldPerp& rhs); @@ -265,7 +309,7 @@ public: FieldPerp& operator*=(BoutReal rhs); /*! - * Division, modifying in place. + * Division, modifying in place. * This loops over the entire domain, including guard/boundary cells */ FieldPerp& operator/=(const FieldPerp& rhs); @@ -286,13 +330,47 @@ public: */ int getNz() const override { return nz; }; - bool is3D() const override { return false; } + FieldType field_type() const override { return FieldType::fieldperp; } friend void swap(FieldPerp& first, FieldPerp& second) noexcept; int size() const override { return nx * nz; }; + struct View { + BoutReal* data; + int mul = 1; + int div = 1; + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal operator()(int idx) const { + return data[(idx * mul) / div]; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE BoutReal& operator[](int idx) const { + return data[(idx * mul) / div]; + } + + View& setScale(int mul, int div) { + this->mul = mul; + this->div = div; + return *this; + } + BOUT_HOST_DEVICE BOUT_FORCEINLINE bool hasParallelSlices() const { return false; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE int numberParallelSlices() const { return 0; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE View yup(int = 0) const { return *this; } + BOUT_HOST_DEVICE BOUT_FORCEINLINE View ydown(int = 0) const { return *this; } + }; + operator View() { return View{&data[0]}; } + operator View() const { return View{const_cast(&data[0])}; } + private: + template + static Array evaluateBinaryExpr(const BinaryExpr& expr) { + const auto* mesh = expr.getMesh(); + ASSERT1(mesh != nullptr); + + Array data{mesh->LocalNx * mesh->LocalNz}; + expr.evaluate(&data[0]); + return data; + } + /// The Y index at which this FieldPerp is defined int yindex{-1}; @@ -331,11 +409,27 @@ FieldPerp operator/(const FieldPerp& lhs, const Field2D& rhs); FieldPerp operator/(const FieldPerp& lhs, BoutReal rhs); FieldPerp operator/(BoutReal lhs, const FieldPerp& rhs); +FieldPerp pow(const FieldPerp& lhs, const FieldPerp& rhs, + const std::string& rgn = "RGN_ALL"); +FieldPerp pow(const FieldPerp& lhs, BoutReal rhs, const std::string& rgn = "RGN_ALL"); +FieldPerp pow(BoutReal lhs, const FieldPerp& rhs, const std::string& rgn = "RGN_ALL"); + /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. */ -FieldPerp operator-(const FieldPerp& f); +inline auto operator-(const FieldPerp& f) { + return BinaryExpr, FieldPerp, bout::op::Mul>{ + static_cast::View>(-1.0), + static_cast(f), + bout::op::Mul{}, + f.getMesh(), + f.getLocation(), + f.getDirections(), + std::nullopt, + f.getRegion("RGN_ALL"), + f.getIndex()}; +} /// Create a FieldPerp by slicing a 3D field at a given y const FieldPerp sliceXZ(const Field3D& f, int y); @@ -353,8 +447,8 @@ inline FieldPerp emptyFrom(const FieldPerp& f) { #if CHECK > 0 void checkData(const FieldPerp& f, const std::string& region = "RGN_NOX"); #else -inline void checkData(const FieldPerp& UNUSED(f), - const std::string& UNUSED(region) = "RGN_NOX") {} +inline void checkData([[maybe_unused]] const FieldPerp& f, + [[maybe_unused]] const std::string& region = "RGN_NOX") {} #endif /// Force guard cells of passed field \p var to NaN @@ -367,7 +461,7 @@ inline void invalidateGuards(FieldPerp& UNUSED(var)) {} /// toString template specialisation /// Defined in utils.hxx template <> -inline std::string toString<>(const FieldPerp& UNUSED(val)) { +inline std::string toString<>([[maybe_unused]] const FieldPerp& val) { return ""; } @@ -379,4 +473,13 @@ bool operator==(const FieldPerp& a, const FieldPerp& b); /// Output a string describing a FieldPerp to a stream std::ostream& operator<<(std::ostream& out, const FieldPerp& value); +template +struct is_expr_fieldperp> + : std::integral_constant> + && is_expr_fieldperp_v>) + || (is_expr_constant_v> + && is_expr_fieldperp_v>) + || (is_expr_fieldperp_v> + && is_expr_constant_v>)> {}; + #endif diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 94007a57a2..cdb0a067ed 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -5,166 +5,87 @@ #ifndef BOUT_FV_OPS_H #define BOUT_FV_OPS_H +#include "bout/bout_types.hxx" +#include "bout/field.hxx" #include "bout/field3d.hxx" -#include "bout/globals.hxx" +#include "bout/mesh.hxx" +#include "bout/output_bout_types.hxx" // NOLINT(unused-includes, misc-include-cleaner) #include "bout/vector2d.hxx" -#include "bout/utils.hxx" -#include - namespace FV { -/*! - * Div ( a Grad_perp(f) ) -- ∇⊥ ( a ⋅ ∇⊥ f) -- Vorticity - */ -Field3D Div_a_Grad_perp(const Field3D& a, const Field3D& x); +/// Vorticity: +/// \f[ +/// \nabla (a \cdot \nabla_\perp(f)) +/// \f] +// Div ( a Grad_perp(f) ) -- ∇⊥ ( a ⋅ ∇⊥ f) -- Vorticity +Field3D Div_a_Grad_perp(const Field3D& a, const Field3D& f); [[deprecated("Please use Div_a_Grad_perp instead")]] inline Field3D -Div_a_Laplace_perp(const Field3D& a, const Field3D& x) { - return Div_a_Grad_perp(a, x); +Div_a_Laplace_perp(const Field3D& a, const Field3D& f) { + return Div_a_Grad_perp(a, f); } -/*! - * Divergence of a parallel diffusion Div( k * Grad_par(f) ) - */ -const Field3D Div_par_K_Grad_par(const Field3D& k, const Field3D& f, - bool bndry_flux = true); - -/*! - * 4th-order derivative in Y, using derivatives - * on cell boundaries. - * - * A one-sided 3rd-order derivative, given a value - * at a boundary is: - * - * d3f/dx3 ~= 16/5 f_b - 6 f_0 + 4 f_1 - 6/5 f_2 - * - * where f_b is the value on the boundary; f_0 is the cell - * to the left of the boundary; f_1 to the left of f_0 and f_2 - * to the left of f_1 - * - * f_2 | f_1 | f_0 | - * f_b - * - * NB: Uses to/from FieldAligned coordinates - * - * No fluxes through domain boundaries - */ -const Field3D D4DY4(const Field3D& d, const Field3D& f); - -/*! - * 4th-order dissipation term - * - * - * A one-sided 3rd-order derivative, given a value - * at a boundary is: - * - * d3f/dx3 ~= 16/5 f_b - 6 f_0 + 4 f_1 - 6/5 f_2 - * - * where f_b is the value on the boundary; f_0 is the cell - * to the left of the boundary; f_1 to the left of f_0 and f_2 - * to the left of f_1 - * - * f_2 | f_1 | f_0 | - * f_b - */ -const Field3D D4DY4_Index(const Field3D& f, bool bndry_flux = true); - -/*! - * Stencil used for Finite Volume calculations - * which includes cell face values L and R - */ -struct Stencil1D { - // Cell centre values - BoutReal c, m, p, mm, pp; - - // Left and right cell face values - BoutReal L, R; -}; - -/*! - * First order upwind for testing - */ -struct Upwind { - void operator()(Stencil1D& n) { n.L = n.R = n.c; } -}; - -/*! - * Fromm method - */ -struct Fromm { - void operator()(Stencil1D& n) { - n.L = n.c - 0.25 * (n.p - n.m); - n.R = n.c + 0.25 * (n.p - n.m); - } -}; - -/*! - * Second order slope limiter method - * - * Limits slope to minimum absolute value - * of left and right gradients. If at a maximum - * or minimum slope set to zero, i.e. reverts - * to first order upwinding - */ -struct MinMod { - void operator()(Stencil1D& n) { - // Choose the gradient within the cell - // as the minimum (smoothest) solution - BoutReal slope = _minmod(n.p - n.c, n.c - n.m); - n.L = n.c - 0.5 * slope; - n.R = n.c + 0.5 * slope; - } - -private: - /*! - * Internal helper function for minmod slope limiter - * - * If the inputs have different signs then - * returns zero, otherwise chooses the value - * with the minimum magnitude. - */ - BoutReal _minmod(BoutReal a, BoutReal b) { - if (a * b <= 0.0) { - return 0.0; - } - - if (fabs(a) < fabs(b)) { - return a; - } - return b; - } -}; +/// Divergence of a parallel diffusion +/// \f[ +/// \nabla_\parallel(k \cdot \nabla_\parallel(f) ) +/// \f] +Field3D Div_par_K_Grad_par(const Field3D& k, const Field3D& f, bool bndry_flux = true); -/*! - * Monotonised Central (MC) second order slope limiter (Van Leer) - * - * Limits the slope based on taking the slope with - * the minimum absolute value from central, 2*left and - * 2*right. If any of these slopes have different signs - * then the slope reverts to zero (i.e. 1st-order upwinding). - */ -struct MC { - void operator()(Stencil1D& n) { - BoutReal slope = minmod(2. * (n.p - n.c), // 2*right difference - 0.5 * (n.p - n.m), // Central difference - 2. * (n.c - n.m)); // 2*left difference - n.L = n.c - 0.5 * slope; - n.R = n.c + 0.5 * slope; - } +/// 4th-order derivative in Y, using derivatives +/// on cell boundaries. +/// +/// A one-sided 3rd-order derivative, given a value +/// at a boundary is: +/// +/// \f[ +/// \frac{d^3f}{dx^3} \simeq \tfrac{16}{5} f_b - 6 f_0 + 4 f_1 - \tfrac{6}{5} f_2 +/// \f] +/// +/// where: +/// +/// - \f$f_b\f$ is the value on the boundary, +/// - \f$f_0\f$ is the cell to the left of the boundary, +/// - \f$f_1\f$ to the left of \f$f_0\f$, and +/// - \f$f_2\f$ to the left of f_1: +/// +/// .. code:: text +/// f_2 | f_1 | f_0 | +/// f_b +/// +/// NB: Uses to/from FieldAligned coordinates +/// +/// No fluxes through domain boundaries -private: - // Return zero if any signs are different - // otherwise return the value with the minimum magnitude - BoutReal minmod(BoutReal a, BoutReal b, BoutReal c) { - // if any of the signs are different, return zero gradient - if ((a * b <= 0.0) || (a * c <= 0.0)) { - return 0.0; - } +Field3D D4DY4(const Field3D& d, const Field3D& f); - // Return the minimum absolute value - return SIGN(a) * BOUTMIN(fabs(a), fabs(b), fabs(c)); - } -}; +/// 4th-order dissipation term +/// +/// \f[ +/// \frac{d^3f}{dx^3} \simeq \tfrac{16}{5} f_b - 6 f_0 + 4 f_1 - \tfrac{6}{5} f_2 +/// \f] +/// +/// where: +/// +/// - \f$f_b\f$ is the value on the boundary, +/// - \f$f_0\f$ is the cell to the left of the boundary, +/// - \f$f_1\f$ to the left of \f$f_0\f$, and +/// - \f$f_2\f$ to the left of f_1: +/// +/// .. code:: text +/// f_2 | f_1 | f_0 | +/// f_b +Field3D D4DY4_Index(const Field3D& f, bool bndry_flux = true); + +// Forward declarations of flux limiters +// If you want to use your own flux limiter, you need to +// #include to instantiate the templates. +struct Upwind; +struct Fromm; +struct MinMod; +struct MC; +struct Superbee; +struct VanAlbada; +struct WENO3; /*! * Communicate fluxes between processors @@ -189,340 +110,80 @@ void communicateFluxes(Field3D& f); /// /// NB: Uses to/from FieldAligned coordinates template -const Field3D Div_par(const Field3D& f_in, const Field3D& v_in, - const Field3D& wave_speed_in, bool fixflux = true) { - - ASSERT1_FIELDS_COMPATIBLE(f_in, v_in); - ASSERT1_FIELDS_COMPATIBLE(f_in, wave_speed_in); - - Mesh* mesh = f_in.getMesh(); - - CellEdges cellboundary; - - ASSERT2(f_in.getDirectionY() == v_in.getDirectionY()); - ASSERT2(f_in.getDirectionY() == wave_speed_in.getDirectionY()); - const bool are_unaligned = - ((f_in.getDirectionY() == YDirectionType::Standard) - and (v_in.getDirectionY() == YDirectionType::Standard) - and (wave_speed_in.getDirectionY() == YDirectionType::Standard)); - - Field3D f = are_unaligned ? toFieldAligned(f_in, "RGN_NOX") : f_in; - Field3D v = are_unaligned ? toFieldAligned(v_in, "RGN_NOX") : v_in; - Field3D wave_speed = - are_unaligned ? toFieldAligned(wave_speed_in, "RGN_NOX") : wave_speed_in; - - Coordinates* coord = f_in.getCoordinates(); - - Field3D result{zeroFrom(f)}; - - // Only need one guard cell, so no need to communicate fluxes - // Instead calculate in guard cells to preserve fluxes - int ys = mesh->ystart - 1; - int ye = mesh->yend + 1; - - for (int i = mesh->xstart; i <= mesh->xend; i++) { - - if (!mesh->firstY(i) || mesh->periodicY(i)) { - // Calculate in guard cell to get fluxes consistent between processors - ys = mesh->ystart - 1; - } else { - // Don't include the boundary cell. Note that this implies special - // handling of boundaries later - ys = mesh->ystart; - } - - if (!mesh->lastY(i) || mesh->periodicY(i)) { - // Calculate in guard cells - ye = mesh->yend + 1; - } else { - // Not in boundary cells - ye = mesh->yend; - } - - for (int j = ys; j <= ye; j++) { - // Pre-calculate factors which multiply fluxes -#if not(BOUT_USE_METRIC_3D) - // For right cell boundaries - BoutReal common_factor = (coord->J(i, j) + coord->J(i, j + 1)) - / (sqrt(coord->g_22(i, j)) + sqrt(coord->g_22(i, j + 1))); - - BoutReal flux_factor_rc = common_factor / (coord->dy(i, j) * coord->J(i, j)); - BoutReal flux_factor_rp = - common_factor / (coord->dy(i, j + 1) * coord->J(i, j + 1)); - - // For left cell boundaries - common_factor = (coord->J(i, j) + coord->J(i, j - 1)) - / (sqrt(coord->g_22(i, j)) + sqrt(coord->g_22(i, j - 1))); - - BoutReal flux_factor_lc = common_factor / (coord->dy(i, j) * coord->J(i, j)); - BoutReal flux_factor_lm = - common_factor / (coord->dy(i, j - 1) * coord->J(i, j - 1)); -#endif - for (int k = 0; k < mesh->LocalNz; k++) { -#if BOUT_USE_METRIC_3D - // For right cell boundaries - BoutReal common_factor = - (coord->J(i, j, k) + coord->J(i, j + 1, k)) - / (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j + 1, k))); - - BoutReal flux_factor_rc = - common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); - BoutReal flux_factor_rp = - common_factor / (coord->dy(i, j + 1, k) * coord->J(i, j + 1, k)); - - // For left cell boundaries - common_factor = (coord->J(i, j, k) + coord->J(i, j - 1, k)) - / (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j - 1, k))); - - BoutReal flux_factor_lc = - common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); - BoutReal flux_factor_lm = - common_factor / (coord->dy(i, j - 1, k) * coord->J(i, j - 1, k)); -#endif - - //////////////////////////////////////////// - // Reconstruct f at the cell faces - // This calculates s.R and s.L for the Right and Left - // face values on this cell - - // Reconstruct f at the cell faces - Stencil1D s; - s.c = f(i, j, k); - s.m = f(i, j - 1, k); - s.p = f(i, j + 1, k); - - cellboundary(s); // Calculate s.R and s.L - - //////////////////////////////////////////// - // Right boundary - - // Calculate velocity at right boundary (y+1/2) - BoutReal vpar = 0.5 * (v(i, j, k) + v(i, j + 1, k)); - BoutReal flux; - - if (mesh->lastY(i) && (j == mesh->yend) && !mesh->periodicY(i)) { - // Last point in domain - - BoutReal bndryval = 0.5 * (s.c + s.p); - if (fixflux) { - // Use mid-point to be consistent with boundary conditions - flux = bndryval * vpar; - } else { - // Add flux due to difference in boundary values - flux = s.R * vpar + wave_speed(i, j, k) * (s.R - bndryval); - } - } else { - - // Maximum wave speed in the two cells - BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j + 1, k)); - - if (vpar > amax) { - // Supersonic flow out of this cell - flux = s.R * vpar; - } else if (vpar < -amax) { - // Supersonic flow into this cell - flux = 0.0; - } else { - // Subsonic flow, so a mix of right and left fluxes - flux = s.R * 0.5 * (vpar + amax); - } - } - - result(i, j, k) += flux * flux_factor_rc; - result(i, j + 1, k) -= flux * flux_factor_rp; - - //////////////////////////////////////////// - // Calculate at left boundary - - vpar = 0.5 * (v(i, j, k) + v(i, j - 1, k)); - - if (mesh->firstY(i) && (j == mesh->ystart) && !mesh->periodicY(i)) { - // First point in domain - BoutReal bndryval = 0.5 * (s.c + s.m); - if (fixflux) { - // Use mid-point to be consistent with boundary conditions - flux = bndryval * vpar; - } else { - // Add flux due to difference in boundary values - flux = s.L * vpar - wave_speed(i, j, k) * (s.L - bndryval); - } - } else { - - // Maximum wave speed in the two cells - BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j - 1, k)); - - if (vpar < -amax) { - // Supersonic out of this cell - flux = s.L * vpar; - } else if (vpar > amax) { - // Supersonic into this cell - flux = 0.0; - } else { - flux = s.L * 0.5 * (vpar - amax); - } - } - - result(i, j, k) -= flux * flux_factor_lc; - result(i, j - 1, k) += flux * flux_factor_lm; - } - } - } - return are_unaligned ? fromFieldAligned(result, "RGN_NOBNDRY") : result; -} +Field3D Div_par(const Field3D& f_in, const Field3D& v_in, const Field3D& wave_speed_in, + bool fixflux = true); /*! * Div ( n * v ) -- Magnetic drifts * * This uses the expression - * + * * Div( A ) = 1/J * d/di ( J * A^i ) - * + * * Hence the input vector should be contravariant * * Note: Uses to/from FieldAligned * */ template -const Field3D Div_f_v(const Field3D& n_in, const Vector3D& v, bool bndry_flux) { - ASSERT1(n_in.getLocation() == v.getLocation()); - ASSERT1_FIELDS_COMPATIBLE(n_in, v.x); - - Mesh* mesh = n_in.getMesh(); - - CellEdges cellboundary; - - Coordinates* coord = n_in.getCoordinates(); - - if (v.covariant) { - // Got a covariant vector instead - throw BoutException("Div_f_v passed a covariant v"); - } - - Field3D result{zeroFrom(n_in)}; - - Field3D vx = v.x; - Field3D vz = v.z; - Field3D n = n_in; - - BOUT_FOR(i, result.getRegion("RGN_NOBNDRY")) { - // Calculate velocities - BoutReal vU = 0.25 * (vz[i.zp()] + vz[i]) * (coord->J[i.zp()] + coord->J[i]); - BoutReal vD = 0.25 * (vz[i.zm()] + vz[i]) * (coord->J[i.zm()] + coord->J[i]); - BoutReal vL = 0.25 * (vx[i.xm()] + vx[i]) * (coord->J[i.xm()] + coord->J[i]); - BoutReal vR = 0.25 * (vx[i.xp()] + vx[i]) * (coord->J[i.xp()] + coord->J[i]); - - // X direction - Stencil1D s; - s.c = n[i]; - s.m = n[i.xm()]; - s.mm = n[i.xmm()]; - s.p = n[i.xp()]; - s.pp = n[i.xpp()]; - - cellboundary(s); - - if ((i.x() == mesh->xend) && (mesh->lastX())) { - // At right boundary in X - if (bndry_flux) { - BoutReal flux; - if (vR > 0.0) { - // Flux to boundary - flux = vR * s.R; - } else { - // Flux in from boundary - flux = vR * 0.5 * (n[i.xp()] + n[i]); - } - result[i] += flux / (coord->dx[i] * coord->J[i]); - result[i.xp()] -= flux / (coord->dx[i.xp()] * coord->J[i.xp()]); - } - } else { - // Not at a boundary - if (vR > 0.0) { - // Flux out into next cell - BoutReal flux = vR * s.R; - result[i] += flux / (coord->dx[i] * coord->J[i]); - result[i.xp()] -= flux / (coord->dx[i.xp()] * coord->J[i.xp()]); - } - } - - // Left side - - if ((i.x() == mesh->xstart) && (mesh->firstX())) { - // At left boundary in X - - if (bndry_flux) { - BoutReal flux; - if (vL < 0.0) { - // Flux to boundary - flux = vL * s.L; - } else { - // Flux in from boundary - flux = vL * 0.5 * (n[i.xm()] + n[i]); - } - result[i] -= flux / (coord->dx[i] * coord->J[i]); - result[i.xm()] += flux / (coord->dx[i.xm()] * coord->J[i.xm()]); - } - } else { - // Not at a boundary - if (vL < 0.0) { - BoutReal flux = vL * s.L; - result[i] -= flux / (coord->dx[i] * coord->J[i]); - result[i.xm()] += flux / (coord->dx[i.xm()] * coord->J[i.xm()]); - } - } - - /// NOTE: Need to communicate fluxes - - // Z direction - s.m = n[i.zm()]; - s.mm = n[i.zmm()]; - s.p = n[i.zp()]; - s.pp = n[i.zpp()]; - - cellboundary(s); - - if (vU > 0.0) { - BoutReal flux = vU * s.R; - result[i] += flux / (coord->J[i] * coord->dz[i]); - result[i.zp()] -= flux / (coord->J[i.zp()] * coord->dz[i.zp()]); - } - if (vD < 0.0) { - BoutReal flux = vD * s.L; - result[i] -= flux / (coord->J[i] * coord->dz[i]); - result[i.zm()] += flux / (coord->J[i.zm()] * coord->dz[i.zm()]); - } - } +Field3D Div_f_v(const Field3D& n_in, const Vector3D& v, bool bndry_flux); - communicateFluxes(result); - - // Y advection - // Currently just using simple centered differences - // so no fluxes need to be exchanged - - n = toFieldAligned(n_in, "RGN_NOX"); - Field3D vy = toFieldAligned(v.y, "RGN_NOX"); +/*! + * X-Z Finite Volume diffusion operator + */ +Field3D Div_Perp_Lap(const Field3D& a, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); - Field3D yresult = 0.0; - yresult.setDirectionY(YDirectionType::Aligned); +/// Finite volume parallel divergence +/// +/// NOTE: Modified version, applies limiter to velocity and field +/// Performs better (smaller overshoots) than Div_par +/// +/// Preserves the sum of f*J*dx*dy*dz over the domain +/// +/// @param[in] f_in The field being advected. +/// This will be reconstructed at cell faces +/// using the given CellEdges method +/// @param[in] v_in The advection velocity. +/// This will be interpolated to cell boundaries +/// using linear interpolation +/// @param[in] wave_speed_in Local maximum speed of all waves in the system at each +// point in space +/// @param[in] fixflux Fix the flux at the boundary to be the value at the +/// midpoint (for boundary conditions) +/// +/// @param[out] flow_ylow Flow at the lower Y cell boundary +/// Already includes area factor * flux +/// For FCI fields this diagnostic is currently set to zero. +template +Field3D Div_par_mod(const Field3D& f_in, const Field3D& v_in, + const Field3D& wave_speed_in, Field3D& flow_ylow, bool fixflux = true, + bool dissipative = false); - BOUT_FOR(i, result.getRegion("RGN_NOBNDRY")) { - // Y velocities on y boundaries - BoutReal vU = 0.25 * (vy[i] + vy[i.yp()]) * (coord->J[i] + coord->J[i.yp()]); - BoutReal vD = 0.25 * (vy[i] + vy[i.ym()]) * (coord->J[i] + coord->J[i.ym()]); +/// This operator calculates Div_par(f v v) +/// It is used primarily (only?) in the parallel momentum equation. +/// +/// This operator is used rather than Div(f fv) so that the values of +/// f and v are consistent with other advection equations: The product +/// fv is not interpolated to cell boundaries. +template +Field3D Div_par_fvv(const Field3D& f_in, const Field3D& v_in, + const Field3D& wave_speed_in, bool fixflux = true); - // n (advected quantity) on y boundaries - // Note: Use unshifted n_in variable - BoutReal nU = 0.5 * (n[i] + n[i.yp()]); - BoutReal nD = 0.5 * (n[i] + n[i.ym()]); +/// Calculates viscous heating due to numerical momentum fluxes +/// and flow of kinetic energy (in flow_ylow) +template +Field3D Div_par_fvv_heating(const Field3D& f_in, const Field3D& v_in, + const Field3D& wave_speed_in, Field3D& flow_ylow, + bool fixflux = true); - yresult[i] = (nU * vU - nD * vD) / (coord->J[i] * coord->dy[i]); - } - return result + fromFieldAligned(yresult, "RGN_NOBNDRY"); -} +/// Div ( a g Grad_perp(f) ) -- Perpendicular gradient-driven advection +/// +/// This version uses a slope limiter to calculate cell edge values of g in X, +/// the advects the upwind cell edge. +/// +/// 1st order upwinding is used in Y. +template +Field3D Div_a_Grad_perp_limit(const Field3D& a, const Field3D& g, const Field3D& f); -/*! - * X-Z Finite Volume diffusion operator - */ -Field3D Div_Perp_Lap(const Field3D& a, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); } // namespace FV #endif // BOUT_FV_OPS_H diff --git a/include/bout/fv_ops_impl.hxx b/include/bout/fv_ops_impl.hxx new file mode 100644 index 0000000000..8f76dae6a3 --- /dev/null +++ b/include/bout/fv_ops_impl.hxx @@ -0,0 +1,1526 @@ +/* + Finite-volume discretisation methods. Flux-conservative form + */ + +#ifndef BOUT_FV_OPS_IMPL_H +#define BOUT_FV_OPS_IMPL_H + +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/build_defines.hxx" +#include "bout/coordinates.hxx" +#include "bout/field.hxx" +#include "bout/field3d.hxx" +#include "bout/fv_ops.hxx" // NOLINT(unused-includes, misc-include-cleaner) +#include "bout/globals.hxx" +#include "bout/mesh.hxx" +#include "bout/output_bout_types.hxx" // NOLINT(unused-includes, misc-include-cleaner) +#include "bout/region.hxx" +#include "bout/utils.hxx" +#include "bout/vector2d.hxx" + +#include + +namespace FV { +/*! + * Stencil used for Finite Volume calculations + * which includes cell face values L and R + */ +struct Stencil1D { + /// Cell centre values + BoutReal c{}; + BoutReal m{}; + BoutReal p{}; + BoutReal mm = BoutNaN; + BoutReal pp = BoutNaN; + + /// Left cell face value + BoutReal L = BoutNaN; + /// Right cell face value + BoutReal R = BoutNaN; +}; + +/*! + * First order upwind for testing + */ +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct Upwind { + void operator()(Stencil1D& n) { n.L = n.R = n.c; } +}; + +/*! + * Fromm method + */ +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct Fromm { + void operator()(Stencil1D& n) { + n.L = n.c - (0.25 * (n.p - n.m)); + n.R = n.c + (0.25 * (n.p - n.m)); + } +}; + +/*! + * Second order slope limiter method + * + * Limits slope to minimum absolute value + * of left and right gradients. If at a maximum + * or minimum slope set to zero, i.e. reverts + * to first order upwinding + */ +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct MinMod { + void operator()(Stencil1D& n) { + // Choose the gradient within the cell + // as the minimum (smoothest) solution + const BoutReal slope = _minmod(n.p - n.c, n.c - n.m); + n.L = n.c - (0.5 * slope); + n.R = n.c + (0.5 * slope); + } + +private: + /*! + * Internal helper function for minmod slope limiter + * + * If the inputs have different signs then + * returns zero, otherwise chooses the value + * with the minimum magnitude. + */ + static BoutReal _minmod(BoutReal a, BoutReal b) { + if (a * b <= 0.0) { + return 0.0; + } + + if (std::abs(a) < std::abs(b)) { + return a; + } + return b; + } +}; + +/*! + * Monotonised Central (MC) second order slope limiter (Van Leer) + * + * Limits the slope based on taking the slope with + * the minimum absolute value from central, 2*left and + * 2*right. If any of these slopes have different signs + * then the slope reverts to zero (i.e. 1st-order upwinding). + */ +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct MC { + void operator()(Stencil1D& n) { + const BoutReal slope = minmod(2. * (n.p - n.c), // 2*right difference + 0.5 * (n.p - n.m), // Central difference + 2. * (n.c - n.m)); // 2*left difference + n.L = n.c - (0.5 * slope); + n.R = n.c + (0.5 * slope); + } + +private: + // Return zero if any signs are different + // otherwise return the value with the minimum magnitude + static BoutReal minmod(BoutReal a, BoutReal b, BoutReal c) { + // if any of the signs are different, return zero gradient + if ((a * b <= 0.0) || (a * c <= 0.0)) { + return 0.0; + } + + // Return the minimum absolute value + return SIGN(a) * BOUTMIN(std::abs(a), std::abs(b), std::abs(c)); + } +}; + +/// Superbee limiter +/// +/// This corresponds to the limiter function +/// φ(r) = max(0, min(2r, 1), min(r,2) +/// +/// The value at cell right (i.e. i + 1/2) is: +/// +/// n.R = n.c - φ(r) (n.c - (n.p + n.c)/2) +/// = n.c + φ(r) (n.p - n.c)/2 +/// +/// Four regimes: +/// a) r < 1/2 -> φ(r) = 2r +/// n.R = n.c + gL +/// b) 1/2 < r < 1 -> φ(r) = 1 +/// n.R = n.c + gR/2 +/// c) 1 < r < 2 -> φ(r) = r +/// n.R = n.c + gL/2 +/// d) 2 < r -> φ(r) = 2 +/// n.R = n.c + gR +/// +/// where the left and right gradients are: +/// gL = n.c - n.m +/// gR = n.p - n.c +/// +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct Superbee { + void operator()(Stencil1D& n) { + const BoutReal gL = n.c - n.m; + const BoutReal gR = n.p - n.c; + + // r = gL / gR + // Limiter is φ(r) + if (gL * gR < 0) { + // Different signs => Zero gradient + n.L = n.R = n.c; + } else { + const BoutReal sign = SIGN(gL); + const BoutReal abs_gL = std::abs(gL); + const BoutReal abs_gR = std::abs(gR); + const BoutReal half_slope = + sign * BOUTMAX(BOUTMIN(abs_gL, 0.5 * abs_gR), BOUTMIN(abs_gR, 0.5 * abs_gL)); + n.L = n.c - half_slope; + n.R = n.c + half_slope; + } + } +}; + +/*! + * Symmetric Van Albada second order slope limiter + * + * Uses a smooth (differentiable) approximation to `max(a*b, 0)` to avoid + * introducing a kink at extrema, which can be helpful for nonlinear solvers + * and finite-difference Jacobian calculations. + * + * The limited slope is calculated from the left and right differences + * `dl = c - m` and `dr = p - c` as + * + * slope = (pos(dl*dr) * (dl + dr)) / (dl^2 + dr^2) + * + * where `pos(x)` is a smooth approximation to `max(x, 0)`. + */ +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct VanAlbada { + void operator()(Stencil1D& n) { + const BoutReal dl = n.c - n.m; + const BoutReal dr = n.p - n.c; + + const BoutReal denom = (dl * dl) + (dr * dr); + + // Smoothness parameters: + // - keep division well-defined when dl=dr=0 + // - provide a differentiable approximation to max(dl*dr, 0) + const BoutReal eps = (1e-12 * denom) + 1e-30; + + const BoutReal ab = dl * dr; + const BoutReal ab_pos = 0.5 * (ab + sqrt((ab * ab) + (eps * eps))); + + const BoutReal slope = (ab_pos * (dl + dr)) / (denom + eps); + + n.L = n.c - (0.5 * slope); + n.R = n.c + (0.5 * slope); + } +}; + +/*! + * WENO3-JS (Jiang-Shu) reconstruction to cell faces + * + * This is a third-order essentially non-oscillatory reconstruction using two + * candidate second-order polynomials and smoothness-weighted blending. + * + * Unlike TVD slope limiters (e.g. ``MC``), WENO reconstruction is generally + * smooth (differentiable) for all inputs, but it does not enforce strict + * monotonicity. + * + * Uses only the three-point stencil (`m`, `c`, `p`), so it is a drop-in + * replacement anywhere `Stencil1D` is populated with those values. + */ +// NB: The templates need to be explicitly instantiated in fv_ops.cxx +struct WENO3 { + void operator()(Stencil1D& n) { + // Right face (between c and p): value from cell c (left state at i+1/2) + const BoutReal p0_r = 0.5 * (-n.m + 3.0 * n.c); + const BoutReal p1_r = 0.5 * (n.c + n.p); + + const BoutReal beta0_r = SQ(n.c - n.m); + const BoutReal beta1_r = SQ(n.p - n.c); + + // Left face (between m and c): value from cell c (right state at i-1/2) + const BoutReal p0_l = 0.5 * (-n.p + 3.0 * n.c); + const BoutReal p1_l = 0.5 * (n.m + n.c); + + const BoutReal beta0_l = beta1_r; + const BoutReal beta1_l = beta0_r; + + // Smoothness parameter (scaled to local variation) + const BoutReal eps = (1e-12 * (beta0_r + beta1_r)) + 1e-30; + + // Linear weights for WENO3-JS + constexpr BoutReal d0 = 1.0 / 3.0; + constexpr BoutReal d1 = 2.0 / 3.0; + + // Right face weights + const BoutReal a0_r = d0 / SQ(eps + beta0_r); + const BoutReal a1_r = d1 / SQ(eps + beta1_r); + const BoutReal wsum_r = a0_r + a1_r; + const BoutReal w0_r = a0_r / wsum_r; + const BoutReal w1_r = a1_r / wsum_r; + + // Left face weights (mirrored) + const BoutReal a0_l = d0 / SQ(eps + beta0_l); + const BoutReal a1_l = d1 / SQ(eps + beta1_l); + const BoutReal wsum_l = a0_l + a1_l; + const BoutReal w0_l = a0_l / wsum_l; + const BoutReal w1_l = a1_l / wsum_l; + + n.R = (w0_r * p0_r) + (w1_r * p1_r); + n.L = (w0_l * p0_l) + (w1_l * p1_l); + } +}; + +template +struct Slices { + T c; + T up; + T down; + + Slices(bool use_slices, const T& field) + : c(use_slices ? field : toFieldAligned(field)), up(use_slices ? field.yup() : c), + down(use_slices ? field.ydown() : c) {} +}; + +template +Slices makeslices(bool use_slices, const T& field) { + return Slices(use_slices, field); +} + +/// Finite volume parallel divergence +/// +/// Preserves the sum of f*J*dx*dy*dz over the domain +/// +/// @param[in] f_in The field being advected. +/// This will be reconstructed at cell faces +/// using the given CellEdges method +/// @param[in] v_in The advection velocity. +/// This will be interpolated to cell boundaries +/// using linear interpolation +/// @param[in] wave_speed_in Local maximum speed of all waves in the system at each +// point in space +/// @param[in] fixflux Fix the flux at the boundary to be the value at the +/// midpoint (for boundary conditions) +/// +/// NB: Uses to/from FieldAligned coordinates +template +Field3D Div_par(const Field3D& f_in, const Field3D& v_in, const Field3D& wave_speed_in, + bool fixflux) { + + ASSERT1_FIELDS_COMPATIBLE(f_in, v_in); + ASSERT1_FIELDS_COMPATIBLE(f_in, wave_speed_in); + + const Mesh* mesh = f_in.getMesh(); + + CellEdges cellboundary; + + ASSERT2(f_in.getDirectionY() == v_in.getDirectionY()); + ASSERT2(f_in.getDirectionY() == wave_speed_in.getDirectionY()); + const bool are_unaligned = + ((f_in.getDirectionY() == YDirectionType::Standard) + and (v_in.getDirectionY() == YDirectionType::Standard) + and (wave_speed_in.getDirectionY() == YDirectionType::Standard)); + + Field3D f = are_unaligned ? toFieldAligned(f_in, "RGN_NOX") : f_in; + Field3D v = are_unaligned ? toFieldAligned(v_in, "RGN_NOX") : v_in; + Field3D wave_speed = + are_unaligned ? toFieldAligned(wave_speed_in, "RGN_NOX") : wave_speed_in; + + Coordinates* coord = f_in.getCoordinates(); + + Field3D result{zeroFrom(f)}; + + for (int i = mesh->xstart; i <= mesh->xend; i++) { + const bool is_periodic_y = mesh->periodicY(i); + const bool is_first_y = mesh->firstY(i); + const bool is_last_y = mesh->lastY(i); + + // Only need one guard cell, so no need to communicate fluxes Instead + // calculate in guard cells to get fluxes consistent between processors, but + // don't include the boundary cell. Note that this implies special handling + // of boundaries later + const int ys = (!is_first_y || is_periodic_y) ? mesh->ystart - 1 : mesh->ystart; + const int ye = (!is_last_y || is_periodic_y) ? mesh->yend + 1 : mesh->yend; + + for (int j = ys; j <= ye; j++) { + // Pre-calculate factors which multiply fluxes +#if not(BOUT_USE_METRIC_3D) + // For right cell boundaries + const BoutReal area_r = coord->cell_area_yhigh()(i, j); + const BoutReal flux_factor_rc = area_r / coord->cell_volume()(i, j); + const BoutReal flux_factor_rp = area_r / coord->cell_volume()(i, j + 1); + // For left cell boundaries + const BoutReal area_l = coord->cell_area_ylow()(i, j); + const BoutReal flux_factor_lc = area_l / coord->cell_volume()(i, j); + const BoutReal flux_factor_lm = area_l / coord->cell_volume()(i, j - 1); +#endif + for (int k = mesh->zstart; k <= mesh->zend; k++) { +#if BOUT_USE_METRIC_3D + // For right cell boundaries + const BoutReal area_r = coord->cell_area_yhigh()(i, j, k); + const BoutReal flux_factor_rc = area_r / coord->cell_volume()(i, j, k); + const BoutReal flux_factor_rp = area_r / coord->cell_volume()(i, j + 1, k); + // For left cell boundaries + const BoutReal area_l = coord->cell_area_ylow()(i, j, k); + const BoutReal flux_factor_lc = area_l / coord->cell_volume()(i, j, k); + const BoutReal flux_factor_lm = area_l / coord->cell_volume()(i, j - 1, k); +#endif + + //////////////////////////////////////////// + // Reconstruct f at the cell faces + // This calculates s.R and s.L for the Right and Left + // face values on this cell + + // Reconstruct f at the cell faces + Stencil1D s; + s.c = f(i, j, k); + s.m = f(i, j - 1, k); + s.p = f(i, j + 1, k); + + cellboundary(s); // Calculate s.R and s.L + + //////////////////////////////////////////// + // Right boundary + + // Calculate velocity at right boundary (y+1/2) + BoutReal vpar = 0.5 * (v(i, j, k) + v(i, j + 1, k)); + BoutReal flux = BoutNaN; + + if (is_last_y && (j == mesh->yend) && !is_periodic_y) { + // Last point in domain + + const BoutReal bndryval = 0.5 * (s.c + s.p); + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux = bndryval * vpar; + } else { + // Add flux due to difference in boundary values + flux = (s.R * vpar) + (wave_speed(i, j, k) * (s.R - bndryval)); + } + } else { + + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j + 1, k)); + + if (vpar > amax) { + // Supersonic flow out of this cell + flux = s.R * vpar; + } else if (vpar < -amax) { + // Supersonic flow into this cell + flux = 0.0; + } else { + // Subsonic flow, so a mix of right and left fluxes + flux = s.R * 0.5 * (vpar + amax); + } + } + + result(i, j, k) += flux * flux_factor_rc; + result(i, j + 1, k) -= flux * flux_factor_rp; + + //////////////////////////////////////////// + // Calculate at left boundary + + vpar = 0.5 * (v(i, j, k) + v(i, j - 1, k)); + + if (is_first_y && (j == mesh->ystart) && !is_periodic_y) { + // First point in domain + const BoutReal bndryval = 0.5 * (s.c + s.m); + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux = bndryval * vpar; + } else { + // Add flux due to difference in boundary values + flux = (s.L * vpar) - (wave_speed(i, j, k) * (s.L - bndryval)); + } + } else { + + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j - 1, k)); + + if (vpar < -amax) { + // Supersonic out of this cell + flux = s.L * vpar; + } else if (vpar > amax) { + // Supersonic into this cell + flux = 0.0; + } else { + flux = s.L * 0.5 * (vpar - amax); + } + } + + result(i, j, k) -= flux * flux_factor_lc; + result(i, j - 1, k) += flux * flux_factor_lm; + } + } + } + return are_unaligned ? fromFieldAligned(result, "RGN_NOBNDRY") : result; +} + +/*! + * Div ( n * v ) -- Magnetic drifts + * + * This uses the expression + * + * Div( A ) = 1/J * d/di ( J * A^i ) + * + * Hence the input vector should be contravariant + * + * Note: Uses to/from FieldAligned + * + */ +template +Field3D Div_f_v(const Field3D& n_in, const Vector3D& v, bool bndry_flux) { + ASSERT1(n_in.getLocation() == v.getLocation()); + ASSERT1_FIELDS_COMPATIBLE(n_in, v.x); + + const Mesh* mesh = n_in.getMesh(); + + CellEdges cellboundary; + + Coordinates* coord = n_in.getCoordinates(); + + if (v.covariant) { + // Got a covariant vector instead + throw BoutException("Div_f_v passed a covariant v"); + } + + Field3D result{zeroFrom(n_in)}; + + Field3D vx = v.x; + Field3D vz = v.z; + Field3D n = n_in; + + BOUT_FOR(i, result.getRegion("RGN_NOBNDRY")) { + // Calculate velocities + const BoutReal vU = + 0.25 * (vz[i.zp()] + vz[i]) * (coord->J()[i.zp()] + coord->J()[i]); + const BoutReal vD = + 0.25 * (vz[i.zm()] + vz[i]) * (coord->J()[i.zm()] + coord->J()[i]); + const BoutReal vL = + 0.25 * (vx[i.xm()] + vx[i]) * (coord->J()[i.xm()] + coord->J()[i]); + const BoutReal vR = + 0.25 * (vx[i.xp()] + vx[i]) * (coord->J()[i.xp()] + coord->J()[i]); + + // X direction + Stencil1D s; + s.c = n[i]; + s.m = n[i.xm()]; + s.mm = n[i.xmm()]; + s.p = n[i.xp()]; + s.pp = n[i.xpp()]; + + cellboundary(s); + + if ((i.x() == mesh->xend) && (mesh->lastX())) { + // At right boundary in X + if (bndry_flux) { + BoutReal flux = BoutNaN; + if (vR > 0.0) { + // Flux to boundary + flux = vR * s.R; + } else { + // Flux in from boundary + flux = vR * 0.5 * (n[i.xp()] + n[i]); + } + result[i] += flux / (coord->dx()[i] * coord->J()[i]); + result[i.xp()] -= flux / (coord->dx()[i.xp()] * coord->J()[i.xp()]); + } + } else { + // Not at a boundary + if (vR > 0.0) { + // Flux out into next cell + const BoutReal flux = vR * s.R; + result[i] += flux / (coord->dx()[i] * coord->J()[i]); + result[i.xp()] -= flux / (coord->dx()[i.xp()] * coord->J()[i.xp()]); + } + } + + // Left side + + if ((i.x() == mesh->xstart) && (mesh->firstX())) { + // At left boundary in X + + if (bndry_flux) { + BoutReal flux = BoutNaN; + if (vL < 0.0) { + // Flux to boundary + flux = vL * s.L; + } else { + // Flux in from boundary + flux = vL * 0.5 * (n[i.xm()] + n[i]); + } + result[i] -= flux / (coord->dx()[i] * coord->J()[i]); + result[i.xm()] += flux / (coord->dx()[i.xm()] * coord->J()[i.xm()]); + } + } else { + // Not at a boundary + if (vL < 0.0) { + const BoutReal flux = vL * s.L; + result[i] -= flux / (coord->dx()[i] * coord->J()[i]); + result[i.xm()] += flux / (coord->dx()[i.xm()] * coord->J()[i.xm()]); + } + } + + /// NOTE: Need to communicate fluxes + + // Z direction + s.m = n[i.zm()]; + s.mm = n[i.zmm()]; + s.p = n[i.zp()]; + s.pp = n[i.zpp()]; + + cellboundary(s); + + if (vU > 0.0) { + const BoutReal flux = vU * s.R; + result[i] += flux / (coord->J()[i] * coord->dz()[i]); + result[i.zp()] -= flux / (coord->J()[i.zp()] * coord->dz()[i.zp()]); + } + if (vD < 0.0) { + const BoutReal flux = vD * s.L; + result[i] -= flux / (coord->J()[i] * coord->dz()[i]); + result[i.zm()] += flux / (coord->J()[i.zm()] * coord->dz()[i.zm()]); + } + } + + communicateFluxes(result); + + // Y advection + // Currently just using simple centered differences + // so no fluxes need to be exchanged + + n = toFieldAligned(n_in, "RGN_NOX"); + Field3D vy = toFieldAligned(v.y, "RGN_NOX"); + + Field3D yresult = 0.0; + yresult.setDirectionY(YDirectionType::Aligned); + + BOUT_FOR(i, result.getRegion("RGN_NOBNDRY")) { + // Y velocities on y boundaries + const BoutReal vU = + 0.25 * (vy[i] + vy[i.yp()]) * (coord->J()[i] + coord->J()[i.yp()]); + const BoutReal vD = + 0.25 * (vy[i] + vy[i.ym()]) * (coord->J()[i] + coord->J()[i.ym()]); + + // n (advected quantity) on y boundaries + // Note: Use unshifted n_in variable + const BoutReal nU = 0.5 * (n[i] + n[i.yp()]); + const BoutReal nD = 0.5 * (n[i] + n[i.ym()]); + + yresult[i] = (nU * vU - nD * vD) / (coord->J()[i] * coord->dy()[i]); + } + return result + fromFieldAligned(yresult, "RGN_NOBNDRY"); +} + +/// Finite volume parallel divergence +/// +/// NOTE: Modified version, applies limiter to velocity and field +/// Performs better (smaller overshoots) than Div_par +/// +/// Preserves the sum of f*J*dx*dy*dz over the domain +/// +/// @param[in] f_in The field being advected. +/// This will be reconstructed at cell faces +/// using the given CellEdges method +/// @param[in] v_in The advection velocity. +/// This will be interpolated to cell boundaries +/// using linear interpolation +/// @param[in] wave_speed_in Local maximum speed of all waves in the system at each +// point in space +/// @param[in] fixflux Fix the flux at the boundary to be the value at the +/// midpoint (for boundary conditions) +/// +/// @param[out] flow_ylow Flow at the lower Y cell boundary +/// Already includes area factor * flux +template +Field3D Div_par_mod(const Field3D& f_in, const Field3D& v_in, + const Field3D& wave_speed_in, Field3D& flow_ylow, bool fixflux, + bool dissipative) { + + Coordinates* coord = f_in.getCoordinates(); + ASSERT1_FIELDS_COMPATIBLE(f_in, v_in); + + if (f_in.isFci()) { + // Use mid-point (cell boundary) averages + + ASSERT1(f_in.hasParallelSlices()); + ASSERT1(v_in.hasParallelSlices()); + + const auto& f_up = f_in.yup(); + const auto& f_down = f_in.ydown(); + + const auto& v_up = v_in.yup(); + const auto& v_down = v_in.ydown(); + + Field3D result{emptyFrom(f_in)}; + flow_ylow = zeroFrom(f_in); + BOUT_FOR(i, f_in.getRegion("RGN_NOBNDRY")) { + const auto iyp = i.yp(); + const auto iym = i.ym(); + + result[i] = (0.25 * (f_in[i] + f_up[iyp]) * (v_in[i] + v_up[iyp]) + * coord->cell_area_yhigh()[i] + - 0.25 * (f_in[i] + f_down[iym]) * (v_in[i] + v_down[iym]) + * coord->cell_area_ylow()[i]) + / coord->cell_volume()[i]; + + if (dissipative) { + const BoutReal amax = BOUTMAX(fabs(wave_speed_in[i]), fabs(v_in[i]), + fabs(v_up[iyp]), fabs(v_down[iym])); + result[i] += (0.5 * amax * (f_in[i] - f_up[iyp]) * coord->cell_area_yhigh()[i] + + 0.5 * amax * (f_in[i] - f_down[iym]) * coord->cell_area_ylow()[i]) + / coord->cell_volume()[i]; + } + } + return result; + } + ASSERT1_FIELDS_COMPATIBLE(f_in, wave_speed_in); + + // Throw error when not Fci + if (dissipative) { + throw BoutException("Using dissipative flag in Div_par_mod but no Fci parallel " + "transform. This flag will have no impact on the simulation"); + } + + const Mesh* mesh = f_in.getMesh(); + + CellEdges cellboundary; + + ASSERT2(f_in.getDirectionY() == v_in.getDirectionY()); + ASSERT2(f_in.getDirectionY() == wave_speed_in.getDirectionY()); + const bool are_unaligned = + ((f_in.getDirectionY() == YDirectionType::Standard) + and (v_in.getDirectionY() == YDirectionType::Standard) + and (wave_speed_in.getDirectionY() == YDirectionType::Standard)); + + const Field3D f = are_unaligned ? toFieldAligned(f_in, "RGN_NOX") : f_in; + const Field3D v = are_unaligned ? toFieldAligned(v_in, "RGN_NOX") : v_in; + const Field3D wave_speed = + are_unaligned ? toFieldAligned(wave_speed_in, "RGN_NOX") : wave_speed_in; + + Field3D result{zeroFrom(f)}; + flow_ylow = zeroFrom(f); + + for (int i = mesh->xstart; i <= mesh->xend; i++) { + const bool is_periodic_y = mesh->periodicY(i); + const bool is_first_y = mesh->firstY(i); + const bool is_last_y = mesh->lastY(i); + + // Only need one guard cell, so no need to communicate fluxes Instead + // calculate in guard cells to get fluxes consistent between processors, but + // don't include the boundary cell. Note that this implies special handling + // of boundaries later + const int ys = (!is_first_y || is_periodic_y) ? mesh->ystart - 1 : mesh->ystart; + const int ye = (!is_last_y || is_periodic_y) ? mesh->yend + 1 : mesh->yend; + + for (int j = ys; j <= ye; j++) { + // Pre-calculate factors which multiply fluxes +#if not(BOUT_USE_METRIC_3D) + // For right cell boundaries + const BoutReal area_rp = coord->cell_area_yhigh()(i, j); + + const BoutReal flux_factor_rc = area_rp / coord->cell_volume()(i, j); + const BoutReal flux_factor_rp = area_rp / coord->cell_volume()(i, j + 1); + + // For left cell boundaries + const BoutReal area_lc = coord->cell_area_ylow()(i, j); + + const BoutReal flux_factor_lc = area_lc / coord->cell_volume()(i, j); + const BoutReal flux_factor_lm = area_lc / coord->cell_volume()(i, j - 1); +#endif + for (int k = 0; k < mesh->LocalNz; k++) { +#if BOUT_USE_METRIC_3D + // For right cell boundaries + const BoutReal area_rp = coord->cell_area_yhigh()(i, j, k); + + const BoutReal flux_factor_rc = area_rp / coord->cell_volume()(i, j, k); + const BoutReal flux_factor_rp = area_rp / coord->cell_volume()(i, j + 1, k); + + // For left cell boundaries + const BoutReal area_lc = coord->cell_area_ylow()(i, j, k); + + const BoutReal flux_factor_lc = area_lc / coord->cell_volume()(i, j, k); + const BoutReal flux_factor_lm = area_lc / coord->cell_volume()(i, j - 1, k); +#endif + + //////////////////////////////////////////// + // Reconstruct f at the cell faces + // This calculates s.R and s.L for the Right and Left + // face values on this cell + + // Reconstruct f at the cell faces + Stencil1D s{.c = f(i, j, k), .m = f(i, j - 1, k), .p = f(i, j + 1, k)}; + cellboundary(s); // Calculate s.R and s.L + + //////////////////////////////////////////// + // Reconstruct v at the cell faces + Stencil1D sv{.c = v(i, j, k), .m = v(i, j - 1, k), .p = v(i, j + 1, k)}; + cellboundary(sv); // Calculate sv.R and sv.L + + //////////////////////////////////////////// + // Right boundary + + BoutReal flux = BoutNaN; + + if (is_last_y && (j == mesh->yend) && !is_periodic_y) { + // Last point in domain + + // Calculate velocity at right boundary (y+1/2) + const BoutReal vpar = 0.5 * (v(i, j, k) + v(i, j + 1, k)); + + const BoutReal bndryval = 0.5 * (s.c + s.p); + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux = bndryval * vpar; + } else { + // Add flux due to difference in boundary values + flux = (s.R * vpar) + (wave_speed(i, j, k) * (s.R - bndryval)); + } + + } else { + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j + 1, k), + std::abs(v(i, j, k)), std::abs(v(i, j + 1, k))); + + flux = s.R * 0.5 * (sv.R + amax); + } + + result(i, j, k) += flux * flux_factor_rc; + result(i, j + 1, k) -= flux * flux_factor_rp; + + flow_ylow(i, j + 1, k) += flux * area_rp; + + //////////////////////////////////////////// + // Calculate at left boundary + + if (is_first_y && (j == mesh->ystart) && !is_periodic_y) { + // First point in domain + const BoutReal bndryval = 0.5 * (s.c + s.m); + const BoutReal vpar = 0.5 * (v(i, j, k) + v(i, j - 1, k)); + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux = bndryval * vpar; + } else { + // Add flux due to difference in boundary values + flux = (s.L * vpar) - (wave_speed(i, j, k) * (s.L - bndryval)); + } + } else { + + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j - 1, k), + std::abs(v(i, j, k)), std::abs(v(i, j - 1, k))); + + flux = s.L * 0.5 * (sv.L - amax); + } + + result(i, j, k) -= flux * flux_factor_lc; + result(i, j - 1, k) += flux * flux_factor_lm; + + flow_ylow(i, j, k) += flux * area_lc; + } + } + } + if (are_unaligned) { + flow_ylow = fromFieldAligned(flow_ylow, "RGN_NOBNDRY"); + } + return are_unaligned ? fromFieldAligned(result, "RGN_NOBNDRY") : result; +} + +/// This operator calculates Div_par(f v v) +/// It is used primarily (only?) in the parallel momentum equation. +/// +/// This operator is used rather than Div(f fv) so that the values of +/// f and v are consistent with other advection equations: The product +/// fv is not interpolated to cell boundaries. +template +Field3D Div_par_fvv(const Field3D& f_in, const Field3D& v_in, + const Field3D& wave_speed_in, bool fixflux) { + ASSERT1_FIELDS_COMPATIBLE(f_in, v_in); + const Mesh* mesh = f_in.getMesh(); + const Coordinates* coord = f_in.getCoordinates(); + CellEdges cellboundary; + + if (f_in.isFci()) { + // FCI version, using yup/down fields + ASSERT1(f_in.hasParallelSlices()); + ASSERT1(v_in.hasParallelSlices()); + + const auto& B = coord->Bxy(); + const auto& B_up = coord->Bxy().yup(); + const auto& B_down = coord->Bxy().ydown(); + + const auto& f_up = f_in.yup(); + const auto& f_down = f_in.ydown(); + + const auto& v_up = v_in.yup(); + const auto& v_down = v_in.ydown(); + + const auto& g_22 = coord->g_22(); + const auto& dy = coord->dy(); + + Field3D result{emptyFrom(f_in)}; + BOUT_FOR(i, f_in.getRegion("RGN_NOBNDRY")) { + const auto iyp = i.yp(); + const auto iym = i.ym(); + + // Maximum local wave speed + const BoutReal amax = BOUTMAX(wave_speed_in[i], std::abs(v_in[i]), + std::abs(v_up[iyp]), std::abs(v_down[iym])); + + const BoutReal term = (f_up[iyp] * v_up[iyp] * v_up[iyp] / B_up[iyp]) + - (f_down[iym] * v_down[iym] * v_down[iym] / B_down[iym]); + + // Penalty terms. This implementation is very dissipative. + BoutReal penalty = + (amax * (f_in[i] * v_in[i] - f_up[iyp] * v_up[iyp]) / (B[i] + B_up[iyp])) + + (amax * (f_in[i] * v_in[i] - f_down[iym] * v_down[iym]) + / (B[i] + B_down[iym])); + + if (std::abs(penalty) > std::abs(term) and penalty * v_in[i] > 0) { + if (term * penalty > 0) { + penalty = term; + } else { + penalty = -term; + } + } + + result[i] = B[i] * (term + penalty) / (2 * dy[i] * sqrt(g_22[i])); + +#if CHECK > 0 + if (!std::isfinite(result[i])) { + throw BoutException("Non-finite value in Div_par_fvv at {}\n" + "fup {} vup {} fdown {} vdown {} amax {}\n", + "B {} Bup {} Bdown {} dy {} sqrt(g_22} {}", i, f_up[i], + v_up[i], f_down[i], v_down[i], amax, B[i], B_up[i], B_down[i], + dy[i], sqrt(g_22[i])); + } +#endif + } + return result; + } + + ASSERT1(areFieldsCompatible(f_in, wave_speed_in)); + + /// Ensure that f, v and wave_speed are field aligned + Field3D f = toFieldAligned(f_in, "RGN_NOX"); + Field3D v = toFieldAligned(v_in, "RGN_NOX"); + Field3D wave_speed = toFieldAligned(wave_speed_in, "RGN_NOX"); + + Field3D result{zeroFrom(f)}; + + for (int i = mesh->xstart; i <= mesh->xend; i++) { + const bool is_periodic_y = mesh->periodicY(i); + const bool is_first_y = mesh->firstY(i); + const bool is_last_y = mesh->lastY(i); + + // Only need one guard cell, so no need to communicate fluxes Instead + // calculate in guard cells to get fluxes consistent between processors, but + // don't include the boundary cell. Note that this implies special handling + // of boundaries later + const int ys = (!is_first_y || is_periodic_y) ? mesh->ystart - 1 : mesh->ystart; + const int ye = (!is_last_y || is_periodic_y) ? mesh->yend + 1 : mesh->yend; + + for (int j = ys; j <= ye; j++) { + // Pre-calculate factors which multiply fluxes + + for (int k = 0; k < mesh->LocalNz; k++) { + // For right cell boundaries + const BoutReal area_r = coord->cell_area_yhigh()(i, j, k); + + const BoutReal flux_factor_rc = area_r / coord->cell_volume()(i, j, k); + const BoutReal flux_factor_rp = area_r / coord->cell_volume()(i, j + 1, k); + + // For left cell boundaries + const BoutReal area_l = coord->cell_area_ylow()(i, j, k); + + const BoutReal flux_factor_lc = area_l / coord->cell_volume()(i, j, k); + const BoutReal flux_factor_lm = area_l / coord->cell_volume()(i, j - 1, k); + + //////////////////////////////////////////// + // Reconstruct f at the cell faces + // This calculates s.R and s.L for the Right and Left + // face values on this cell + + // Reconstruct f at the cell faces + Stencil1D s{.c = f(i, j, k), .m = f(i, j - 1, k), .p = f(i, j + 1, k)}; + cellboundary(s); // Calculate s.R and s.L + + //////////////////////////////////////////// + // Reconstruct v at the cell faces + Stencil1D sv{.c = v(i, j, k), .m = v(i, j - 1, k), .p = v(i, j + 1, k)}; + cellboundary(sv); + + //////////////////////////////////////////// + // Right boundary + + // Calculate velocity at right boundary (y+1/2) + const BoutReal v_mid_r = 0.5 * (sv.c + sv.p); + // And mid-point density at right boundary + const BoutReal n_mid_r = 0.5 * (s.c + s.p); + BoutReal flux = BoutNaN; + + if (mesh->lastY(i) && (j == mesh->yend) && !mesh->periodicY(i)) { + // Last point in domain + + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux = n_mid_r * v_mid_r * v_mid_r; + } else { + // Add flux due to difference in boundary values + flux = + (s.R * sv.R * sv.R) // Use right cell edge values + + (BOUTMAX(wave_speed(i, j, k), std::abs(sv.c), std::abs(sv.p)) * n_mid_r + * (sv.R - v_mid_r)); // Damp differences in velocity, not flux + } + } else { + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j + 1, k), + std::abs(sv.c), std::abs(sv.p)); + + flux = s.R * 0.5 * (sv.R + amax) * sv.R; + } + + result(i, j, k) += flux * flux_factor_rc; + result(i, j + 1, k) -= flux * flux_factor_rp; + + //////////////////////////////////////////// + // Calculate at left boundary + + const BoutReal v_mid_l = 0.5 * (sv.c + sv.m); + const BoutReal n_mid_l = 0.5 * (s.c + s.m); + + if (mesh->firstY(i) && (j == mesh->ystart) && !mesh->periodicY(i)) { + // First point in domain + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux = n_mid_l * v_mid_l * v_mid_l; + } else { + // Add flux due to difference in boundary values + flux = (s.L * sv.L * sv.L) + - (BOUTMAX(wave_speed(i, j, k), std::abs(sv.c), std::abs(sv.m)) + * n_mid_l * (sv.L - v_mid_l)); + } + } else { + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j - 1, k), + std::abs(sv.c), std::abs(sv.m)); + + flux = s.L * 0.5 * (sv.L - amax) * sv.L; + } + + result(i, j, k) -= flux * flux_factor_lc; + result(i, j - 1, k) += flux * flux_factor_lm; + } + } + } + return fromFieldAligned(result, "RGN_NOBNDRY"); +} + +// Calculates viscous heating due to numerical momentum fluxes +// and flow of kinetic energy (in flow_ylow) +template +Field3D Div_par_fvv_heating(const Field3D& f_in, const Field3D& v_in, + const Field3D& wave_speed_in, Field3D& flow_ylow, + bool fixflux) { + + ASSERT1(areFieldsCompatible(f_in, v_in)); + ASSERT1(areFieldsCompatible(f_in, wave_speed_in)); + + const Mesh* mesh = f_in.getMesh(); + Coordinates* coord = f_in.getCoordinates(); + CellEdges cellboundary; + + if (f_in.isFci()) { + // FCI version, using yup/down fields + ASSERT1(f_in.hasParallelSlices()); + ASSERT1(v_in.hasParallelSlices()); + + const auto B = coord->Bxy(); + const auto B_up = coord->Bxy().yup(); + const auto B_down = coord->Bxy().ydown(); + + const auto& f_up = f_in.yup(); + const auto& f_down = f_in.ydown(); + + const auto& v_up = v_in.yup(); + const auto& v_down = v_in.ydown(); + + const auto g_22 = coord->g_22(); + const auto dy = coord->dy(); + + Field3D result{emptyFrom(f_in)}; + flow_ylow = zeroFrom(f_in); + + BOUT_FOR(i, f_in.getRegion("RGN_NOBNDRY")) { + const auto iyp = i.yp(); + const auto iym = i.ym(); + + //Maximum local wave speed + const BoutReal amax = BOUTMAX(wave_speed_in[i], std::abs(v_in[i]), + std::abs(v_up[iyp]), std::abs(v_down[iym])); + + result[i] = + B[i] + * ((f_up[iyp] * v_up[iyp] * v_up[iyp] / B_up[iyp]) + - (f_down[iym] * v_down[iym] * v_down[iym] / B_down[iym]) + // Penalty terms. This implementation is very dissipative. + // Note: This version adds a viscosity that damps gradients of velocity + + amax * (f_in[i] + f_up[iyp]) * (v_in[i] - v_up[iyp]) / (B[i] + B_up[iyp]) + + amax * (f_in[i] + f_down[iym]) * (v_in[i] - v_down[iym]) + / (B[i] + B_down[iym])) + / (2 * dy[i] * sqrt(g_22[i])); + +#if CHECK > 0 + if (!std::isfinite(result[i])) { + throw BoutException("Non-finite value in Div_par_fvv at {}\n" + "fup {} vup {} fdown {} vdown {} amax {}\n", + "B {} Bup {} Bdown {} dy {} sqrt(g_22} {}", i, f_up[i], + v_up[i], f_down[i], v_down[i], amax, B[i], B_up[i], B_down[i], + dy[i], sqrt(g_22[i])); + } +#endif + } + return result; + } + + /// Ensure that f, v and wave_speed are field aligned + Field3D f = toFieldAligned(f_in, "RGN_NOX"); + Field3D v = toFieldAligned(v_in, "RGN_NOX"); + Field3D wave_speed = toFieldAligned(wave_speed_in, "RGN_NOX"); + + // result and flow_ylow are field-aligned. + // Will be converted to non-aligned before return. + Field3D result{zeroFrom(f)}; + flow_ylow = zeroFrom(f); + + // Only need one guard cell, so no need to communicate fluxes + // Instead calculate in guard cells to preserve fluxes + int ys = mesh->ystart - 1; + int ye = mesh->yend + 1; + + for (int i = mesh->xstart; i <= mesh->xend; i++) { + + if (!mesh->firstY(i) || mesh->periodicY(i)) { + // Calculate in guard cell to get fluxes consistent between processors + ys = mesh->ystart - 1; + } else { + // Don't include the boundary cell. Note that this implies special + // handling of boundaries later + ys = mesh->ystart; + } + + if (!mesh->lastY(i) || mesh->periodicY(i)) { + // Calculate in guard cells + ye = mesh->yend + 1; + } else { + // Not in boundary cells + ye = mesh->yend; + } + + for (int j = ys; j <= ye; j++) { + for (int k = 0; k < mesh->LocalNz; k++) { + // Pre-calculate factors which multiply fluxes + // Note: In 3D metric geometries these quantities can depend on (i,j,k), + // so calculate inside the k loop. + + // For right cell boundaries + const BoutReal area_rp = coord->cell_area_yhigh()(i, j, k); + + const BoutReal flux_factor_rc = area_rp / coord->cell_volume()(i, j, k); + + // For left cell boundaries + const BoutReal area_lc = coord->cell_area_ylow()(i, j, k); + + const BoutReal flux_factor_lc = area_lc / coord->cell_volume()(i, j, k); + + //////////////////////////////////////////// + // Reconstruct f at the cell faces + // This calculates s.R and s.L for the Right and Left + // face values on this cell + + // Reconstruct f at the cell faces + Stencil1D s; + s.c = f(i, j, k); + s.m = f(i, j - 1, k); + s.p = f(i, j + 1, k); + + cellboundary(s); // Calculate s.R and s.L + + // Reconstruct v at the cell faces + Stencil1D sv; + sv.c = v(i, j, k); + sv.m = v(i, j - 1, k); + sv.p = v(i, j + 1, k); + + cellboundary(sv); + + //////////////////////////////////////////// + // Right boundary + + // Calculate velocity at right boundary (y+1/2) + BoutReal v_mid = 0.5 * (sv.c + sv.p); + // And mid-point density at right boundary + BoutReal n_mid = 0.5 * (s.c + s.p); + + if (mesh->lastY(i) && (j == mesh->yend) && !mesh->periodicY(i)) { + // Last point in domain + + // Expected loss of kinetic energy into boundary + // This is used in the sheath boundary condition to calculate + // energy losses. + const BoutReal expected_ke = 0.5 * n_mid * v_mid * v_mid * v_mid; + + BoutReal flux_mom = BoutNaN; + if (fixflux) { + // Mid-point consistent with boundary conditions + // but kinetic energy loss will not match expected + // -> Adjust energy balance in pressure equation + flux_mom = n_mid * v_mid * v_mid; + } else { + flux_mom = (s.R * sv.R * sv.R) + + (BOUTMAX(wave_speed(i, j, k), std::abs(sv.c), std::abs(sv.p)) + * (s.R * sv.R - n_mid * v_mid)); + } + + // Assume that particle flux is fixed to boundary value + const BoutReal flux_part = n_mid * v_mid; + + // d/dt(1/2 m n v^2) = v * d/dt(mnv) - 1/2 m v^2 * dn/dt + const BoutReal actual_ke = (sv.c * flux_mom) - (0.5 * sv.c * sv.c * flux_part); + + // Note: If the actual loss was higher than expected, then + // plasma heating is needed to compensate + result(i, j, k) += (actual_ke - expected_ke) * flux_factor_rc; + + // Final flow through boundary is the expected value + flow_ylow(i, j + 1, k) += expected_ke * area_rp; + + } else { + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j + 1, k), + std::abs(sv.c), std::abs(sv.p)); + + // Viscous heating due to relaxation of velocity towards midpoint + result(i, j, k) += + (amax + 0.5 * sv.R) * s.R * (sv.c - sv.p) * (sv.R - v_mid) * flux_factor_rc; + + // Kinetic energy flow into next cell. + // Note: Different from flow out of this cell; the difference + // is in the viscous heating. + const BoutReal flux_part = s.R * 0.5 * (sv.R + amax); + const BoutReal flux_mom = flux_part * sv.R; + + flow_ylow(i, j + 1, k) += + (sv.p * flux_mom - 0.5 * SQ(sv.p) * flux_part) * area_rp; + } + + //////////////////////////////////////////// + // Calculate at left boundary + + v_mid = 0.5 * (sv.c + sv.m); + n_mid = 0.5 * (s.c + s.m); + + // Expected KE loss. Note minus sign because negative v into boundary + const BoutReal expected_ke = -0.5 * n_mid * v_mid * v_mid * v_mid; + + if (mesh->firstY(i) && (j == mesh->ystart) && !mesh->periodicY(i)) { + // First point in domain + BoutReal flux_mom = BoutNaN; + if (fixflux) { + // Use mid-point to be consistent with boundary conditions + flux_mom = n_mid * v_mid * v_mid; + } else { + // Add flux due to difference in boundary values + flux_mom = (s.L * sv.L * sv.L) + - (BOUTMAX(wave_speed(i, j, k), std::abs(sv.c), std::abs(sv.m)) + * (s.L * sv.L - n_mid * v_mid)); + } + + // Assume that density flux is fixed to boundary value + const BoutReal flux_part = n_mid * v_mid; + + // d/dt(1/2 m n v^2) = v * d/dt(mnv) - 1/2 m v^2 * dn/dt + const BoutReal actual_ke = (-sv.c * flux_mom) + (0.5 * sv.c * sv.c * flux_part); + + result(i, j, k) += (actual_ke - expected_ke) * flux_factor_lc; + + flow_ylow(i, j, k) -= expected_ke * area_lc; + } else { + // Maximum wave speed in the two cells + const BoutReal amax = BOUTMAX(wave_speed(i, j, k), wave_speed(i, j - 1, k), + std::abs(sv.c), std::abs(sv.m)); + + // Viscous heating due to relaxation + result(i, j, k) += + (amax - 0.5 * sv.L) * s.L * (sv.c - sv.m) * (sv.L - v_mid) * flux_factor_lc; + + // Kinetic energy flow into this cell. + // Note: Different from flow out of left cell; the difference + // is in the viscous heating. + const BoutReal flux_part = s.L * 0.5 * (sv.L - amax); + const BoutReal flux_mom = flux_part * sv.L; + + flow_ylow(i, j, k) += (sv.c * flux_mom - 0.5 * SQ(sv.c) * flux_part) * area_lc; + } + } + } + } + flow_ylow = fromFieldAligned(flow_ylow, "RGN_NOBNDRY"); + return fromFieldAligned(result, "RGN_NOBNDRY"); +} + +/// Div ( a g Grad_perp(f) ) -- Perpendicular gradient-driven advection +/// +/// This version uses a slope limiter to calculate cell edge values of g in X, +/// the advects the upwind cell edge. +/// +/// 1st order upwinding is used in Y. +template +Field3D Div_a_Grad_perp_limit(const Field3D& a, const Field3D& g, const Field3D& f) { + ASSERT2(a.getLocation() == f.getLocation()); + + Mesh* mesh = a.getMesh(); + + // Requires at least 2 communication guard cells in X, 1 in Y + ASSERT1(mesh->xstart >= 2); + ASSERT1(mesh->ystart >= 1); + + CellEdges cellboundary; + + Field3D result{zeroFrom(f)}; + + Coordinates* coord = f.getCoordinates(); + + // Flux in x + + for (int i = mesh->xstart - 1; i <= mesh->xend; i++) { + for (int j = mesh->ystart; j <= mesh->yend; j++) { + for (int k = 0; k < mesh->LocalNz; k++) { + // Calculate flux from i to i+1 + + const BoutReal gradient = f(i + 1, j, k) - f(i, j, k); + + // Mid-point average boundary value of 'a' + const BoutReal aedge = 0.5 * (a(i + 1, j, k) + a(i, j, k)); + BoutReal gedge = BoutNaN; + if (((i == mesh->xstart - 1) and mesh->firstX()) + or ((i == mesh->xend) and mesh->lastX())) { + // Mid-point average boundary value of 'g' + gedge = 0.5 * (g(i + 1, j, k) + g(i, j, k)); + } else if (gradient > 0) { + // Flux is from (i+1) to (i) + // Reconstruct `g` at left of (i+1, j, k) + + Stencil1D sg; + sg.m = g(i, j, k); + sg.c = g(i + 1, j, k); + sg.p = g(i + 2, j, k); + cellboundary(sg); // Calculate sg.R and sg.L + + gedge = sg.L; + } else { + // Flux is from (i) to (i+1) + // Reconstruct `g` at right of (i, j, k) + + Stencil1D sg; + sg.m = g(i - 1, j, k); + sg.c = g(i, j, k); + sg.p = g(i + 1, j, k); + cellboundary(sg); // Calculate sg.R and sg.L + + gedge = sg.R; + } + + // Flux across cell edge + const BoutReal fout = gradient * aedge * gedge + * (coord->J(i, j, k) * coord->g11(i, j, k) + + coord->J(i + 1, j, k) * coord->g11(i + 1, j, k)) + / (coord->dx(i, j, k) + coord->dx(i + 1, j, k)); + + result(i, j, k) += fout / (coord->dx(i, j, k) * coord->J(i, j, k)); + result(i + 1, j, k) -= fout / (coord->dx(i + 1, j, k) * coord->J(i + 1, j, k)); + } + } + } + + const bool fci = + f.hasParallelSlices() && a.hasParallelSlices() && g.hasParallelSlices(); + +#if BOUT_USE_METRIC_3D + if (fci) { + // 3D Metric, need yup/ydown fields. + // Requires previous communication of metrics. + if (!coord->g23().hasParallelSlices() || !coord->g_23().hasParallelSlices() + || !coord->dy().hasParallelSlices() || !coord->dz().hasParallelSlices() + || !coord->Bxy().hasParallelSlices() || !coord->J().hasParallelSlices()) { + throw BoutException("metrics have no yup/down!"); + } + } +#endif + + // Y and Z fluxes require Y derivatives + + // Values on this y slice (centre). + // This is needed because toFieldAligned may modify the field + const auto f_slice = makeslices(fci, f); + const auto a_slice = makeslices(fci, a); + const auto g_slice = makeslices(fci, g); + +#if BOUT_USE_METRIC_3D + const bool metric_fci = fci; +#else + constexpr bool metric_fci = false; +#endif + const auto g23 = makeslices(metric_fci, coord->g23()); + const auto g_23 = makeslices(metric_fci, coord->g_23()); + const auto J = makeslices(metric_fci, coord->J()); + const auto dy = makeslices(metric_fci, coord->dy()); + const auto dz = makeslices(metric_fci, coord->dz()); + const auto Bxy = makeslices(metric_fci, coord->Bxy()); + + // Result of the Y and Z fluxes + Field3D yzresult(0.0, mesh); + if (!fci) { + yzresult.setDirectionY(YDirectionType::Aligned); + } + + // Y flux + + for (int i = mesh->xstart; i <= mesh->xend; i++) { + for (int j = mesh->ystart; j <= mesh->yend; j++) { +#if BOUT_USE_METRIC_3D + for (int k = 0; k < mesh->LocalNz; k++) +#else + const int k = 0; +#endif + { + const BoutReal coef_u = + 0.5 + * (g_23.c(i, j, k) / SQ(J.c(i, j, k) * Bxy.c(i, j, k)) + + g_23.up(i, j + 1, k) / SQ(J.up(i, j + 1, k) * Bxy.up(i, j + 1, k))); + + const BoutReal coef_d = + 0.5 + * (g_23.c(i, j, k) / SQ(J.c(i, j, k) * Bxy.c(i, j, k)) + + g_23.down(i, j - 1, k) + / SQ(J.down(i, j - 1, k) * Bxy.down(i, j - 1, k))); + +#if not BOUT_USE_METRIC_3D + for (int k = 0; k < mesh->LocalNz; k++) +#endif + { + // Calculate flux between j and j+1 + const int kp = (k + 1) % mesh->LocalNz; + const int km = (k - 1 + mesh->LocalNz) % mesh->LocalNz; + + // Calculate Z derivative at y boundary + BoutReal dfdz = 0.5 + * (f_slice.c(i, j, kp) - f_slice.c(i, j, km) + + f_slice.up(i, j + 1, kp) - f_slice.up(i, j + 1, km)) + / (dz.c(i, j, k) + dz.up(i, j + 1, k)); + + // Y derivative + BoutReal dfdy = 2. * (f_slice.up(i, j + 1, k) - f_slice.c(i, j, k)) + / (dy.up(i, j + 1, k) + dy.c(i, j, k)); + + BoutReal aedge = 0.5 * (a_slice.c(i, j, k) + a_slice.up(i, j + 1, k)); + BoutReal gedge = BoutNaN; + if ((j == mesh->yend) and mesh->lastY(i)) { + // Midpoint boundary value + gedge = 0.5 * (g_slice.c(i, j, k) + g_slice.up(i, j + 1, k)); + } else if (dfdy > 0) { + // Flux from (j+1) to (j) + gedge = g_slice.up(i, j + 1, k); + } else { + // Flux from (j) to (j+1) + gedge = g_slice.c(i, j, k); + } + + BoutReal fout = + aedge * gedge * 0.5 + * (J.c(i, j, k) * g23.c(i, j, k) + J.up(i, j + 1, k) * g23.up(i, j + 1, k)) + * (dfdz - coef_u * dfdy); + + yzresult(i, j, k) += fout / (dy.c(i, j, k) * J.c(i, j, k)); + + // Calculate flux between j and j-1 + dfdz = 0.5 + * (f_slice.c(i, j, kp) - f_slice.c(i, j, km) + f_slice.down(i, j - 1, kp) + - f_slice.down(i, j - 1, km)) + / (dz.c(i, j, k) + dz.down(i, j - 1, k)); + + dfdy = 2. * (f_slice.c(i, j, k) - f_slice.down(i, j - 1, k)) + / (dy.c(i, j, k) + dy.down(i, j - 1, k)); + + aedge = 0.5 * (a_slice.c(i, j, k) + a_slice.down(i, j - 1, k)); + if ((j == mesh->ystart) and mesh->firstY(i)) { + gedge = 0.5 * (g_slice.c(i, j, k) + g_slice.down(i, j - 1, k)); + } else if (dfdy > 0) { + gedge = g_slice.c(i, j, k); + } else { + gedge = g_slice.down(i, j - 1, k); + } + + fout = aedge * gedge * 0.5 + * (J.c(i, j, k) * g23.c(i, j, k) + + J.down(i, j - 1, k) * g23.down(i, j - 1, k)) + * (dfdz - coef_d * dfdy); + + yzresult(i, j, k) -= fout / (dy.c(i, j, k) * J.c(i, j, k)); + } + } + } + } + + // Z flux + // Easier since all metrics constant in Z + + for (int i = mesh->xstart; i <= mesh->xend; i++) { + for (int j = mesh->ystart; j <= mesh->yend; j++) { +#if BOUT_USE_METRIC_3D + for (int k = 0; k < mesh->LocalNz; k++) +#else + const int k = 0; +#endif + { + // Coefficient in front of df/dy term + const BoutReal coef = + g_23.c(i, j, k) + / (dy.up(i, j + 1, k) + 2. * dy.c(i, j, k) + dy.down(i, j - 1, k)) + / SQ(J.c(i, j, k) * Bxy.c(i, j, k)); +#if not BOUT_USE_METRIC_3D + for (int k = 0; k < mesh->LocalNz; k++) +#endif + { + // Calculate flux between k and k+1 + const int kp = (k + 1) % mesh->LocalNz; + + const BoutReal gradient = + // df/dz + ((f_slice.c(i, j, kp) - f_slice.c(i, j, k)) / dz.c(i, j, k)) + + // - g_yz * df/dy / SQ(J*B) + - (coef + * (f_slice.up(i, j + 1, k) + f_slice.up(i, j + 1, kp) + - f_slice.down(i, j - 1, k) - f_slice.down(i, j - 1, kp))); + + const BoutReal fout = + gradient * 0.5 * (a_slice.c(i, j, kp) + a_slice.c(i, j, k)) + * ((gradient > 0) ? g_slice.c(i, j, kp) : g_slice.c(i, j, k)); + + yzresult(i, j, k) += fout / dz.c(i, j, k); + yzresult(i, j, kp) -= fout / dz.c(i, j, kp); + } + } + } + } + // Check if we need to transform back + if (fci) { + result += yzresult; + } else { + result += fromFieldAligned(yzresult); + } + return result; +} + +} // namespace FV +#endif // BOUT_FV_OPS_H diff --git a/include/bout/g_values.hxx b/include/bout/g_values.hxx new file mode 100644 index 0000000000..cbbd6d24ff --- /dev/null +++ b/include/bout/g_values.hxx @@ -0,0 +1,28 @@ +#ifndef BOUT_GVALUES_HXX +#define BOUT_GVALUES_HXX + +#include + +class Coordinates; + +/// `GValues` needs renaming, when we know what the name should be +class GValues { +public: + explicit GValues(const Coordinates& coordinates); + + const bout::FieldMetric& G1() const { return G1_m; } + const bout::FieldMetric& G2() const { return G2_m; } + const bout::FieldMetric& G3() const { return G3_m; } + + template + void map(F function) { + G1_m = function(G1_m); + G2_m = function(G2_m); + G3_m = function(G3_m); + } + +private: + bout::FieldMetric G1_m, G2_m, G3_m; +}; + +#endif //BOUT_GVALUES_HXX diff --git a/include/bout/generic_factory.hxx b/include/bout/generic_factory.hxx index 9493ef77f1..589431bc2a 100644 --- a/include/bout/generic_factory.hxx +++ b/include/bout/generic_factory.hxx @@ -1,5 +1,9 @@ +/// \file /// Base type for factories +// Copyright 2018-2022 Peter Hill, BOUT++ Team +// SPDX-License-Identifier: MIT + #pragma once #ifndef BOUT_GENERIC_FACTORY_H #define BOUT_GENERIC_FACTORY_H @@ -48,6 +52,14 @@ /// RegisterInFactory register("derived_type"); /// auto foo = MyFactory::getInstance().create("derived_type"); /// +/// In a .cxx file the static members should be declared: +/// +/// constexpr decltype(MyFactory::type_name) MyFactory::type_name; +/// constexpr decltype(MyFactory::section_name) MyFactory::section_name; +/// constexpr decltype(MyFactory::option_name) MyFactory::option_name; +/// constexpr decltype(MyFactory::default_type) MyFactory::default_type; +/// +/// /// @tparam BaseType The base class that this factory creates /// @tparam DerivedFactory The derived factory inheriting from this class /// @tparam TypeCreator The function signature for creating a new BaseType diff --git a/include/bout/git_metadata.hxx b/include/bout/git_metadata.hxx new file mode 100644 index 0000000000..0fc1018cdb --- /dev/null +++ b/include/bout/git_metadata.hxx @@ -0,0 +1,21 @@ +#ifndef BOUT_GIT_METADATA_H +#define BOUT_GIT_METADATA_H + +#include + +namespace bout { +namespace version { + +/// True if git metadata could be collected for this build. +auto git_metadata_available() -> bool; + +/// True if the source tree had tracked uncommitted changes at build time. +auto git_dirty() -> bool; + +/// Diff of tracked changes in the source tree at build time. +auto git_diff() -> std::string_view; + +} // namespace version +} // namespace bout + +#endif // BOUT_GIT_METADATA_H diff --git a/include/bout/globalindexer.hxx b/include/bout/globalindexer.hxx index e756ead3b2..8fa9c309b5 100644 --- a/include/bout/globalindexer.hxx +++ b/include/bout/globalindexer.hxx @@ -1,14 +1,21 @@ #ifndef BOUT_GLOBALINDEXER_H #define BOUT_GLOBALINDEXER_H +#include +#include #include #include #include +#include #include #include #include #include +#include +#include +#include + template class GlobalIndexer; @@ -86,7 +93,7 @@ public: int localSize = size(); MPI_Comm comm = - std::is_same_v ? fieldmesh->getXcomm() : BoutComm::get(); + std::is_same_v ? fieldmesh->getXZcomm() : BoutComm::get(); fieldmesh->getMpi().MPI_Scan(&localSize, &globalEnd, 1, MPI_INT, MPI_SUM, comm); globalEnd--; int counter = globalStart = globalEnd - size() + 1; diff --git a/include/bout/griddata.hxx b/include/bout/griddata.hxx index 29a32e5779..61a8a2b40b 100644 --- a/include/bout/griddata.hxx +++ b/include/bout/griddata.hxx @@ -2,9 +2,9 @@ * Functions to read input variables on a grid/mesh * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -28,12 +28,16 @@ class GridDataSource; #ifndef BOUT_GRIDDATA_H #define BOUT_GRIDDATA_H -#include "mesh.hxx" -#include "bout/bout_types.hxx" -#include "bout/options.hxx" - +#include +#include #include #include +#include +#include +#include + +#include +#include /// Interface class to serve grid data /*! @@ -46,8 +50,8 @@ public: GridDataSource(const bool source_is_file = false) : is_file(source_is_file) {} virtual ~GridDataSource() = default; - virtual bool - hasVar(const std::string& name) = 0; ///< Test if source can supply a variable + /// Test if source can supply a variable + virtual bool hasVar(const std::string& name) const = 0; /// Get a string virtual bool get(Mesh* m, std::string& sval, const std::string& name, @@ -71,6 +75,15 @@ public: static constexpr Direction Y = Direction::Y; static constexpr Direction Z = Direction::Z; + virtual bool get([[maybe_unused]] Array& var, + [[maybe_unused]] const std::string& name) { + return false; + } + virtual bool get([[maybe_unused]] Array& var, + [[maybe_unused]] const std::string& name) { + return false; + } + virtual bool get(Mesh* m, std::vector& var, const std::string& name, int len, int offset = 0, Direction dir = GridDataSource::X) = 0; virtual bool get(Mesh* m, std::vector& var, const std::string& name, int len, @@ -95,9 +108,9 @@ class GridFile : public GridDataSource { public: GridFile() = delete; GridFile(std::string gridfilename); - ~GridFile() = default; + ~GridFile() override = default; - bool hasVar(const std::string& name) override; + bool hasVar(const std::string& name) const override; /// Get a string bool get(Mesh* m, std::string& sval, const std::string& name, @@ -115,6 +128,9 @@ public: return getField(m, var, name, def, location); } + bool get(Array& var, const std::string& name) override; + bool get(Array& var, const std::string& name) override; + bool get(Mesh* m, std::vector& var, const std::string& name, int len, int offset = 0, GridDataSource::Direction dir = GridDataSource::X) override; bool get(Mesh* m, std::vector& var, const std::string& name, int len, @@ -178,7 +194,9 @@ public: /*! * Checks if the options has a given variable */ - bool hasVar(const std::string& name) override; + bool hasVar(const std::string& name) const override; + + using GridDataSource::get; /*! * Reads strings from options. Uses Options::get to handle diff --git a/include/bout/gyro_average.hxx b/include/bout/gyro_average.hxx index 63ef13279b..9ce68871cc 100644 --- a/include/bout/gyro_average.hxx +++ b/include/bout/gyro_average.hxx @@ -1,17 +1,17 @@ /*!************************************************************ * \file gyro_average.hxx - * + * * Gyro-averaging operators * * * 2010-09-03 Ben Dudson * * Initial version, simple averaging operator - * + * ************************************************************** * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -41,7 +41,9 @@ constexpr int GYRO_FLAGS = INVERT_BNDRY_ONE + INVERT_RHS; /// Gyro-average using Taylor series approximation /// -/// \f$ \Gamma(f) = f + \rho^2 \nabla_\perp^2(f)\f$ +/// \f[ +/// \Gamma(f) = f + \rho^2 \nabla_\perp^2(f) +/// \f] /// /// Note: Faster, but less robust than Pade approximations /// @@ -51,7 +53,9 @@ Field3D gyroTaylor0(const Field3D& f, const Field3D& rho); /// Gyro-average using Pade approximation /// -/// \f$ \Gamma_0 = (1 - \rho^2 \nabla_\perp^2)g = f\f$ +/// \f[ +/// \Gamma_0 = (1 - \rho^2 \nabla_\perp^2)g = f +/// \f] /// /// NOTE: Uses Z average of rho for efficient inversion /// @@ -70,7 +74,11 @@ Field3D gyroPade0(const Field3D& f, const Field2D& rho, Field3D gyroPade0(const Field3D& f, BoutReal rho, int inner_boundary_flags = GYRO_FLAGS, int outer_boundary_flags = GYRO_FLAGS); -/// Pade approximation \f$Gamma_1 = (1 - \frac{1}{2} \rho^2 \nabla_\perp^2)g = f\f$ +/// Pade approximation +/// +/// \f[ +/// \Gamma_1 = (1 - \frac{1}{2} \rho^2 \nabla_\perp^2)g = f +/// \f] /// /// Note: Have to use Z average of rho for efficient inversion /// diff --git a/include/bout/hypre_interface.hxx b/include/bout/hypre_interface.hxx index ae392de4f3..0f1617c5b3 100644 --- a/include/bout/hypre_interface.hxx +++ b/include/bout/hypre_interface.hxx @@ -5,12 +5,20 @@ #if BOUT_HAS_HYPRE +#include "bout/assert.hxx" #include "bout/bout_enum_class.hxx" +#include "bout/bout_types.hxx" #include "bout/boutcomm.hxx" +#include "bout/boutexception.hxx" #include "bout/caliper_wrapper.hxx" #include "bout/field.hxx" +#include "bout/field2d.hxx" #include "bout/globalindexer.hxx" #include "bout/hyprelib.hxx" +#include "bout/options.hxx" +#include "bout/output.hxx" +#include "bout/paralleltransform.hxx" +#include "bout/region.hxx" #include "bout/utils.hxx" #include "HYPRE.h" @@ -20,7 +28,11 @@ #include "HYPRE_utilities.h" #include "_hypre_utilities.h" +#include +#include +#include #include +#include // BOUT_ENUM_CLASS does not work inside namespaces BOUT_ENUM_CLASS(HYPRE_SOLVER_TYPE, gmres, bicgstab, pcg); @@ -58,6 +70,139 @@ int checkHypreError(int error) { // TODO: set sizes // TODO: set contiguous blocks at once +/// Wrapper around HYPRE_Complex, that calls HypreFree when destroyed. +struct HypreComplexArray { + HYPRE_Complex* data; + + HypreComplexArray(int n) { HypreMalloc(data, sizeof(HYPRE_Complex) * n); } + + ~HypreComplexArray() { HypreFree(data); } +}; + +/// Shared pointter to a HypreComplexArray. When the last copy is destroyed +/// the HYPRE_Complex array inside will be free'd. +using BCValuesPtr = std::shared_ptr; + +/*! + * This function modifies the input for the HYPRE_IJMatrixSetValues() routine to + * eliminate the boundary condition equations (see below for details on how the + * equations are adjusted). It modifies the arrays ncols, rows, cols, and + * values. It also returns a row_indexes array. This can then be passed to the + * HYPRE_IJMatrixSetValues2() routine to set up the matrix in hypre. + * + * The arguments nb and bi_array indicate the boundary equations. The routine + * returns info needed to adjust the right-hand-side and solution vector through + * the functions AdjustRightHandSideEquations and AdjustSolutionEquations. + * + * NOTE: It may make sense from an organizational standpoint to collect many of + * these arguments in a structure of some sort. + * + * Notation, assumptions, and other details: + * + * - Boundary equation i is assumed to have two coefficients + * + * b_ii * u_i + b_ij * u_j = rhs_i + * + * - We also assume that each boundary equation has only one retained unknown j + * on the boundary row + * + * b_ii * u_i + b_ij * u_j = rhs_i + * + * - Any number of other equations k may couple to u_i with coefficient a_ki + * + * a_ki * u_i + a_kj * u_j + ... = rhs_k + * + * - Each such equation k is adjusted as follows: + * + * a_kj = a_kj - a_ki * b_ij / b_ii + * a_ki = 0 + * + * - Boundary equations are adjusted to be identity equations in the matrix, but + * the boundary coefficients (b_ii, b_ij) are returned for use later + * + * - Right-hand-side equations are adjusted in AdjustRightHandSideEquations() as + * follows: rhs_k = rhs_k - a_ki * rhs_i / b_ii + * + * - Solution unknowns are adjusted at boundaries in AdjustSolutionEquations as + * follows: u_i = (rhs_i - b_ij * u_j) / b_ii + * + * - Naming conventions: Arrays starting with 'b' are boundary equation arrays + * indexed by 'bnum', and arrays starting with 'a' are non-boundary arrays + * (interior matrix equations) indexed by 'anum'. When 'num' is prefixed with + * a row or column number 'i', 'j', or 'k', the array holds the corresponding + * local data index for that row or column (e.g., an index into the local + * solution vector). Matrix coefficients are named as above, e.g., 'bij' is + * the coefficient for b_ij. + * + * NOTE: Implementation in src/sys/hypre_interface.cxx + */ +struct BoundaryElimination { + HYPRE_Int nb; + HYPRE_Int* binum_array; + HYPRE_Int* bjnum_array; + HYPRE_Int* bdep_array; + HYPRE_Complex* bii_array; + HYPRE_Complex* bij_array; + HYPRE_Int na; + HYPRE_Int* aoffset_array; + HYPRE_Int* aknum_array; + HYPRE_Complex* aki_array; + std::vector reduction_order; + std::vector expansion_order; + + BoundaryElimination() = delete; + + BoundaryElimination(HYPRE_Int nrows, HYPRE_Int* ncols, HYPRE_BigInt* rows, + HYPRE_Int** row_indexes_ptr, HYPRE_BigInt* cols, + HYPRE_Complex* values, + HYPRE_Int nb, // number of boundary equations + HYPRE_Int* bi_array); // row i for each boundary equation + + ~BoundaryElimination() { + // Free arrays + HypreFree(binum_array); + HypreFree(bjnum_array); + HypreFree(bdep_array); + HypreFree(bii_array); + HypreFree(bij_array); + HypreFree(aoffset_array); + HypreFree(aknum_array); + HypreFree(aki_array); + } + + HYPRE_Int size() const { return nb; } + + /// Copy boundary-row entries from an existing full-space vector. + BCValuesPtr copyBoundaryRowValues(const HYPRE_Complex* values) const; + + /// Evaluate the original boundary equations using the supplied full-space vector. + BCValuesPtr evaluateBoundaryEquations(const HYPRE_Complex* values) const; + + /// Applies in-place modification of the rhs array. + /// + /// Returns boundary values needed to reconstruct the full-space solution. + BCValuesPtr reduceRightHandSideInPlace(HYPRE_Complex* rhs) const; + + /// Apply boundary conditions to the solution. + /// Uses the BCValuesPtr returned from reduceRightHandSideInPlace() + void expandSolutionInPlace(BCValuesPtr brhs, HYPRE_Complex* solution) const; + + /// Reconstruct the action of the full operator from the reduced matrix-vector product. + void expandMatvecResultInPlace(BCValuesPtr boundary_operator_values, + BCValuesPtr full_boundary_values, + HYPRE_Complex* result) const; +}; + +/// A shared pointer to a BoundaryElimination object +using BoundaryEliminationPtr = std::shared_ptr; + +struct BoundaryEliminationState { + BCValuesPtr interior_values; + BCValuesPtr boundary_values; +}; + +enum class HypreVectorReadMode { standard, solution, matvec }; + template class HypreVector { MPI_Comm comm; @@ -70,6 +215,8 @@ class HypreVector { bool have_indices{false}; HYPRE_BigInt* I{nullptr}; HYPRE_Complex* V{nullptr}; + HYPRE_Complex* workV{nullptr}; + bool cache_current{false}; HypreLib hyprelib{}; public: @@ -86,6 +233,7 @@ public: checkHypreError(HYPRE_IJVectorDestroy(hypre_vector)); HypreFree(I); HypreFree(V); + HypreFree(workV); } // Disable copy, at least for now: not clear that HYPRE_IJVector is @@ -97,16 +245,18 @@ public: : comm(other.comm), jlower(other.jlower), jupper(other.jupper), vsize(other.vsize), indexConverter(other.indexConverter), location(other.location), initialised(other.initialised), have_indices(other.have_indices), I(other.I), - V(other.V) { + V(other.V), workV(other.workV), cache_current(other.cache_current) { std::swap(hypre_vector, other.hypre_vector); std::swap(parallel_vector, other.parallel_vector); other.initialised = false; other.have_indices = false; other.I = nullptr; other.V = nullptr; + other.workV = nullptr; + other.cache_current = false; } - HypreVector& operator=(HypreVector&& other) { + HypreVector& operator=(HypreVector&& other) noexcept { comm = other.comm; jlower = other.jlower; jupper = other.jupper; @@ -121,8 +271,12 @@ public: other.have_indices = false; I = other.I; V = other.V; + workV = other.workV; + cache_current = other.cache_current; other.I = nullptr; other.V = nullptr; + other.workV = nullptr; + other.cache_current = false; return *this; } @@ -152,14 +306,16 @@ public: initialised = true; HypreMalloc(I, vsize * sizeof(HYPRE_BigInt)); HypreMalloc(V, vsize * sizeof(HYPRE_Complex)); + HypreMalloc(workV, vsize * sizeof(HYPRE_Complex)); importValuesFromField(f); + assemble(); } /// Construct a vector with given index set, but don't set any values explicit HypreVector(IndexerPtr indConverter) : indexConverter(indConverter) { Mesh& mesh = *indConverter->getMesh(); const MPI_Comm comm = - std::is_same_v ? mesh.getXcomm() : BoutComm::get(); + std::is_same_v ? mesh.getXZcomm() : BoutComm::get(); HYPRE_BigInt jlower = indConverter->getGlobalStart(); HYPRE_BigInt jupper = jlower + indConverter->size() - 1; // inclusive end @@ -172,22 +328,70 @@ public: location = CELL_LOC::centre; HypreMalloc(I, vsize * sizeof(HYPRE_BigInt)); HypreMalloc(V, vsize * sizeof(HYPRE_Complex)); + HypreMalloc(workV, vsize * sizeof(HYPRE_Complex)); } - void assemble() { + void assemble(const BoundaryElimination* boundary_elimination = nullptr, + BoundaryEliminationState* elimination_state = nullptr) { CALI_CXX_MARK_FUNCTION; - writeCacheToHypre(); + + parallel_vector = nullptr; + checkHypreError(HYPRE_IJVectorInitialize(hypre_vector)); + writeCacheToHypre(boundary_elimination, elimination_state); checkHypreError(HYPRE_IJVectorAssemble(hypre_vector)); checkHypreError(HYPRE_IJVectorGetObject(hypre_vector, reinterpret_cast(¶llel_vector))); + cache_current = true; } - void writeCacheToHypre() { - checkHypreError(HYPRE_IJVectorSetValues(hypre_vector, vsize, I, V)); + void writeCacheToHypre(const BoundaryElimination* boundary_elimination = nullptr, + BoundaryEliminationState* elimination_state = nullptr) { + HYPRE_Complex* values = V; + if (boundary_elimination != nullptr) { + ASSERT1(elimination_state != nullptr); + std::copy(V, V + vsize, workV); + values = workV; + elimination_state->interior_values = + boundary_elimination->reduceRightHandSideInPlace(values); + elimination_state->boundary_values = elimination_state->interior_values; + } else if (elimination_state != nullptr) { + elimination_state->interior_values = nullptr; + elimination_state->boundary_values = nullptr; + } + checkHypreError(HYPRE_IJVectorSetValues(hypre_vector, vsize, I, values)); } - void readCacheFromHypre() { - checkHypreError(HYPRE_IJVectorGetValues(hypre_vector, vsize, I, V)); + void readCacheFromHypre(const BoundaryElimination* boundary_elimination = nullptr, + const BoundaryEliminationState* elimination_state = nullptr, + HypreVectorReadMode mode = HypreVectorReadMode::standard) { + HYPRE_Complex* values = V; + if ((boundary_elimination != nullptr) and (mode != HypreVectorReadMode::standard)) { + values = workV; + } + checkHypreError(HYPRE_IJVectorGetValues(hypre_vector, vsize, I, values)); + if (boundary_elimination != nullptr) { + switch (mode) { + case HypreVectorReadMode::standard: + break; + case HypreVectorReadMode::solution: + ASSERT1(elimination_state != nullptr); + ASSERT1(elimination_state->interior_values != nullptr); + boundary_elimination->expandSolutionInPlace(elimination_state->interior_values, + values); + std::copy(values, values + vsize, V); + break; + case HypreVectorReadMode::matvec: + ASSERT1(elimination_state != nullptr); + ASSERT1(elimination_state->interior_values != nullptr); + ASSERT1(elimination_state->boundary_values != nullptr); + boundary_elimination->expandMatvecResultInPlace( + elimination_state->interior_values, elimination_state->boundary_values, + values); + std::copy(values, values + vsize, V); + break; + } + } + cache_current = true; } T toField() { @@ -196,7 +400,9 @@ public: T result(indexConverter->getMesh()); result.allocate().setLocation(location); - readCacheFromHypre(); + if ((!cache_current) and (parallel_vector != nullptr)) { + readCacheFromHypre(); + } // Note that this only populates boundaries to a depth of 1 int count = 0; BOUT_FOR_SERIAL(i, indexConverter->getRegionAll()) { @@ -210,6 +416,7 @@ public: return result; } + // Loads values into I and V arrays but does not assemble void importValuesFromField(const T& f) { CALI_CXX_MARK_FUNCTION; @@ -224,16 +431,22 @@ public: } ASSERT2(vec_i == vsize); - // writeCacheToHypre(); // redundant assemble already performs writeCacheToHypre - assemble(); have_indices = true; + cache_current = true; } HYPRE_IJVector get() { return hypre_vector; } const HYPRE_IJVector& get() const { return hypre_vector; } + const HYPRE_Complex* getValues() const { return V; } - HYPRE_ParVector getParallel() { return parallel_vector; } - const HYPRE_ParVector& getParallel() const { return parallel_vector; } + HYPRE_ParVector getParallel() { + ASSERT1(parallel_vector != nullptr); + return parallel_vector; + } + const HYPRE_ParVector& getParallel() const { + ASSERT1(parallel_vector != nullptr); + return parallel_vector; + } class Element { HypreVector* vector; @@ -265,20 +478,22 @@ public: } Element& operator=(const Element& other) { - ASSERT3(finite(static_cast(other))); + ASSERT3(std::isfinite(static_cast(other))); return *this = static_cast(other); } Element& operator=(BoutReal value_) { - ASSERT3(finite(value_)); + ASSERT3(std::isfinite(value_)); value = value_; vector->V[vec_i] = value_; + vector->cache_current = true; return *this; } Element& operator+=(BoutReal value_) { - ASSERT3(finite(value_)); + ASSERT3(std::isfinite(value_)); value += value_; - ASSERT3(finite(value)); + ASSERT3(std::isfinite(value)); vector->V[vec_i] += value_; + vector->cache_current = true; return *this; } operator BoutReal() const { return value; } @@ -301,11 +516,20 @@ public: friend void swap(HypreVector& lhs, HypreVector& rhs) { using std::swap; + swap(lhs.comm, rhs.comm); + swap(lhs.jlower, rhs.jlower); + swap(lhs.jupper, rhs.jupper); + swap(lhs.vsize, rhs.vsize); swap(lhs.hypre_vector, rhs.hypre_vector); swap(lhs.parallel_vector, rhs.parallel_vector); swap(lhs.indexConverter, rhs.indexConverter); swap(lhs.location, rhs.location); swap(lhs.initialised, rhs.initialised); + swap(lhs.have_indices, rhs.have_indices); + swap(lhs.I, rhs.I); + swap(lhs.V, rhs.V); + swap(lhs.workV, rhs.workV); + swap(lhs.cache_current, rhs.cache_current); } }; @@ -325,6 +549,9 @@ class HypreMatrix { std::vector* I; std::vector>* J; std::vector>* V; + /// Enable reduction of boundary equations before assembling the Hypre matrix. + bool use_boundary_elimination{false}; + BoundaryEliminationPtr boundary_elimination; HypreLib hyprelib{}; // todo also take care of I,J,V @@ -348,7 +575,9 @@ public: index_converter(other.index_converter), location(other.location), initialised(other.initialised), yoffset(other.yoffset), parallel_transform(other.parallel_transform), assembled(other.assembled), - num_rows(other.num_rows), I(other.I), J(other.J), V(other.V) { + num_rows(other.num_rows), I(other.I), J(other.J), V(other.V), + use_boundary_elimination(other.use_boundary_elimination), + boundary_elimination(other.boundary_elimination) { std::swap(hypre_matrix, other.hypre_matrix); std::swap(parallel_matrix, other.parallel_matrix); } @@ -369,6 +598,8 @@ public: I = other.I; J = other.J; V = other.V; + use_boundary_elimination = other.use_boundary_elimination; + boundary_elimination = other.boundary_elimination; return *this; } @@ -380,7 +611,7 @@ public: : hypre_matrix(new HYPRE_IJMatrix, MatrixDeleter{}), index_converter(indConverter) { Mesh* mesh = indConverter->getMesh(); const MPI_Comm comm = - std::is_same_v ? mesh->getXcomm() : BoutComm::get(); + std::is_same_v ? mesh->getXZcomm() : BoutComm::get(); parallel_transform = &mesh->getCoordinates()->getParallelTransform(); ilower = indConverter->getGlobalStart(); @@ -432,7 +663,7 @@ public: weights(weights_) { #if CHECK > 2 for (const auto val : weights) { - ASSERT3(finite(val)); + ASSERT3(std::isfinite(val)); } #endif ASSERT2(positions.size() == weights.size()); @@ -444,23 +675,23 @@ public: value = matrix->getVal(row, column); } Element& operator=(const Element& other) { - AUTO_TRACE(); - ASSERT3(finite(static_cast(other))); + + ASSERT3(std::isfinite(static_cast(other))); return *this = static_cast(other); } Element& operator=(BoutReal value_) { - AUTO_TRACE(); - ASSERT3(finite(value_)); + + ASSERT3(std::isfinite(value_)); value = value_; setValues(value); return *this; } Element& operator+=(BoutReal value_) { - AUTO_TRACE(); - ASSERT3(finite(value_)); - auto column_position = std::find(cbegin(positions), cend(positions), column); + + ASSERT3(std::isfinite(value_)); + auto column_position = std::ranges::find(positions, column); if (column_position != cend(positions)) { - const auto i = std::distance(cbegin(positions), column_position); + const auto i = std::distance(begin(positions), column_position); value += weights[i] * value_; } addValues(value_); @@ -473,7 +704,6 @@ public: void setValues(BoutReal value_) { CALI_CXX_MARK_FUNCTION; - TRACE("HypreMatrix setting values at ({}, {})", row, column); ASSERT3(!positions.empty()); std::vector values; std::transform( @@ -488,7 +718,6 @@ public: void addValues(BoutReal value_) { CALI_CXX_MARK_FUNCTION; - TRACE("HypreMatrix setting values at ({}, {})", row, column); ASSERT3(!positions.empty()); std::vector values; std::transform( @@ -657,7 +886,7 @@ public: pw.begin(), pw.end(), std::back_inserter(positions), [this, ny, nz](ParallelTransform::PositionsAndWeights p) -> HYPRE_Int { return this->index_converter->getGlobal( - ind_type(p.i * ny * nz + p.j * nz + p.k, ny, nz)); + ind_type((((p.i * ny) + p.j) * nz) + p.k, ny, nz)); }); std::transform(pw.begin(), pw.end(), std::back_inserter(weights), [](ParallelTransform::PositionsAndWeights p) -> HYPRE_Complex { @@ -667,19 +896,22 @@ public: return Element(*this, global_row, global_column, positions, weights); } + /// Enable elimination of boundary equations during matrix assembly. + void setUseBoundaryElimination() { use_boundary_elimination = true; } + void assemble() { CALI_CXX_MARK_FUNCTION; HYPRE_BigInt num_entries = 0; - HYPRE_BigInt* num_cols; + HYPRE_Int* num_cols; HYPRE_BigInt* cols; HYPRE_BigInt* rawI; HYPRE_Complex* vals; - HypreMalloc(num_cols, num_rows * sizeof(HYPRE_BigInt)); + HypreMalloc(num_cols, num_rows * sizeof(HYPRE_Int)); for (HYPRE_BigInt i = 0; i < num_rows; ++i) { - num_cols[i] = (*J)[i].size(); - num_entries += (*J)[i].size(); + num_cols[i] = static_cast((*J)[i].size()); + num_entries += num_cols[i]; } HypreMalloc(rawI, num_rows * sizeof(HYPRE_BigInt)); @@ -695,8 +927,31 @@ public: entry++; } } - checkHypreError( - HYPRE_IJMatrixSetValues(*hypre_matrix, num_rows, num_cols, rawI, cols, vals)); + + // Eliminate boundary condition equations in hypre SetValues input arguments + if (use_boundary_elimination) { + HYPRE_Int* bi_array; + HYPRE_Int* row_indexes; + int nb = index_converter->getRegionBndry().size(); + HypreMalloc(bi_array, nb * sizeof(HYPRE_Int)); + nb = 0; + BOUT_FOR_SERIAL(i, index_converter->getRegionBndry()) { + bi_array[nb] = index_converter->getGlobal(i); + nb++; + } + + boundary_elimination = std::make_shared( + num_rows, num_cols, rawI, &row_indexes, cols, vals, nb, bi_array); + HypreFree(bi_array); + + checkHypreError(HYPRE_IJMatrixSetValues2(*hypre_matrix, num_rows, num_cols, rawI, + row_indexes, cols, vals)); + HypreFree(row_indexes); + } else { + boundary_elimination = nullptr; + checkHypreError( + HYPRE_IJMatrixSetValues(*hypre_matrix, num_rows, num_cols, rawI, cols, vals)); + } checkHypreError(HYPRE_IJMatrixAssemble(*hypre_matrix)); checkHypreError(HYPRE_IJMatrixGetObject(*hypre_matrix, reinterpret_cast(¶llel_matrix))); @@ -741,12 +996,17 @@ public: result.I = I; // We want the pointer to transfer so this works like a view result.J = J; result.V = V; + result.use_boundary_elimination = use_boundary_elimination; + result.boundary_elimination = boundary_elimination; return result; } HYPRE_IJMatrix get() { return *hypre_matrix; } const HYPRE_IJMatrix& get() const { return *hypre_matrix; } + const BoundaryElimination* getBoundaryElimination() const { + return boundary_elimination.get(); + } HYPRE_ParCSRMatrix getParallel() { return parallel_matrix; } const HYPRE_ParCSRMatrix& getParallel() const { return parallel_matrix; } @@ -756,8 +1016,33 @@ public: void computeAxpby(double alpha, HypreVector& x, double beta, HypreVector& y) { CALI_CXX_MARK_FUNCTION; + BoundaryEliminationState elimination_state; + if (boundary_elimination != nullptr) { + elimination_state.interior_values = + boundary_elimination->evaluateBoundaryEquations(x.getValues()); + elimination_state.boundary_values = + std::make_shared(boundary_elimination->size()); + BCValuesPtr y_boundary_values; + if (beta != 0.0) { + y_boundary_values = boundary_elimination->copyBoundaryRowValues(y.getValues()); + } + for (HYPRE_Int i = 0; i < boundary_elimination->size(); ++i) { + const HYPRE_Complex operator_value = elimination_state.interior_values->data[i]; + elimination_state.interior_values->data[i] = alpha * operator_value; + elimination_state.boundary_values->data[i] = + alpha * operator_value + + (y_boundary_values != nullptr ? beta * y_boundary_values->data[i] : 0.0); + } + } + + x.assemble(); + y.assemble(); checkHypreError(HYPRE_ParCSRMatrixMatvec(alpha, parallel_matrix, x.getParallel(), beta, y.getParallel())); + y.readCacheFromHypre(boundary_elimination.get(), + boundary_elimination != nullptr ? &elimination_state : nullptr, + boundary_elimination != nullptr ? HypreVectorReadMode::matvec + : HypreVectorReadMode::standard); } // y = A*x @@ -765,8 +1050,7 @@ public: void computeAx(HypreVector& x, HypreVector& y) { CALI_CXX_MARK_FUNCTION; - checkHypreError(HYPRE_ParCSRMatrixMatvec(1.0, parallel_matrix, x.getParallel(), 0.0, - y.getParallel())); + computeAxpby(1.0, x, 0.0, y); } }; @@ -812,7 +1096,7 @@ public: "values are: gmres, bicgstab, pcg") .withDefault(HYPRE_SOLVER_TYPE::bicgstab); - comm = std::is_same_v ? mesh.getXcomm() : BoutComm::get(); + comm = std::is_same_v ? mesh.getXZcomm() : BoutComm::get(); auto print_level = options["hypre_print_level"] @@ -876,6 +1160,31 @@ public: setMaxIter( options["maxits"].doc("Maximum iterations for Hypre solver").withDefault(10000)); + switch (solver_type) { + case HYPRE_SOLVER_TYPE::gmres: { + HYPRE_ParCSRGMRESSetKDim(solver, + options["kdim"] + .doc("Set the maximum size of the Krylov space") + .withDefault(30)); + + if (options["skip_real_residual_check"] + .doc("Skip the evaluation and the check of the actual residual?") + .withDefault(false)) { + HYPRE_GMRESSetSkipRealResidualCheck(solver, 1); + } + break; + } + case HYPRE_SOLVER_TYPE::bicgstab: { + break; + } + case HYPRE_SOLVER_TYPE::pcg: { + break; + } + default: { + throw BoutException("Unsupported hypre_solver_type {}", toString(solver_type)); + } + } + HYPRE_BoomerAMGCreate(&precon); HYPRE_BoomerAMGSetOldDefault(precon); #if BOUT_HAS_CUDA @@ -960,6 +1269,11 @@ public: ASSERT2(A != nullptr); ASSERT2(x != nullptr); ASSERT2(b != nullptr); + BoundaryEliminationState elimination_state; + const auto* boundary_elimination = A->getBoundaryElimination(); + b->assemble(boundary_elimination, + boundary_elimination != nullptr ? &elimination_state : nullptr); + x->assemble(); if (not solver_setup) { checkHypreError( solverSetup(solver, A->getParallel(), b->getParallel(), x->getParallel())); @@ -969,6 +1283,12 @@ public: solve_err = checkHypreError( solverSolve(solver, A->getParallel(), b->getParallel(), x->getParallel())); + x->readCacheFromHypre(boundary_elimination, + boundary_elimination != nullptr ? &elimination_state : nullptr, + boundary_elimination != nullptr + ? HypreVectorReadMode::solution + : HypreVectorReadMode::standard); + return solve_err; } }; // class HypreSystem diff --git a/include/bout/hyprelib.hxx b/include/bout/hyprelib.hxx index a35feb2137..07daa0b641 100644 --- a/include/bout/hyprelib.hxx +++ b/include/bout/hyprelib.hxx @@ -1,24 +1,24 @@ -/*!************************************************************************ +/*! \file ****************************************************************** * Provides access to the Hypre library, handling initialisation and * finalisation. * * Usage * ----- * - * #include + * #include * - * class MyClass { - * public: + * class MyClass { + * HypreLib lib; + * public: + * // ... + * }; * - * private: - * HypreLib lib; - * }; * - * - * This will then automatically initialise Hypre the first time an object - * is created, and finalise it when the last object is destroyed. - * - ************************************************************************** + * This will then automatically ensure Hypre is initialised the first + * time an instance is created, and finalise it when the last instances is + * destroyed (across all objects using `HypreLib`) + */ +/************************************************************************** * Copyright 2012 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk @@ -46,13 +46,14 @@ #include "bout/build_defines.hxx" namespace bout { -#if BOUT_HAS_HYPRE /*! * Handles initialisation and finalisation of Hypre library. - * The first instance which is created initialises Hypre. - * Keeps a count of the number of how many instances exist - * when the last instance is destroyed it finalises Hypre. + * + * The first instance which is created initialises Hypre. Keeps a + * count of the number of how many instances exist, and when the last + * instance is destroyed it finalises Hypre. */ +#if BOUT_HAS_HYPRE class HypreLib { public: explicit HypreLib(); @@ -64,10 +65,11 @@ public: ~HypreLib(); + /// Immediately finalise Hypre library static void cleanup(); private: - static int count; ///< How many instances? + static int count; ///< Current number of instances }; #else // BOUT_HAS_HYPRE diff --git a/include/bout/index_derivs.hxx b/include/bout/index_derivs.hxx index 456f98f8c2..a8d1bbb1d3 100644 --- a/include/bout/index_derivs.hxx +++ b/include/bout/index_derivs.hxx @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -84,7 +83,7 @@ class DerivativeType { public: template void standard(const T& var, T& result, const std::string& region) const { - AUTO_TRACE(); + ASSERT2(meta.derivType == DERIV::Standard || meta.derivType == DERIV::StandardSecond || meta.derivType == DERIV::StandardFourth) ASSERT2(var.getMesh()->getNguard(direction) >= nGuards); @@ -98,7 +97,7 @@ public: template void upwindOrFlux(const T& vel, const T& var, T& result, const std::string& region) const { - AUTO_TRACE(); + ASSERT2(meta.derivType == DERIV::Upwind || meta.derivType == DERIV::Flux) ASSERT2(var.getMesh()->getNguard(direction) >= nGuards); @@ -133,7 +132,7 @@ struct registerMethod { template void operator()(Direction, Stagger, FieldTypeContainer, Method) { - AUTO_TRACE(); + using namespace std::placeholders; // Now we want to get the actual field type out of the TypeContainer @@ -149,7 +148,7 @@ struct registerMethod { // removed and we can use nGuard directly in the template statement. const int nGuards = method.meta.nGuards; - auto& derivativeRegister = DerivativeStore::getInstance(); + auto& derivativeRegister = getStore(); switch (method.meta.derivType) { case (DERIV::Standard): diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index 8f7e41a68e..cbb1e5ac53 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -29,6 +29,8 @@ #ifndef __INDEX_DERIVS_INTERFACE_HXX__ #define __INDEX_DERIVS_INTERFACE_HXX__ +#include "bout/boutexception.hxx" +#include "bout/field3d.hxx" #include "bout/traits.hxx" #include #include @@ -45,7 +47,6 @@ namespace index { template T flowDerivative(const T& vel, const T& f, CELL_LOC outloc, const std::string& method, const std::string& region) { - AUTO_TRACE(); // Checks static_assert(bout::utils::is_Field2D_v || bout::utils::is_Field3D_v, @@ -110,7 +111,6 @@ T flowDerivative(const T& vel, const T& f, CELL_LOC outloc, const std::string& m template T standardDerivative(const T& f, CELL_LOC outloc, const std::string& method, const std::string& region) { - AUTO_TRACE(); // Checks static_assert(bout::utils::is_Field2D_v || bout::utils::is_Field3D_v, @@ -150,8 +150,8 @@ T standardDerivative(const T& f, CELL_LOC outloc, const std::string& method, } // Lookup the method - auto derivativeMethod = DerivativeStore::getInstance().getStandardDerivative( - method, direction, stagger, derivType); + auto derivativeMethod = + getStore().getStandardDerivative(method, direction, stagger, derivType); // Create the result field T result{emptyFrom(f).setLocation(outloc)}; @@ -174,14 +174,20 @@ T standardDerivative(const T& f, CELL_LOC outloc, const std::string& method, template T DDX(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return standardDerivative(f, outloc, method, region); } +inline Field3D DDX(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDX(f.asField3D(), outloc, method, region); +} + template T D2DX2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return standardDerivative(f, outloc, method, region); } @@ -189,7 +195,7 @@ T D2DX2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = template T D4DX4(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return standardDerivative(f, outloc, method, region); } @@ -199,24 +205,33 @@ T D4DX4(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = template T DDY(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); - if (f.hasParallelSlices()) { + + if (f.isFci() or f.hasParallelSlices()) { ASSERT1(f.getDirectionY() == YDirectionType::Standard); + if (!f.hasParallelSlices()) { + throw BoutException( + "parallel slices needed for parallel derivatives. Make sure to communicate and " + "apply parallel boundary conditions before calling derivative"); + } return standardDerivative(f, outloc, method, region); - } else { - const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - const T f_aligned = is_unaligned ? toFieldAligned(f, "RGN_NOX") : f; - T result = standardDerivative(f_aligned, outloc, - method, region); - return is_unaligned ? fromFieldAligned(result, region) : result; } + const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); + const T f_aligned = is_unaligned ? toFieldAligned(f, "RGN_NOX") : f; + T result = standardDerivative(f_aligned, outloc, + method, region); + return is_unaligned ? fromFieldAligned(result, region) : result; +} +inline Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDY(f.asField3D(), outloc, method, region); } template T D2DY2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + if (f.hasParallelSlices()) { ASSERT1(f.getDirectionY() == YDirectionType::Standard); return standardDerivative( @@ -233,7 +248,7 @@ T D2DY2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = template T D4DY4(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + if (f.hasParallelSlices()) { ASSERT1(f.getDirectionY() == YDirectionType::Standard); return standardDerivative( @@ -251,14 +266,20 @@ T D4DY4(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = template T DDZ(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return standardDerivative(f, outloc, method, region); } +inline Field3D DDZ(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDZ(f.asField3D(), outloc, method, region); +} + template T D2DZ2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return standardDerivative(f, outloc, method, region); } @@ -266,7 +287,7 @@ T D2DZ2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = template T D4DZ4(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return standardDerivative(f, outloc, method, region); } @@ -291,14 +312,14 @@ T D4DZ4(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = template T VDDX(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return flowDerivative(vel, f, outloc, method, region); } template T FDDX(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return flowDerivative(vel, f, outloc, method, region); } @@ -307,7 +328,6 @@ T FDDX(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, template T VDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); // Note the following chunk is copy+pasted from flowDerivative // above. Not pulled out as a separate function due the number of @@ -359,11 +379,16 @@ T VDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, return are_unaligned ? fromFieldAligned(result, region) : result; } } +inline Field3D VDDY(const Field3D& v, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return VDDY(v, f.asField3D(), outloc, method, region); +} template T FDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + const bool fHasParallelSlices = (f.hasParallelSlices()); const bool velHasParallelSlices = (vel.hasParallelSlices()); if (fHasParallelSlices && velHasParallelSlices) { @@ -383,20 +408,25 @@ T FDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, return are_unaligned ? fromFieldAligned(result, region) : result; } } +inline Field3D FDDY(const Field3D& v, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return FDDY(v, f.asField3D(), outloc, method, region); +} ////////////// Z DERIVATIVE ///////////////// template T VDDZ(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return flowDerivative(vel, f, outloc, method, region); } template T FDDZ(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - AUTO_TRACE(); + return flowDerivative(vel, f, outloc, method, region); } diff --git a/include/bout/initialprofiles.hxx b/include/bout/initialprofiles.hxx index a2fc050b15..fe0bd71686 100644 --- a/include/bout/initialprofiles.hxx +++ b/include/bout/initialprofiles.hxx @@ -58,22 +58,22 @@ class Vector3D; * ------- * Given the input file: * - * [All] - * function = sin(y) + * [all] + * function = sin(y) * - * [pressure] + * [pressure] * - * [density] - * scale = 0.2 + * [density] + * scale = 0.2 * - * [vorticity] - * function = cos(y) + * [vorticity] + * function = cos(y) * - * initial_profile would generate: + * `initial_profile` would generate: * - * o pressure -> sin(y) - * o density -> 0.2*sin(y) - * o vorticity -> cos(y) + * - ``pressure -> sin(y)`` + * - ``density -> 0.2*sin(y)`` + * - ``vorticity -> cos(y)`` * */ void initial_profile(const std::string& name, Field3D& var); diff --git a/include/bout/interpolation.hxx b/include/bout/interpolation.hxx index 2c7df4472d..40ff603712 100644 --- a/include/bout/interpolation.hxx +++ b/include/bout/interpolation.hxx @@ -2,9 +2,9 @@ * Functions to interpolate between cell locations (e.g. lower Y and centred) * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -26,9 +26,19 @@ #ifndef BOUT_INTERP_H #define BOUT_INTERP_H +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" #include "bout/mesh.hxx" +#include "bout/msg_stack.hxx" +#include "bout/region.hxx" #include "bout/stencils.hxx" +#include +#include + /// Perform interpolation between centre -> shifted or vice-versa /*! Interpolate using 4th-order staggered formula @@ -55,15 +65,15 @@ inline BoutReal interp(const stencil& s) { @param[in] region Region where output will be calculated */ template -const T interp_to(const T& var, CELL_LOC loc, const std::string region = "RGN_ALL") { - AUTO_TRACE(); +std::enable_if_t || bout::utils::is_Field3D_v, const T> +interp_to(const T& var, CELL_LOC loc, const std::string& region = "RGN_ALL") { static_assert(bout::utils::is_Field2D_v || bout::utils::is_Field3D_v, "interp_to must be templated with one of Field2D or Field3D."); ASSERT1(loc != CELL_DEFAULT); // doesn't make sense to interplote to CELL_DEFAULT Mesh* fieldmesh = var.getMesh(); - if ((loc != CELL_CENTRE) && (fieldmesh->StaggerGrids == false)) { + if ((loc != CELL_CENTRE) && !fieldmesh->StaggerGrids) { throw BoutException("Asked to interpolate, but StaggerGrids is disabled!"); } @@ -72,7 +82,7 @@ const T interp_to(const T& var, CELL_LOC loc, const std::string region = "RGN_AL return var; } - // NOTE: invalidateGuards() is called in Field3D::alloctate() if the data + // NOTE: invalidateGuards() is called in Field3D::allocate() if the data // block is not already allocated, so will be called here if // region==RGN_NOBNDRY T result{emptyFrom(var).setLocation(loc)}; @@ -203,4 +213,16 @@ const T interp_to(const T& var, CELL_LOC loc, const std::string region = "RGN_AL return result; } +template +std::enable_if_t && !bout::utils::is_Field3D_v, const Field3D> +interp_to(const E& expr, CELL_LOC loc, const std::string& rgn = "RGN_ALL") { + return interp_to(Field3D{expr}, loc, rgn); +} + +template +std::enable_if_t && !bout::utils::is_Field2D_v, const Field2D> +interp_to(const E& expr, CELL_LOC loc, const std::string& rgn = "RGN_ALL") { + return interp_to(Field2D{expr}, loc, rgn); +} + #endif // BOUT_INTERP_H diff --git a/include/bout/interpolation_xz.hxx b/include/bout/interpolation_xz.hxx index 52dc38f174..1a8be9ef6b 100644 --- a/include/bout/interpolation_xz.hxx +++ b/include/bout/interpolation_xz.hxx @@ -1,8 +1,7 @@ /************************************************************************** - * Copyright 2010-2020 B.D.Dudson, S.Farley, P. Hill, J.T. Omotani, J.T. Parker, - * M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -24,9 +23,23 @@ #ifndef BOUT_INTERP_XZ_H #define BOUT_INTERP_XZ_H -#include "bout/mask.hxx" +#include +#include +#include +#include + +#if BOUT_HAS_PETSC +#include "bout/petsclib.hxx" +#endif + +namespace bout { +namespace details { +enum class implementation_type { new_weights, petsc, legacy }; +} +} // namespace bout class Options; +class GlobalField3DAccess; /// Interpolate a field onto a perturbed set of points const Field3D interpolate(const Field3D& f, const Field3D& delta_x, @@ -43,8 +56,7 @@ public: protected: Mesh* localmesh{nullptr}; - std::string region_name; - std::shared_ptr> region{nullptr}; + int region_id{-1}; public: XZInterpolation(int y_offset = 0, Mesh* localmeshIn = nullptr) @@ -52,48 +64,44 @@ public: localmesh(localmeshIn == nullptr ? bout::globals::mesh : localmeshIn) {} XZInterpolation(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr) : XZInterpolation(y_offset, mesh) { - region = regionFromMask(mask, localmesh); + setMask(mask); } XZInterpolation(const std::string& region_name, int y_offset = 0, Mesh* mesh = nullptr) - : y_offset(y_offset), localmesh(mesh), region_name(region_name) {} - XZInterpolation(std::shared_ptr> region, int y_offset = 0, - Mesh* mesh = nullptr) - : y_offset(y_offset), localmesh(mesh), region(std::move(region)) {} + : y_offset(y_offset), localmesh(mesh), + region_id(localmesh->getRegionID(region_name)) {} + XZInterpolation(const Region& region, int y_offset = 0, Mesh* mesh = nullptr) + : y_offset(y_offset), localmesh(mesh) { + setRegion(region); + } virtual ~XZInterpolation() = default; - void setMask(const BoutMask& mask) { - region = regionFromMask(mask, localmesh); - region_name = ""; - } + void setMask(const BoutMask& mask) { setRegion(regionFromMask(mask, localmesh)); } void setRegion(const std::string& region_name) { - this->region_name = region_name; - this->region = nullptr; - } - void setRegion(const std::shared_ptr>& region) { - this->region_name = ""; - this->region = region; + this->region_id = localmesh->getRegionID(region_name); } + void setRegion(const std::unique_ptr> region) { setRegion(*region); } void setRegion(const Region& region) { - this->region_name = ""; - this->region = std::make_shared>(region); + std::string name; + int i = 0; + do { + name = fmt::format("unsec_reg_xz_interp_{:d}", i++); + } while (localmesh->hasRegion3D(name)); + localmesh->addRegion(name, region); + this->region_id = localmesh->getRegionID(name); } - Region getRegion() const { - if (!region_name.empty()) { - return localmesh->getRegion(region_name); - } - ASSERT1(region != nullptr); - return *region; + const Region& getRegion() const { + ASSERT2(region_id != -1); + return localmesh->getRegion(region_id); } - Region getRegion(const std::string& region) const { - const bool has_region = !region_name.empty() or this->region != nullptr; - if (!region.empty() and region != "RGN_ALL") { - if (has_region) { - return intersection(localmesh->getRegion(region), getRegion()); - } + const Region& getRegion(const std::string& region) const { + if (region_id == -1) { return localmesh->getRegion(region); } - ASSERT1(has_region); - return getRegion(); + if (region == "" or region == "RGN_ALL") { + return getRegion(); + } + return localmesh->getRegion( + localmesh->getCommonRegion(localmesh->getRegionID(region), region_id)); } virtual void calcWeights(const Field3D& delta_x, const Field3D& delta_z, const std::string& region = "RGN_NOBNDRY") = 0; @@ -129,13 +137,25 @@ public: } }; -class XZHermiteSpline : public XZInterpolation { +/// Monotonic Hermite spline interpolator +/// +/// Similar to XZHermiteSpline, so uses most of the same code. +/// Forces the interpolated result to be in the range of the +/// neighbouring cell values. This prevents unphysical overshoots, +/// but also degrades accuracy near maxima and minima. +/// Perhaps should only impose near boundaries, since that is where +/// problems most obviously occur. +template +class XZHermiteSplineBase : public XZInterpolation { protected: /// This is protected rather than private so that it can be /// extended and used by HermiteSplineMonotonic - Tensor i_corner; // x-index of bottom-left grid point - Tensor k_corner; // z-index of bottom-left grid point + Tensor> i_corner; // index of bottom-left grid point + Tensor k_corner; // z-index of bottom-left grid point + + std::unique_ptr gf3daccess; + Tensor> g3dinds; // Basis functions for cubic Hermite spline interpolation // see http://en.wikipedia.org/wiki/Cubic_Hermite_spline @@ -152,12 +172,38 @@ protected: Field3D h10_z; Field3D h11_z; + std::vector newWeights; + +#if BOUT_HAS_PETSC + PetscLib* petsclib; + bool isInit{false}; + Mat petscWeights{}; + Vec rhs{}, result{}; +#endif + + /// Factors to allow for some wiggleroom + BoutReal abs_fac_monotonic{1e-2}; + BoutReal rel_fac_monotonic{1e-1}; + public: - XZHermiteSpline(Mesh* mesh = nullptr) : XZHermiteSpline(0, mesh) {} - XZHermiteSpline(int y_offset = 0, Mesh* mesh = nullptr); - XZHermiteSpline(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr) - : XZHermiteSpline(y_offset, mesh) { - region = regionFromMask(mask, localmesh); + XZHermiteSplineBase(Mesh* mesh = nullptr, [[maybe_unused]] Options* options = nullptr) + : XZHermiteSplineBase(0, mesh, options) {} + XZHermiteSplineBase(int y_offset = 0, Mesh* mesh = nullptr, Options* options = nullptr); + XZHermiteSplineBase(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr, + Options* options = nullptr) + : XZHermiteSplineBase(y_offset, mesh, options) { + setRegion(regionFromMask(mask, localmesh)); + } + ~XZHermiteSplineBase() override { +#if BOUT_HAS_PETSC + if (isInit) { + MatDestroy(&petscWeights); + VecDestroy(&rhs); + VecDestroy(&result); + isInit = false; + delete petsclib; + } +#endif } void calcWeights(const Field3D& delta_x, const Field3D& delta_z, @@ -178,30 +224,29 @@ public: getWeightsForYApproximation(int i, int j, int k, int yoffset) override; }; -/// Monotonic Hermite spline interpolator +using XZMonotonicHermiteSplineSerial = + XZHermiteSplineBase; +using XZHermiteSplineSerial = + XZHermiteSplineBase; +using XZMonotonicHermiteSplineLegacy = + XZHermiteSplineBase; +using XZHermiteSplineLegacy = + XZHermiteSplineBase; +#if BOUT_HAS_PETSC +using XZMonotonicHermiteSpline = + XZHermiteSplineBase; +using XZHermiteSpline = + XZHermiteSplineBase; +#else +using XZMonotonicHermiteSpline = + XZHermiteSplineBase; +using XZHermiteSpline = + XZHermiteSplineBase; +#endif + +/// XZLagrange4pt interpolation class /// -/// Similar to XZHermiteSpline, so uses most of the same code. -/// Forces the interpolated result to be in the range of the -/// neighbouring cell values. This prevents unphysical overshoots, -/// but also degrades accuracy near maxima and minima. -/// Perhaps should only impose near boundaries, since that is where -/// problems most obviously occur. -class XZMonotonicHermiteSpline : public XZHermiteSpline { -public: - XZMonotonicHermiteSpline(Mesh* mesh = nullptr) : XZHermiteSpline(0, mesh) {} - XZMonotonicHermiteSpline(int y_offset = 0, Mesh* mesh = nullptr) - : XZHermiteSpline(y_offset, mesh) {} - XZMonotonicHermiteSpline(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr) - : XZHermiteSpline(mask, y_offset, mesh) {} - - using XZHermiteSpline::interpolate; - /// Interpolate using precalculated weights. - /// This function is called by the other interpolate functions - /// in the base class XZHermiteSpline. - Field3D interpolate(const Field3D& f, - const std::string& region = "RGN_NOBNDRY") const override; -}; - +/// Does not support MPI splitting in X class XZLagrange4pt : public XZInterpolation { Tensor i_corner; // x-index of bottom-left grid point Tensor k_corner; // z-index of bottom-left grid point @@ -209,11 +254,12 @@ class XZLagrange4pt : public XZInterpolation { Field3D t_x, t_z; public: - XZLagrange4pt(Mesh* mesh = nullptr) : XZLagrange4pt(0, mesh) {} + XZLagrange4pt(Mesh* mesh = nullptr, [[maybe_unused]] Options* options = nullptr) + : XZLagrange4pt(0, mesh) {} XZLagrange4pt(int y_offset = 0, Mesh* mesh = nullptr); XZLagrange4pt(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr) : XZLagrange4pt(y_offset, mesh) { - region = regionFromMask(mask, localmesh); + setRegion(regionFromMask(mask, localmesh)); } void calcWeights(const Field3D& delta_x, const Field3D& delta_z, @@ -235,6 +281,9 @@ public: BoutReal lagrange_4pt(const BoutReal v[], BoutReal offset) const; }; +/// XZBilinear interpolation calss +/// +/// Does not support MPI splitting in X. class XZBilinear : public XZInterpolation { Tensor i_corner; // x-index of bottom-left grid point Tensor k_corner; // z-index of bottom-left grid point @@ -242,11 +291,12 @@ class XZBilinear : public XZInterpolation { Field3D w0, w1, w2, w3; public: - XZBilinear(Mesh* mesh = nullptr) : XZBilinear(0, mesh) {} + XZBilinear(Mesh* mesh = nullptr, [[maybe_unused]] Options* options = nullptr) + : XZBilinear(0, mesh) {} XZBilinear(int y_offset = 0, Mesh* mesh = nullptr); XZBilinear(const BoutMask& mask, int y_offset = 0, Mesh* mesh = nullptr) : XZBilinear(y_offset, mesh) { - region = regionFromMask(mask, localmesh); + setRegion(regionFromMask(mask, localmesh)); } void calcWeights(const Field3D& delta_x, const Field3D& delta_z, @@ -266,7 +316,7 @@ public: }; class XZInterpolationFactory - : public Factory { + : public Factory { public: static constexpr auto type_name = "XZInterpolation"; static constexpr auto section_name = "xzinterpolation"; @@ -274,10 +324,10 @@ public: static constexpr auto default_type = "hermitespline"; ReturnType create(Options* options = nullptr, Mesh* mesh = nullptr) const { - return Factory::create(getType(options), mesh); + return Factory::create(getType(options), mesh, options); } - ReturnType create(const std::string& type, [[maybe_unused]] Options* options) const { - return Factory::create(type, nullptr); + ReturnType create(const std::string& type, Options* options) const { + return Factory::create(type, nullptr, options); } static void ensureRegistered(); diff --git a/include/bout/invert/laplacexy.hxx b/include/bout/invert/laplacexy.hxx index 5a4dd46512..51605b9db5 100644 --- a/include/bout/invert/laplacexy.hxx +++ b/include/bout/invert/laplacexy.hxx @@ -1,18 +1,18 @@ /************************************************************************** - * Laplacian solver in 2D (X-Y) + * Perpendicular Laplacian inversion in X-Y * - * Equation solved is: + * Equation solved is: * * Div( A * Grad_perp(x) ) + B*x = b * * Intended for use in solving n = 0 component of potential * from inversion of vorticity equation - * + * ************************************************************************** - * Copyright 2015 B.Dudson + * Copyright 2015-2025 BOUT++ Team * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -30,196 +30,67 @@ * **************************************************************************/ -#ifndef BOUT_LAPLACE_XY_H -#define BOUT_LAPLACE_XY_H - -#include "bout/build_defines.hxx" +#ifndef BOUT_LAPLACEXY_H +#define BOUT_LAPLACEXY_H -#if !BOUT_HAS_PETSC -// If no PETSc - -#warning LaplaceXY requires PETSc. No LaplaceXY available +#include +#include +#include +#include -#include +#include -class Field2D; -class Mesh; +class LaplaceXY; class Options; class Solver; -/*! - * Create a dummy class so that code will compile - * without PETSc, but will throw an exception if - * LaplaceXY is used. - */ -class LaplaceXY { +class LaplaceXYFactory + : public Factory { public: - LaplaceXY(Mesh* UNUSED(m) = nullptr, Options* UNUSED(opt) = nullptr, - const CELL_LOC UNUSED(loc) = CELL_CENTRE) { - throw BoutException("LaplaceXY requires PETSc. No LaplaceXY available"); - } - void setCoefs(const Field2D& UNUSED(A), const Field2D& UNUSED(B)) {} - const Field2D solve(const Field2D& UNUSED(rhs), const Field2D& UNUSED(x0)) { - throw BoutException("LaplaceXY requires PETSc. No LaplaceXY available"); + static constexpr auto type_name = "LaplaceXY"; + static constexpr auto section_name = "laplacexy"; + static constexpr auto option_name = "type"; + static constexpr auto default_type = "petsc"; + + ReturnType create(Mesh* mesh = nullptr, Options* options = nullptr, + CELL_LOC loc = CELL_CENTRE) const { + return Factory::create(getType(options), mesh, optionsOrDefaultSection(options), loc); } - void savePerformance(Solver&, std::string) { - throw BoutException("LaplaceXY requires PETSc. No LaplaceXY available"); + ReturnType create(const std::string& type, Options* options) const { + return Factory::create(type, nullptr, options, CELL_CENTRE); } + + static void ensureRegistered(); }; -#else // BOUT_HAS_PETSC +template +using RegisterLaplaceXY = LaplaceXYFactory::RegisterInFactory; -#include "bout/solver.hxx" -#include "bout/utils.hxx" -#include -#include -#include - -class Options; -class Solver; +using RegisterUnavailableLaplaceXY = LaplaceXYFactory::RegisterUnavailableInFactory; class LaplaceXY { public: - /*! - * Constructor - */ - LaplaceXY(Mesh* m = nullptr, Options* opt = nullptr, const CELL_LOC loc = CELL_CENTRE); - /*! - * Destructor - */ - ~LaplaceXY(); - - /*! - * Set coefficients (A, B) in equation: - * Div( A * Grad_perp(x) ) + B*x = b - */ - void setCoefs(const Field2D& A, const Field2D& B); - - /*! - * Solve Laplacian in X-Y - * - * Inputs - * ====== - * - * rhs - The field to be inverted. This must be allocated - * and contain valid data. - * x0 - Initial guess at the solution. If this is unallocated - * then an initial guess of zero will be used. - * - * Returns - * ======= - * - * The solution as a Field2D. On failure an exception will be raised - * - */ - const Field2D solve(const Field2D& rhs, const Field2D& x0); - - /*! - * Preconditioner function - * This is called by PETSc via a static function. - * and should not be called by external users - */ - int precon(Vec x, Vec y); - - /*! - * If this method is called, save some performance monitoring information - */ - void savePerformance(Solver& solver, const std::string& name = ""); - -private: - PetscLib lib; ///< Requires PETSc library - Mat MatA; ///< Matrix to be inverted - Vec xs, bs; ///< Solution and RHS vectors - KSP ksp; ///< Krylov Subspace solver - PC pc; ///< Preconditioner + LaplaceXY() = default; + LaplaceXY(const LaplaceXY&) = default; + LaplaceXY(LaplaceXY&&) = delete; + LaplaceXY& operator=(const LaplaceXY&) = default; + LaplaceXY& operator=(LaplaceXY&&) = delete; + virtual ~LaplaceXY() = default; - Mesh* localmesh; ///< The mesh this operates on, provides metrics and communication + virtual void setCoefs(const Field2D& A, const Field2D& B) = 0; - /// default prefix for writing performance logging variables - std::string default_prefix; + virtual Field2D solve(const Field2D& b, const Field2D& x0) = 0; - // Preconditioner - int xstart, xend; - int nloc, nsys; - Matrix acoef, bcoef, ccoef, xvals, bvals; - std::unique_ptr> cr; ///< Tridiagonal solver - - // Use finite volume or finite difference discretization - bool finite_volume{true}; - - // Y derivatives - bool include_y_derivs; // Include Y derivative terms? - - // Boundary conditions - bool x_inner_dirichlet; // Dirichlet on inner X boundary? - bool x_outer_dirichlet; // Dirichlet on outer X boundary? - std::string y_bndry{"neumann"}; // Boundary condition for y-boundary - - // Location of the rhs and solution - CELL_LOC location; - - /*! - * Number of grid points on this processor - */ - int localSize(); - - /*! - * Return the communicator for XY - */ - MPI_Comm communicator(); - - /*! - * Return the global index of a local (x,y) coordinate - * including guard cells. - * Boundary cells have a global index of -1 - * - * To do this, a Field2D (indexXY) is used to store - * the index as a floating point number which is then rounded - * to an integer. Guard cells are filled by communication - * so no additional logic is needed in Mesh. - */ - int globalIndex(int x, int y); - Field2D indexXY; ///< Global index (integer stored as BoutReal) - - // Save performance information? - bool save_performance = false; - - // Running average of number of iterations taken for solve in each output timestep - BoutReal average_iterations = 0.; - - // Variable to store the final result of average_iterations, since output is - // written after all other monitors have been called, and average_iterations - // must be reset in the monitor - BoutReal output_average_iterations = 0.; - - // Running total of number of calls to the solver in each output timestep - int n_calls = 0; - - // Utility methods - void setPreallocationFiniteVolume(PetscInt* d_nnz, PetscInt* o_nnz); - void setPreallocationFiniteDifference(PetscInt* d_nnz, PetscInt* o_nnz); - void setMatrixElementsFiniteVolume(const Field2D& A, const Field2D& B); - void setMatrixElementsFiniteDifference(const Field2D& A, const Field2D& B); - void solveFiniteVolume(const Field2D& x0); - void solveFiniteDifference(const Field2D& x0); - - // Monitor class used to reset performance-monitoring variables for a new - // output timestep - friend class LaplaceXYMonitor; - class LaplaceXYMonitor : public Monitor { - public: - LaplaceXYMonitor(LaplaceXY& owner) : laplacexy(owner) {} - - int call(Solver* /*solver*/, BoutReal /*time*/, int /*iter*/, int /*nout*/) override; - void outputVars(Options& output_options, const std::string& time_dimension) override; - - private: - // LaplaceXY object that this monitor belongs to - LaplaceXY& laplacexy; - }; + static std::unique_ptr create(Mesh* m = nullptr, Options* opt = nullptr, + CELL_LOC loc = CELL_CENTRE) { + return LaplaceXYFactory::getInstance().create(m, opt, loc); + } - LaplaceXYMonitor monitor; +protected: + static const int INVERT_DC_GRAD = 1; + static const int INVERT_AC_GRAD = 2; // Use zero neumann (NOTE: AC is a misnomer) + static const int INVERT_SET = 16; // Set boundary to x0 value + static const int INVERT_RHS = 32; // Set boundary to b value }; -#endif // BOUT_HAS_PETSC -#endif // BOUT_LAPLACE_XY_H +#endif // BOUT_LAPLACEXY_H diff --git a/include/bout/invert_laplace.hxx b/include/bout/invert_laplace.hxx index 187056d115..76212dcd76 100644 --- a/include/bout/invert_laplace.hxx +++ b/include/bout/invert_laplace.hxx @@ -3,15 +3,18 @@ * * Perpendicular Laplacian inversion using FFT and Tridiagonal solver * - * Equation solved is: \f$d*\nabla^2_\perp x + (1/c)\nabla_perp c\cdot\nabla_\perp x + a x = b\f$ - * - * Where a, c and d are functions of x and y only (not z) + * Equation solved is: + * \f[ + * d \nabla^2_\perp x + (1/c)\nabla_\perp c\cdot\nabla_\perp x + a x = b + * \f] * - ************************************************************************** + * Where a, c and d are functions of x and y only (not z) + */ +/************************************************************************** * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -40,6 +43,7 @@ class Laplacian; #define PVEC_REAL_MPI_TYPE MPI_DOUBLE #endif +#include "bout/bout_types.hxx" #include "bout/field2d.hxx" #include "bout/field3d.hxx" #include "bout/fieldperp.hxx" @@ -50,6 +54,8 @@ class Laplacian; #include "bout/dcomplex.hxx" +class DSTTransform; +class FFTTransform; class Solver; constexpr auto LAPLACE_SPT = "spt"; @@ -138,7 +144,11 @@ public: static constexpr auto type_name = "Laplacian"; static constexpr auto section_name = "laplace"; static constexpr auto option_name = "type"; +#if BOUT_USE_METRIC_3D + static constexpr auto default_type = LAPLACE_PETSC; +#else static constexpr auto default_type = LAPLACE_CYCLIC; +#endif ReturnType create(Options* options = nullptr, CELL_LOC loc = CELL_CENTRE, Mesh* mesh = nullptr, Solver* solver = nullptr) { @@ -258,7 +268,7 @@ public: /// Coefficients in tridiagonal inversion void tridagCoefs(int jx, int jy, int jz, dcomplex& a, dcomplex& b, dcomplex& c, const Field2D* ccoef = nullptr, const Field2D* d = nullptr, - CELL_LOC loc = CELL_DEFAULT); + CELL_LOC loc = CELL_DEFAULT) const; /*! * Create a new Laplacian solver @@ -301,6 +311,10 @@ public: void savePerformance(Solver& solver, const std::string& name); protected: + // Give access for tridagMatrix + friend class DSTTransform; + friend class FFTTransform; + bool async_send; ///< If true, use asyncronous send in parallel algorithms int maxmode; ///< The maximum Z mode to solve for @@ -332,23 +346,24 @@ protected: void tridagCoefs(int jx, int jy, BoutReal kwave, dcomplex& a, dcomplex& b, dcomplex& c, const Field2D* ccoef = nullptr, const Field2D* d = nullptr, - CELL_LOC loc = CELL_DEFAULT) { + CELL_LOC loc = CELL_DEFAULT) const { tridagCoefs(jx, jy, kwave, a, b, c, ccoef, ccoef, d, loc); } void tridagCoefs(int jx, int jy, BoutReal kwave, dcomplex& a, dcomplex& b, dcomplex& c, const Field2D* c1coef, const Field2D* c2coef, const Field2D* d, - CELL_LOC loc = CELL_DEFAULT); + CELL_LOC loc = CELL_DEFAULT) const; void tridagMatrix(dcomplex* avec, dcomplex* bvec, dcomplex* cvec, dcomplex* bk, int jy, int kz, BoutReal kwave, const Field2D* a, const Field2D* ccoef, - const Field2D* d, bool includeguards = true, bool zperiodic = true) { + const Field2D* d, bool includeguards = true, + bool zperiodic = true) const { tridagMatrix(avec, bvec, cvec, bk, jy, kz, kwave, a, ccoef, ccoef, d, includeguards, zperiodic); } void tridagMatrix(dcomplex* avec, dcomplex* bvec, dcomplex* cvec, dcomplex* bk, int jy, int kz, BoutReal kwave, const Field2D* a, const Field2D* c1coef, const Field2D* c2coef, const Field2D* d, bool includeguards = true, - bool zperiodic = true); + bool zperiodic = true) const; CELL_LOC location; ///< staggered grid location of this solver Mesh* localmesh; ///< Mesh object for this solver Coordinates* coords; ///< Coordinates object, so we only have to call diff --git a/include/bout/invertable_operator.hxx b/include/bout/invertable_operator.hxx index fe139986be..6dcd92897a 100644 --- a/include/bout/invertable_operator.hxx +++ b/include/bout/invertable_operator.hxx @@ -42,7 +42,6 @@ class InvertableOperator; #include #include #include -#include #include #include #include @@ -61,14 +60,14 @@ namespace inversion { /// No-op function to use as a default -- may wish to remove once testing phase complete template T identity(const T& in) { - AUTO_TRACE(); + return in; }; /// Pack a PetscVec from a Field template PetscErrorCode fieldToPetscVec(const T& in, Vec out) { - TRACE("fieldToPetscVec"); + Timer timer("invertable_operator_packing"); PetscScalar* vecData; @@ -93,7 +92,7 @@ PetscErrorCode fieldToPetscVec(const T& in, Vec out) { /// Pack a Field from a PetscVec template PetscErrorCode petscVecToField(Vec in, T& out) { - TRACE("petscVecToField"); + Timer timer("invertable_operator_packing"); const PetscScalar* vecData; @@ -137,12 +136,11 @@ public: opt(optIn == nullptr ? Options::getRoot()->getSection("invertableOperator") : optIn), localmesh(localmeshIn == nullptr ? bout::globals::mesh : localmeshIn), lib(opt) { - AUTO_TRACE(); - }; + + }; /// Destructor just has to cleanup the PETSc owned objects. ~InvertableOperator() { - TRACE("InvertableOperator::destructor"); KSPDestroy(&ksp); MatDestroy(&matOperator); @@ -157,7 +155,7 @@ public: /// do this they can set alsoSetPreconditioner to false. void setOperatorFunction(const function_signature& func, bool alsoSetPreconditioner = true) { - TRACE("InvertableOperator::setOperatorFunction"); + operatorFunction = func; if (alsoSetPreconditioner) { preconditionerFunction = func; @@ -166,28 +164,21 @@ public: /// Allow the user to override the existing preconditioner function void setPreconditionerFunction(const function_signature& func) { - TRACE("InvertableOperator::setPreconditionerFunction"); + preconditionerFunction = func; } /// Provide a way to apply the operator to a Field - T operator()(const T& input) { - TRACE("InvertableOperator::operator()"); - return operatorFunction(input); - } + T operator()(const T& input) { return operatorFunction(input); } /// Provide a synonym for applying the operator to a Field - T apply(const T& input) { - AUTO_TRACE(); - return operator()(input); - } + T apply(const T& input) { return operator()(input); } /// Sets up the PETSc objects required for inverting the operator /// Currently also takes the functor that applies the operator this class /// represents. Not actually required by any of the setup so this should /// probably be moved to a separate place (maybe the constructor). PetscErrorCode setup() { - TRACE("InvertableOperator::setup"); Timer timer("invertable_operator_setup"); if (doneSetup) { @@ -219,21 +210,18 @@ public: localmesh->LocalNy, localmesh->LocalNz, localmesh->maxregionblocksize); } } - if (localmesh->firstY() or localmesh->lastY()) { - for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { - if (not localmesh->periodicY(ix)) { - if (localmesh->firstY()) { - nocorner3D += - Region(ix, ix, 0, localmesh->ystart - 1, 0, - localmesh->LocalNz - 1, localmesh->LocalNy, - localmesh->LocalNz, localmesh->maxregionblocksize); - } - if (localmesh->lastY()) { - nocorner3D += Region( - ix, ix, localmesh->LocalNy - localmesh->ystart, - localmesh->LocalNy - 1, 0, localmesh->LocalNz - 1, localmesh->LocalNy, - localmesh->LocalNz, localmesh->maxregionblocksize); - } + for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { + if (not localmesh->periodicY(ix)) { + if (localmesh->firstY(ix)) { + nocorner3D += Region( + ix, ix, 0, localmesh->ystart - 1, 0, localmesh->LocalNz - 1, + localmesh->LocalNy, localmesh->LocalNz, localmesh->maxregionblocksize); + } + if (localmesh->lastY(ix)) { + nocorner3D += Region( + ix, ix, localmesh->LocalNy - localmesh->ystart, localmesh->LocalNy - 1, + 0, localmesh->LocalNz - 1, localmesh->LocalNy, localmesh->LocalNz, + localmesh->maxregionblocksize); } } } @@ -259,20 +247,17 @@ public: 0, 0, localmesh->LocalNy, 1, localmesh->maxregionblocksize); } } - if (localmesh->firstY() or localmesh->lastY()) { - for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { - if (not localmesh->periodicY(ix)) { - if (localmesh->firstY()) { - nocorner2D += - Region(ix, ix, 0, localmesh->ystart - 1, 0, 0, - localmesh->LocalNy, 1, localmesh->maxregionblocksize); - } - if (localmesh->lastY()) { - nocorner2D += - Region(ix, ix, localmesh->LocalNy - localmesh->ystart, - localmesh->LocalNy - 1, 0, 0, localmesh->LocalNy, 1, - localmesh->maxregionblocksize); - } + for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { + if (not localmesh->periodicY(ix)) { + if (localmesh->firstY(ix)) { + nocorner2D += + Region(ix, ix, 0, localmesh->ystart - 1, 0, 0, + localmesh->LocalNy, 1, localmesh->maxregionblocksize); + } + if (localmesh->lastY(ix)) { + nocorner2D += Region( + ix, ix, localmesh->LocalNy - localmesh->ystart, localmesh->LocalNy - 1, + 0, 0, localmesh->LocalNy, 1, localmesh->maxregionblocksize); } } } @@ -392,7 +377,7 @@ public: // but suspect it's not as there are KSPGuess objects // to deal with. T invert(const T& rhsField, const T& guess) { - AUTO_TRACE(); + auto ierr = fieldToPetscVec(guess, lhs); CHKERRQ(ierr); return invert(rhsField); @@ -403,7 +388,7 @@ public: /// of the operator we represent. Should probably provide an overload or similar as a /// way of setting the initial guess. T invert(const T& rhsField) { - TRACE("InvertableOperator::invert"); + Timer timer("invertable_operator_invert"); if (!doneSetup) { @@ -450,7 +435,6 @@ public: /// applying the registered function on the calculated inverse gives /// back the initial values. bool verify(const T& rhsIn, BoutReal tol = 1.0e-5) { - TRACE("InvertableOperator::verify"); T result = invert(rhsIn); localmesh->communicate(result); @@ -469,7 +453,7 @@ public: /// that as the Timer "labels" are not unique to an instance the time /// reported is summed across all different instances. static void reportTime() { - TRACE("InvertableOperator::reportTime"); + BoutReal time_setup = Timer::resetTime("invertable_operator_setup"); BoutReal time_invert = Timer::resetTime("invertable_operator_invert"); BoutReal time_packing = Timer::resetTime("invertable_operator_packing"); @@ -509,7 +493,7 @@ private: /// Copies data from v1 into a field of type T, calls the function on this and then /// copies the result into the v2 argument. static PetscErrorCode functionWrapper(Mat m, Vec v1, Vec v2) { - TRACE("InvertableOperator::functionWrapper"); + InvertableOperator* ctx; auto ierr = MatShellGetContext(m, &ctx); T tmpField(ctx->localmesh); @@ -540,7 +524,7 @@ private: /// Copies data from v1 into a field of type T, calls the function on this and then /// copies the result into the v2 argument. static PetscErrorCode preconditionerWrapper(Mat m, Vec v1, Vec v2) { - TRACE("InvertableOperator::functionWrapper"); + InvertableOperator* ctx; auto ierr = MatShellGetContext(m, &ctx); T tmpField(ctx->localmesh); @@ -575,7 +559,7 @@ public: }; #endif // PETSC -}; // namespace inversion -}; // namespace bout +}; // namespace inversion +}; // namespace bout #endif // HEADER GUARD diff --git a/include/bout/lapack_routines.hxx b/include/bout/lapack_routines.hxx index 8ec793f127..d9a0af0bdc 100644 --- a/include/bout/lapack_routines.hxx +++ b/include/bout/lapack_routines.hxx @@ -1,8 +1,22 @@ +/// \file +/// +/// Serial code to invert a complex tridiagonal system +/// +/// Solves a banded matrix given the matrix in compact form: +/// +/// a[0...(n-1)][0...(m1+m2)] +/// +/// and the rhs vector: +/// +/// b[0...(n-1)] +/// +/// ``a`` is overwritten, and ``b`` is replaced by the solution + /************************************************************************** * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -26,35 +40,34 @@ #include "bout/dcomplex.hxx" #include "bout/utils.hxx" -/* Tridiagonal inversion - * - * a = Left of diagonal (so a[0] not used) - * b = diagonal terms - * c = Right of diagonal (so c[n-1] not used) - * r = RHS vector - * u = Result vector - * n = Length of vectors - * - * - * b[0] c[0] - * a[1] b[1] c[1] - * . . . - * - */ - -// Tri-diagonal solvers +/// Tridiagonal inversion +/// +/// \param a Left of diagonal (so a[0] not used) +/// \param b diagonal terms +/// \param c Right of diagonal (so c[n-1] not used) +/// \param r RHS vector +/// \param u Result vector +/// \param n Length of vectors +/// +/// b[0] c[0] +/// a[1] b[1] c[1] +/// . . . +/// +/// Uses LAPACK routine ZGTSV int tridag(const dcomplex* a, const dcomplex* b, const dcomplex* c, const dcomplex* r, dcomplex* u, int n); bool tridag(const BoutReal* a, const BoutReal* b, const BoutReal* c, const BoutReal* r, BoutReal* x, int n); -// Cyclic tridiagonal +/// Cyclic tridiagonal +/// +/// Uses Sherman-Morrison formula void cyclic_tridag(BoutReal* a, BoutReal* b, BoutReal* c, BoutReal* r, BoutReal* x, int n); void cyclic_tridag(dcomplex* a, dcomplex* b, dcomplex* c, dcomplex* r, dcomplex* x, int n); -/// Complex band matrix solver +/// Complex band matrix solver using ZGBSV void cband_solve(Matrix& a, int n, int m1, int m2, Array& b); #endif // BOUT_LAPACK_ROUTINES_H diff --git a/include/bout/mask.hxx b/include/bout/mask.hxx index fd90ae7345..9033080d44 100644 --- a/include/bout/mask.hxx +++ b/include/bout/mask.hxx @@ -26,7 +26,7 @@ #include "bout/globals.hxx" #include "bout/mesh.hxx" -#include "bout/msg_stack.hxx" +#include "bout/region.hxx" /** * 3D array of bools to mask Field3Ds @@ -81,4 +81,12 @@ inline std::unique_ptr> regionFromMask(const BoutMask& mask, } return std::make_unique>(indices); } + +inline BoutMask maskFromRegion(const Region& region, const Mesh* mesh) { + BoutMask mask{mesh, false}; + + BOUT_FOR(i, region) { mask[i] = true; } + return mask; +} + #endif //BOUT_MASK_H diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index a9fe4363c4..46f8351539 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -3,24 +3,12 @@ * * Interface for mesh classes. Contains standard variables and useful * routines. - * - * Changelog - * ========= - * - * 2014-12 Ben Dudson - * * Removing coordinate system into separate - * Coordinates class - * * Adding index derivative functions from derivs.cxx - * - * 2010-06 Ben Dudson, Sean Farley - * * Initial version, adapted from GridData class - * * Incorporates code from topology.cpp and Communicator * ************************************************************************** - * Copyright 2010-2025 BOUT++ contributors + * Copyright 2010-2026 BOUT++ contributors * * Contact: Ben Dudson, dudson2@llnl.gov - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -38,17 +26,14 @@ * **************************************************************************/ +#include "bout/boutexception.hxx" class Mesh; #ifndef BOUT_MESH_H #define BOUT_MESH_H -#include "mpi.h" - -#include -#include -#include - +#include "bout/array.hxx" +#include "bout/bout_enum_class.hxx" #include "bout/bout_types.hxx" #include "bout/field2d.hxx" #include "bout/field3d.hxx" @@ -68,17 +53,18 @@ class BoundaryRegionPar; #include "bout/unused.hxx" -#include "bout/generic_factory.hxx" -#include - -#include - -#include #include #include #include #include #include +#include + +class BoundaryRegion; +namespace bout::boundary { +class BoundaryRegionFCI; +} +class GridDataSource; class MeshFactory : public Factory { public: @@ -180,6 +166,9 @@ public: /// @returns zero if successful, non-zero on failure int get(bool& bval, const std::string& name, bool def = false); + int get(Array& var, const std::string& name); + int get(Array& var, const std::string& name); + /// Get a Field2D from the input source /// including communicating guard cells /// @@ -272,6 +261,16 @@ public: communicate(g); } + /// Communicate Fields without calculating the parallel slices + template + void communicate_no_slices(Ts&... ts) { + FieldGroup g(ts...); + const bool old = calcParallelSlices_on_communicate; + calcParallelSlices_on_communicate = false; + communicate(g); + calcParallelSlices_on_communicate = old; + } + template void communicateXZ(Ts&... ts) { FieldGroup g(ts...); @@ -301,11 +300,6 @@ public: /// @param g The group of fields to communicate. Guard cells will be modified void communicateYZ(FieldGroup& g); - /*! - * Communicate an X-Z field - */ - virtual void communicate(FieldPerp& f); - /*! * Send a list of FieldData objects * Packs arguments into a FieldGroup and passes @@ -354,10 +348,14 @@ public: // non-local communications - virtual int getNXPE() = 0; ///< The number of processors in the X direction - virtual int getNYPE() = 0; ///< The number of processors in the Y direction - virtual int getXProcIndex() = 0; ///< This processor's index in X direction - virtual int getYProcIndex() = 0; ///< This processor's index in Y direction + virtual int getNXPE() const = 0; ///< The number of processors in the X direction + virtual int getNYPE() const = 0; ///< The number of processors in the Y direction + virtual int getNZPE() const = 0; ///< The number of processors in the Z direction + virtual int getXProcIndex() const = 0; ///< This processor's index in X direction + virtual int getYProcIndex() const = 0; ///< This processor's index in Y direction + virtual int getZProcIndex() const = 0; ///< This processor's index in Z direction + /// The index of a processor with given X, Y, and Z index + virtual int getProcIndex(int X, int Y, int Z) const = 0; // X communications virtual bool firstX() @@ -368,8 +366,6 @@ public: /// Domain is periodic in X? bool periodicX{false}; - int NXPE, PE_XIND; ///< Number of processors in X, and X processor index - /// Send a buffer of data to processor at X index +1 /// /// @param[in] buffer The data to send. Must be at least length \p size @@ -403,6 +399,7 @@ public: } ///< Return communicator containing all processors in X virtual MPI_Comm getXcomm(int jy) const = 0; ///< Return X communicator virtual MPI_Comm getYcomm(int jx) const = 0; ///< Return Y communicator + virtual MPI_Comm getXZcomm() const = 0; ///< Communicator in X-Z /// Return pointer to the mesh's MPI Wrapper object MpiWrapper& getMpi() { return *mpi; } @@ -474,21 +471,25 @@ public: /// Is there a boundary on the lower guard cells in Y /// on any processor along the X direction? - bool hasBndryLowerY(); + virtual bool hasBndryLowerY() const = 0; /// Is there a boundary on the upper guard cells in Y /// on any processor along the X direction? - bool hasBndryUpperY(); + virtual bool hasBndryUpperY() const = 0; // Boundary regions /// Return a vector containing all the boundary regions on this processor - virtual std::vector getBoundaries() = 0; + virtual std::vector> getBoundaries() const = 0; /// Get the set of all possible boundaries in this configuration - virtual std::set getPossibleBoundaries() const { return {}; } + virtual std::set getPossibleBoundaries() const { + throw BoutException("Not implemented for this mesh"); + }; /// Add a boundary region to this processor - virtual void addBoundary(BoundaryRegion* UNUSED(bndry)) {} + virtual void addBoundary(std::shared_ptr UNUSED(bndry)) { + throw BoutException("This has never been implemented"); + }; /// Get the list of parallel boundary regions. The option specifies with /// region to get. Default is to get all regions. All possible options are @@ -498,20 +499,20 @@ public: /// mesh->getBoundariesPar(Mesh::BoundaryParType::all) /// get only xout: /// mesh->getBoundariesPar(Mesh::BoundaryParType::xout) - virtual std::vector> - getBoundariesPar(BoundaryParType type = BoundaryParType::all) = 0; + virtual std::vector> + getBoundariesPar(BoundaryParType type = BoundaryParType::all) const = 0; /// Add a parallel(Y) boundary to this processor - virtual void addBoundaryPar(std::shared_ptr UNUSED(bndry), - BoundaryParType UNUSED(type)) {} - - /// Branch-cut special handling (experimental) - virtual Field3D smoothSeparatrix(const Field3D& f) { return f; } + virtual void + addBoundaryPar(std::shared_ptr UNUSED(bndry), + BoundaryParType UNUSED(type)) {} virtual BoutReal GlobalX(int jx) const = 0; ///< Continuous X index between 0 and 1 virtual BoutReal GlobalY(int jy) const = 0; ///< Continuous Y index (0 -> 1) + virtual BoutReal GlobalZ(int jz) const = 0; ///< Continuous Z index (0 -> 1) virtual BoutReal GlobalX(BoutReal jx) const = 0; ///< Continuous X index between 0 and 1 virtual BoutReal GlobalY(BoutReal jy) const = 0; ///< Continuous Y index (0 -> 1) + virtual BoutReal GlobalZ(BoutReal jz) const = 0; ///< Continuous Z index (0 -> 1) ////////////////////////////////////////////////////////// @@ -601,7 +602,7 @@ public: virtual int getLocalZIndexNoBoundaries(int zglobal) const = 0; /// Size of the mesh on this processor including guard/boundary cells - int LocalNx, LocalNy, LocalNz; + int LocalNx{0}, LocalNy{0}, LocalNz{0}; /// Local ranges of data (inclusive), excluding guard cells int xstart, xend, ystart, yend, zstart, zend; @@ -616,25 +617,7 @@ public: return getCoordinatesSmart(location).get(); }; - std::shared_ptr - getCoordinatesSmart(const CELL_LOC location = CELL_CENTRE) { - ASSERT1(location != CELL_DEFAULT); - ASSERT1(location != CELL_VSHIFT); - - auto found = coords_map.find(location); - if (found != coords_map.end()) { - // True branch most common, returns immediately - return found->second; - } - - // No coordinate system set. Create default - // Note that this can't be allocated here due to incomplete type - // (circular dependency between Mesh and Coordinates) - auto inserted = coords_map.emplace(location, nullptr); - inserted.first->second = createDefaultCoordinates(location); - inserted.first->second->geometry(false); - return inserted.first->second; - } + std::shared_ptr getCoordinatesSmart(CELL_LOC location = CELL_CENTRE); std::shared_ptr getCoordinatesConst(const CELL_LOC location = CELL_CENTRE) const { @@ -652,7 +635,7 @@ public: /// Returns the non-CELL_CENTRE location /// allowed as a staggered location static CELL_LOC getAllowedStaggerLoc(DIRECTION direction) { - AUTO_TRACE(); + switch (direction) { case (DIRECTION::X): return CELL_XLOW; @@ -670,7 +653,7 @@ public: /// Returns the number of grid points in the /// particular direction int getNpoints(DIRECTION direction) const { - AUTO_TRACE(); + switch (direction) { case (DIRECTION::X): return LocalNx; @@ -688,7 +671,7 @@ public: /// Returns the number of guard points in the /// particular direction int getNguard(DIRECTION direction) const { - AUTO_TRACE(); + switch (direction) { case (DIRECTION::X): return xstart; @@ -767,7 +750,7 @@ public: void addRegionPerp(const std::string& region_name, const Region& region); /// Converts an Ind2D to an Ind3D using calculation - Ind3D ind2Dto3D(const Ind2D& ind2D, int jz = 0) { + Ind3D ind2Dto3D(const Ind2D& ind2D, int jz = 0) const { return {ind2D.ind * LocalNz + jz, LocalNy, LocalNz}; } @@ -785,6 +768,12 @@ public: return {(indPerp.ind - jz) * LocalNy + LocalNz * jy + jz, LocalNy, LocalNz}; } + BOUT_HOST_DEVICE int flatIndPerpto3D(const int& flatIndPerp, const int nz, + int jy = 0) const { + int jz = flatIndPerp % nz; + return (flatIndPerp - jz) * LocalNy + LocalNz * jy + jz; + } + /// Converts an Ind3D to an Ind2D representing a 2D index using a lookup -- to be used with care Ind2D map3Dto2D(const Ind3D& ind3D) { return {indexLookup3Dto2D[ind3D.ind], LocalNy, 1}; @@ -805,15 +794,17 @@ protected: /// Mesh options section Options* options{nullptr}; +private: /// Set whether to call calcParallelSlices on all communicated fields (true) or not (false) bool calcParallelSlices_on_communicate{true}; +protected: /// Read a 1D array of integers const std::vector readInts(const std::string& name, int n); /// Calculates the size of a message for a given x and y range - int msg_len(const std::vector& var_list, int xge, int xlt, int yge, - int ylt); + int msg_len(const std::vector& var_list, int xge, int xlt, int yge, + int ylt) const; /// Initialise derivatives void derivs_init(Options* options); @@ -834,7 +825,8 @@ public: // Switch for communication of corner guard and boundary cells const bool include_corner_cells; - std::optional getCommonRegion(std::optional, std::optional); + std::optional getCommonRegion(std::optional lhs, + std::optional rhs); size_t getRegionID(const std::string& region) const; const Region& getRegion(size_t RegionID) const { return region3D[RegionID]; } const Region& getRegion(std::optional RegionID) const { diff --git a/include/bout/metric_tensor.hxx b/include/bout/metric_tensor.hxx new file mode 100644 index 0000000000..fa94d504a1 --- /dev/null +++ b/include/bout/metric_tensor.hxx @@ -0,0 +1,113 @@ +#ifndef BOUT_METRIC_TENSOR_HXX +#define BOUT_METRIC_TENSOR_HXX + +#include +#include +#include +#include + +#include + +namespace bout { +#if BOUT_USE_METRIC_3D +using FieldMetric = Field3D; +using FieldMetricParallel = Field3DParallel; +#else +using FieldMetric = Field2D; +using FieldMetricParallel = Field2D; +#endif +} // namespace bout + +class Coordinates; +struct MetricNormaliser; + +class MetricTensor { +public: + friend class Coordinates; + +#if BOUT_USE_METRIC_3D + using Metric2DSlice = const BoutReal*; +#else + using Metric2DSlice = const BoutReal&; +#endif + using FieldMetric = bout::FieldMetric; + + MetricTensor(const MetricTensor&) = default; + MetricTensor(MetricTensor&&) = default; + MetricTensor& operator=(const MetricTensor&) = default; + MetricTensor& operator=(MetricTensor&&) = default; + MetricTensor(FieldMetric g11, FieldMetric g22, FieldMetric g33, FieldMetric g12, + FieldMetric g13, FieldMetric g23); + + MetricTensor(BoutReal g11, BoutReal g22, BoutReal g33, BoutReal g12, BoutReal g13, + BoutReal g23, Mesh* mesh); + virtual ~MetricTensor() = default; + + /// Check that tensors are positive (if expected) and finite (always) + void check(int ystart); + + const FieldMetric& g11() const { return g11_m; } + const FieldMetric& g22() const { return g22_m; } + const FieldMetric& g33() const { return g33_m; } + const FieldMetric& g12() const { return g12_m; } + const FieldMetric& g13() const { return g13_m; } + const FieldMetric& g23() const { return g23_m; } + + const BoutReal& g11(int x, int y, int z) const { return g11_m(x, y, z); } + const BoutReal& g22(int x, int y, int z) const { return g22_m(x, y, z); } + const BoutReal& g33(int x, int y, int z) const { return g33_m(x, y, z); } + const BoutReal& g12(int x, int y, int z) const { return g12_m(x, y, z); } + const BoutReal& g13(int x, int y, int z) const { return g13_m(x, y, z); } + const BoutReal& g23(int x, int y, int z) const { return g23_m(x, y, z); } + + Metric2DSlice g11(int x, int y) const { return g11_m(x, y); } + Metric2DSlice g22(int x, int y) const { return g22_m(x, y); } + Metric2DSlice g33(int x, int y) const { return g33_m(x, y); } + Metric2DSlice g12(int x, int y) const { return g12_m(x, y); } + Metric2DSlice g13(int x, int y) const { return g13_m(x, y); } + Metric2DSlice g23(int x, int y) const { return g23_m(x, y); } + + /// Transforms the MetricTensor by applying the given function to every component + template + void map(F function) { + g11_m = function(g11_m); + g22_m = function(g22_m); + g33_m = function(g33_m); + g12_m = function(g12_m); + g13_m = function(g13_m); + g23_m = function(g23_m); + } + + void communicate(); + + template + void normaliseMetric(const MetricNormaliser& norm, const F& op); + +private: + FieldMetric g11_m, g22_m, g33_m, g12_m, g13_m, g23_m; +}; + +class CovariantMetricTensor; +class ContravariantMetricTensor; + +class CovariantMetricTensor : public MetricTensor { +public: + using MetricTensor::MetricTensor; + + auto inverse(const std::string& region = "RGN_ALL", bool communicate = true) + -> ContravariantMetricTensor; + + void normaliseMetric(const MetricNormaliser& norm); +}; + +class ContravariantMetricTensor : public MetricTensor { +public: + using MetricTensor::MetricTensor; + + auto inverse(const std::string& region = "RGN_ALL", bool communicate = true) + -> CovariantMetricTensor; + + void normaliseMetric(const MetricNormaliser& norm); +}; + +#endif //BOUT_METRIC_TENSOR_HXX diff --git a/include/bout/monitor.hxx b/include/bout/monitor.hxx index 991cbd65c5..d1363e8009 100644 --- a/include/bout/monitor.hxx +++ b/include/bout/monitor.hxx @@ -33,7 +33,7 @@ class Monitor { public: /// A \p timestep_ of -1 defaults to the the frequency of the BOUT++ /// output monitor - Monitor(BoutReal timestep_ = -1) : timestep(timestep_){}; + Monitor(BoutReal timestep_ = -1) : timestep(timestep_) {}; virtual ~Monitor() = default; @@ -48,7 +48,7 @@ public: virtual int call(Solver* solver, BoutReal time, int iter, int nout) = 0; /// Callback function for when a clean shutdown is initiated - virtual void cleanup(){}; + virtual void cleanup() {}; virtual void outputVars([[maybe_unused]] Options& options, [[maybe_unused]] const std::string& time_dimension) {} diff --git a/include/bout/msg_stack.hxx b/include/bout/msg_stack.hxx index 6d19469e25..aa19939058 100644 --- a/include/bout/msg_stack.hxx +++ b/include/bout/msg_stack.hxx @@ -31,27 +31,14 @@ class MsgStack; #include "bout/build_defines.hxx" -#include "bout/unused.hxx" - +#include "fmt/base.h" #include "fmt/core.h" -#include +#include #include #include #include -/// The __PRETTY_FUNCTION__ variable is defined by GCC (and some other families) but is -/// not a part of the standard. The __func__ variable *is* a part of the c++11 standard so -/// we'd like to fall back to this if possible. However as these are variables/constants -/// and not macros we can't just check if __PRETTY_FUNCITON__ is defined or not. Instead -/// we need to say if we support this or not by defining BOUT_HAS_PRETTY_FUNCTION (to be -/// implemented in configure) -#if BOUT_HAS_PRETTY_FUNCTION -#define __thefunc__ __PRETTY_FUNCTION__ -#else -#define __thefunc__ __func__ -#endif - /*! * Message stack * @@ -74,9 +61,10 @@ public: int push(std::string message); int push() { return push(""); } - template - int push(const S& format, const Args&... args) { - return push(fmt::format(format, args...)); + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + int push(fmt::format_string format, Args&&... args) { + return push(fmt::vformat(format, fmt::make_format_args(args...))); } void pop(); ///< Remove the last message @@ -88,19 +76,23 @@ public: #else /// Dummy functions which should be optimised out int push(const std::string&) { return 0; } - template - int push(const S&, const Args&...) { + template + int push([[maybe_unused]] fmt::format_string format, + [[maybe_unused]] const Args&... args) { return 0; } void pop() {} - void pop(int UNUSED(id)) {} + void pop([[maybe_unused]] int id) {} void clear() {} void dump() {} std::string getDump() { return ""; } #endif + /// Current stack size + std::size_t size() const { return position; } + private: std::vector stack; ///< Message stack; std::vector::size_type position{0}; ///< Position in stack @@ -143,10 +135,13 @@ public: MsgStackItem(const std::string& file, int line, const char* msg) : point(msg_stack.push("{:s} on line {:d} of '{:s}'", msg, line, file)) {} - template - MsgStackItem(const std::string& file, int line, const S& msg, const Args&... args) - : point(msg_stack.push("{:s} on line {:d} of '{:s}'", fmt::format(msg, args...), - line, file)) {} + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + MsgStackItem(const std::string& file, int line, fmt::format_string msg, + Args&&... args) + : point(msg_stack.push("{:s} on line {:d} of '{:s}'", + fmt::vformat(msg, fmt::make_format_args(args...)), line, + file)) {} ~MsgStackItem() { // If an exception has occurred, don't pop the message if (exception_count == std::uncaught_exceptions()) { @@ -193,23 +188,4 @@ private: #define TRACE(...) #endif -/*! - * The AUTO_TRACE macro provides a convenient way to put messages onto the msg_stack - * It pushes a message onto the stack, and pops it when the scope ends - * The message is automatically derived from the function signature - * as identified by the compiler. This will be PRETTY_FUNCTION if available - * else it will be the mangled form. - * - * This is implemented as a use of the TRACE macro with specific arguments. - * - * Example - * ------- - * - * { - * AUTO_TRACE(); - * - * } // Scope ends, message popped - */ -#define AUTO_TRACE() TRACE(__thefunc__) // NOLINT - #endif // BOUT_MSG_STACK_H diff --git a/include/bout/multiostream.hxx b/include/bout/multiostream.hxx index ca3cc2d0c7..d038c8f659 100644 --- a/include/bout/multiostream.hxx +++ b/include/bout/multiostream.hxx @@ -17,7 +17,7 @@ private: public: void add(std::basic_ostream& str) { - auto pos = std::find(streams_.begin(), streams_.end(), &str); + auto pos = std::ranges::find(streams_, &str); // Already been added if (pos != streams_.end()) { @@ -28,7 +28,7 @@ public: } void remove(std::basic_ostream& str) { - auto pos = std::find(streams_.begin(), streams_.end(), &str); + auto pos = std::ranges::find(streams_, &str); if (pos != streams_.end()) { streams_.erase(pos); @@ -74,8 +74,8 @@ private: public: multiostream() - : multioutbuf_init(), std::basic_ostream( - multioutbuf_init::buf()) {} + : multioutbuf_init(), + std::basic_ostream(multioutbuf_init::buf()) {} void add(std::basic_ostream& str) { multioutbuf_init::buf()->add(str); diff --git a/include/bout/openmpwrap.hxx b/include/bout/openmpwrap.hxx index 582df7b86c..19cc181787 100644 --- a/include/bout/openmpwrap.hxx +++ b/include/bout/openmpwrap.hxx @@ -1,12 +1,10 @@ -/************************************************************************/ /** - * \brief Openmp utilitiy wrappers - * - * - ************************************************************************** +/// \file +/// Openmp utilitiy wrappers +/************************************************************************** * Copyright 2017 * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -40,8 +38,8 @@ #define INDIRECT1(a) INDIRECT0(omp a) #define INDIRECT2(b) INDIRECT1(b) -//Define a macro wrapper to the use of `#pragma omp` to avoid unknown pragma -//warnings when compiling without openmp support. +/// Wrapper to use `#pragma omp` while avoiding unknown pragma +/// warnings when compiling without openmp support. #define BOUT_OMP_SAFE(...) _Pragma(INDIRECT2(__VA_ARGS__)) #define BOUT_OMP(...) _Pragma(INDIRECT2(__VA_ARGS__)) #else diff --git a/include/bout/operatorstencil.hxx b/include/bout/operatorstencil.hxx index 118dc7a068..1135a79fc7 100644 --- a/include/bout/operatorstencil.hxx +++ b/include/bout/operatorstencil.hxx @@ -33,9 +33,7 @@ #include #include #include -#include #include -#include #include #include @@ -45,17 +43,17 @@ /// subtracted from them. template struct IndexOffset { - static_assert( - std::is_same_v || std::is_same_v || std::is_same_v, - "IndexOffset only works with SpecificInd types"); + static_assert(std::is_same_v || std::is_same_v + || std::is_same_v, + "IndexOffset only works with SpecificInd types"); int dx = 0, dy = 0, dz = 0; - const inline IndexOffset xp(int delta_x = 1) const { return {dx + delta_x, dy, dz}; } - const inline IndexOffset xm(int delta_x = 1) const { return xp(-delta_x); } - const inline IndexOffset yp(int delta_y = 1) const { return {dx, dy + delta_y, dz}; } - const inline IndexOffset ym(int delta_y = 1) const { return yp(-delta_y); } - const inline IndexOffset zp(int delta_z = 1) const { return {dx, dy, dz + delta_z}; } - const inline IndexOffset zm(int delta_z = 1) const { return zp(-delta_z); } + IndexOffset xp(int delta_x = 1) const { return {dx + delta_x, dy, dz}; } + IndexOffset xm(int delta_x = 1) const { return xp(-delta_x); } + IndexOffset yp(int delta_y = 1) const { return {dx, dy + delta_y, dz}; } + IndexOffset ym(int delta_y = 1) const { return yp(-delta_y); } + IndexOffset zp(int delta_z = 1) const { return {dx, dy, dz + delta_z}; } + IndexOffset zm(int delta_z = 1) const { return zp(-delta_z); } IndexOffset& operator+=(const IndexOffset& n) { dx += n.dx; @@ -69,46 +67,29 @@ struct IndexOffset { dz -= n.dz; return *this; } -}; -template -inline bool operator==(const IndexOffset& lhs, const IndexOffset& rhs) { - return lhs.dx == rhs.dx && lhs.dy == rhs.dy && lhs.dz == rhs.dz; -} -template -inline bool operator!=(const IndexOffset& lhs, const IndexOffset& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator<(const IndexOffset& lhs, const IndexOffset& rhs) { - if (lhs.dx != rhs.dx) { - return lhs.dx < rhs.dx; - } else if (lhs.dy != rhs.dy) { - return lhs.dy < rhs.dy; - } else { - return lhs.dz < rhs.dz; - } -} + auto operator<=>(const IndexOffset&) const = default; +}; template -const inline IndexOffset operator+(IndexOffset lhs, const IndexOffset& rhs) { +inline IndexOffset operator+(IndexOffset lhs, const IndexOffset& rhs) { return lhs += rhs; } template -const inline IndexOffset operator-(IndexOffset lhs, const IndexOffset& rhs) { +inline IndexOffset operator-(IndexOffset lhs, const IndexOffset& rhs) { return lhs -= rhs; } template -const inline T operator+(const T& lhs, const IndexOffset& rhs) { +inline T operator+(const T& lhs, const IndexOffset& rhs) { return lhs.offset(rhs.dx, rhs.dy, rhs.dz); } template -const inline T operator+(const IndexOffset& lhs, const T& rhs) { +inline T operator+(const IndexOffset& lhs, const T& rhs) { return operator+(rhs, lhs); } template -const inline T operator-(const T& lhs, const IndexOffset& rhs) { +inline T operator-(const T& lhs, const IndexOffset& rhs) { // If CHECKLEVEL >= 3 then SpecificInd.zm() complains about // negative values. return lhs.offset(-rhs.dx, -rhs.dy, -rhs.dz); @@ -133,9 +114,9 @@ using OffsetIndPerp = IndexOffset; template class OperatorStencil { public: - static_assert( - std::is_same_v || std::is_same_v || std::is_same_v, - "OperatorStencil only works with SpecificInd types"); + static_assert(std::is_same_v || std::is_same_v + || std::is_same_v, + "OperatorStencil only works with SpecificInd types"); using offset = IndexOffset; using stencil_part = std::vector; using stencil_test = std::function; @@ -271,14 +252,11 @@ OperatorStencil squareStencil(Mesh* localmesh) { std::vector> offsetsVec(offsets.begin(), offsets.end()); stencil.add( [localmesh](T ind) -> bool { - return ( - localmesh->xstart <= ind.x() && ind.x() <= localmesh->xend - && (std::is_same_v< - T, - IndPerp> || (localmesh->ystart <= ind.y() && ind.y() <= localmesh->yend)) - && (std::is_same_v< - T, - Ind2D> || (localmesh->zstart <= ind.z() && ind.z() <= localmesh->zend))); + return (localmesh->xstart <= ind.x() && ind.x() <= localmesh->xend + && (std::is_same_v + || (localmesh->ystart <= ind.y() && ind.y() <= localmesh->yend)) + && (std::is_same_v + || (localmesh->zstart <= ind.z() && ind.z() <= localmesh->zend))); }, offsetsVec); stencil.add([](T UNUSED(ind)) -> bool { return true; }, {zero}); @@ -308,14 +286,11 @@ OperatorStencil starStencil(Mesh* localmesh) { std::vector> offsetsVec(offsets.begin(), offsets.end()); stencil.add( [localmesh](T ind) -> bool { - return ( - localmesh->xstart <= ind.x() && ind.x() <= localmesh->xend - && (std::is_same_v< - T, - IndPerp> || (localmesh->ystart <= ind.y() && ind.y() <= localmesh->yend)) - && (std::is_same_v< - T, - Ind2D> || (localmesh->zstart <= ind.z() && ind.z() <= localmesh->zend))); + return (localmesh->xstart <= ind.x() && ind.x() <= localmesh->xend + && (std::is_same_v + || (localmesh->ystart <= ind.y() && ind.y() <= localmesh->yend)) + && (std::is_same_v + || (localmesh->zstart <= ind.z() && ind.z() <= localmesh->zend))); }, offsetsVec); stencil.add([](T UNUSED(ind)) -> bool { return true; }, {zero}); diff --git a/include/bout/options.hxx b/include/bout/options.hxx index 9356326d0e..b7eb9eb29c 100644 --- a/include/bout/options.hxx +++ b/include/bout/options.hxx @@ -12,7 +12,7 @@ * options and allows access to all sub-sections * ************************************************************************** -* Copyright 2010-2024 BOUT++ contributors +* Copyright 2010-2025 BOUT++ contributors * * Contact: Ben Dudson, dudson2@llnl.gov * @@ -39,6 +39,7 @@ class Options; #ifndef OPTIONS_H #define OPTIONS_H +#include "bout/array.hxx" #include "bout/bout_types.hxx" #include "bout/field2d.hxx" #include "bout/field3d.hxx" @@ -51,8 +52,10 @@ class Options; #include "bout/utils.hxx" #include +#include #include +#include #include #include #include @@ -72,19 +75,19 @@ class Options; * which can be used as a map. * * Options options; - * + * * // Set values * options["key"] = 1.0; * * // Get values. Throws BoutException if not found - * int val = options["key"]; // Sets val to 1 + * int val = options["key"]; // Sets val to 1 * * // Return as specified type. Throws BoutException if not found * BoutReal var = options["key"].as(); * * // A default value can be used if key is not found * BoutReal value = options["pi"].withDefault(3.14); - * + * * // Assign value with source label. Throws if already has a value from same source * options["newkey"].assign(1.0, "some source"); * @@ -92,7 +95,7 @@ class Options; * options["newkey"].force(2.0, "some source"); * * A legacy interface is also supported: - * + * * options.set("key", 1.0, "code"); // Sets a key from source "code" * * int val; @@ -117,9 +120,9 @@ class Options; * * Each Options object can also contain any number of sections, which are * themselves Options objects. - * + * * Options §ion = options["section"]; - * + * * which can be nested: * * options["section"]["subsection"]["value"] = 3; @@ -132,13 +135,13 @@ class Options; * * e.g. * options->getSection("section")->getSection("subsection")->set("value", 3); - * + * * Options also know about their parents: * * Options &parent = section.parent(); - * + * * or - * + * * Options *parent = section->getParent(); * * Root options object @@ -148,8 +151,8 @@ class Options; * there is a global singleton Options object which can be accessed with a static function * * Options &root = Options::root(); - * - * or + * + * or * * Options *root = Options::getRoot(); * @@ -191,7 +194,7 @@ public: /// @param[in] parent Parent object /// @param[in] sectionName Name of the section, including path from the root Options(Options* parent_instance, std::string full_name) - : parent_instance(parent_instance), full_name(std::move(full_name)){}; + : parent_instance(parent_instance), full_name(std::move(full_name)) {}; /// Initialise with a value /// These enable Options to be constructed using initializer lists @@ -203,7 +206,16 @@ public: /// The type used to store values using ValueType = bout::utils::variant, Matrix, Tensor>; + Array, Array, Matrix, Matrix, + Tensor, Tensor>; + + /// Methods to iterate over `Options` + auto begin() { return std::begin(children); } + auto end() { return std::end(children); } + auto begin() const { return std::begin(children); } + auto end() const { return std::end(children); } + auto cbegin() const { return std::cbegin(children); } + auto cend() const { return std::cend(children); } /// A tree representation with leaves containing ValueType. /// Used to construct Options from initializer lists. @@ -343,9 +355,7 @@ public: std::map attributes; /// Return true if this value has attribute \p key - bool hasAttribute(const std::string& key) const { - return attributes.find(key) != attributes.end(); - } + bool hasAttribute(const std::string& key) const { return attributes.contains(key); } /// Set attributes, overwriting any already set /// @@ -400,9 +410,8 @@ public: /// Edit distance from original search term std::string::size_type distance; /// Comparison operator so this works in a std::multiset - friend bool operator<(const FuzzyMatch& lhs, const FuzzyMatch& rhs) { - return lhs.distance < rhs.distance; - } + auto operator<=>(const FuzzyMatch& rhs) const { return distance <=> rhs.distance; } + bool operator==(const FuzzyMatch& rhs) const { return distance == rhs.distance; } }; /// Find approximate matches for \p name throughout the whole @@ -430,6 +439,13 @@ public: return inputvalue; } + template + ResT operator=(const BinaryExpr& expr) { + ResT value{expr}; + assign(value); + return value; + } + /// Assign a value to the option. /// This will throw an exception if already has a value /// @@ -561,7 +577,7 @@ public: value_used = true; // Note this is mutable output_info << "\tOption " << full_name << " = " << val; - if (attributes.count("source")) { + if (attributes.contains("source")) { // Specify the source of the setting output_info << " (" << bout::utils::variantToString(attributes.at("source")) << ")"; } @@ -616,8 +632,8 @@ public: // Option not found. Copy the value from the default. this->_set_no_check(def.value, DEFAULT_SOURCE); - output_info << _("\tOption ") << full_name << " = " << def.full_name << " (" - << DEFAULT_SOURCE << ")\n"; + output_info.write("{}{} = {}({})\n", _("\tOption "), full_name, def.full_name, + DEFAULT_SOURCE); } else { // Check if this was previously set as a default option if (bout::utils::variantEqualTo(attributes.at("source"), DEFAULT_SOURCE)) { @@ -889,7 +905,7 @@ private: // If already set, and not time evolving then check for changing values // If a variable has a "time_dimension" attribute then it is assumed // that updates to the value is ok and don't need to be forced. - if (isSet() && (attributes.find("time_dimension") == attributes.end())) { + if (isSet() && (!attributes.contains("time_dimension"))) { // Check if current value the same as new value if (!bout::utils::variantEqualTo(value, val)) { if (force or !bout::utils::variantEqualTo(attributes["source"], source)) { @@ -901,8 +917,8 @@ private: << ")\n"; } else { throw BoutException( - _("Options: Setting a value from same source ({:s}) to new value " - "'{:s}' - old value was '{:s}'."), + _f("Options: Setting a value from same source ({:s}) to new value " + "'{:s}' - old value was '{:s}'."), source, toString(val), bout::utils::variantToString(value)); } } @@ -916,6 +932,9 @@ private: bool similar(T lhs, T rhs) const { return lhs == rhs; } + + /// Replaces the start of the name of an Option and any children + void recursively_update_names(size_t len, const std::string& new_prefix); }; // Specialised assign methods for types stored in ValueType @@ -955,9 +974,15 @@ Options& Options::assign<>(FieldPerp val, std::string source); template <> Options& Options::assign<>(Array val, std::string source); template <> +Options& Options::assign<>(Array val, std::string source); +template <> Options& Options::assign<>(Matrix val, std::string source); template <> +Options& Options::assign<>(Matrix val, std::string source); +template <> Options& Options::assign<>(Tensor val, std::string source); +template <> +Options& Options::assign<>(Tensor val, std::string source); /// Specialised similar comparison methods template <> @@ -967,29 +992,38 @@ inline bool Options::similar(BoutReal lhs, BoutReal rhs) const { /// Specialised as routines template <> -std::string Options::as(const std::string& similar_to) const; +auto Options::as(const std::string& similar_to) const -> std::string; +template <> +auto Options::as(const int& similar_to) const -> int; +template <> +auto Options::as(const BoutReal& similar_to) const -> BoutReal; template <> -int Options::as(const int& similar_to) const; +auto Options::as(const bool& similar_to) const -> bool; template <> -BoutReal Options::as(const BoutReal& similar_to) const; +auto Options::as(const Field2D& similar_to) const -> Field2D; template <> -bool Options::as(const bool& similar_to) const; +auto Options::as(const Field3D& similar_to) const -> Field3D; template <> -Field2D Options::as(const Field2D& similar_to) const; +auto Options::as(const FieldPerp& similar_to) const -> FieldPerp; template <> -Field3D Options::as(const Field3D& similar_to) const; +auto Options::as(const Array& similar_to) const -> Array; template <> -FieldPerp Options::as(const FieldPerp& similar_to) const; +auto Options::as(const Array& similar_to) const -> Array; template <> -Array Options::as>(const Array& similar_to) const; +auto Options::as(const Matrix& similar_to) const -> Matrix; template <> -Matrix Options::as>(const Matrix& similar_to) const; +auto Options::as(const Matrix& similar_to) const -> Matrix; template <> -Tensor Options::as>(const Tensor& similar_to) const; +auto Options::as(const Tensor& similar_to) const -> Tensor; +template <> +auto Options::as(const Tensor& similar_to) const -> Tensor; /// Convert \p value to string std::string toString(const Options& value); +/// Save the parallel fields +void saveParallel(Options& opt, const std::string& name, const Field3D& tosave); + /// Output a stringified \p value to a stream /// /// This is templated to avoid implict casting: anything is @@ -1021,7 +1055,40 @@ namespace details { /// so that we can put the function definitions in the .cxx file, /// avoiding lengthy recompilation if we change it struct OptionsFormatterBase { - auto parse(fmt::format_parse_context& ctx) -> fmt::format_parse_context::iterator; + constexpr auto parse(fmt::format_parse_context& ctx) { + const auto* it = ctx.begin(); + const auto* const end = ctx.end(); + + while (it != end and *it != '}') { + switch (*it) { + case 'd': + docstrings = true; + ++it; + break; + case 'i': + inline_section_names = true; + ++it; + break; + case 'k': + key_only = true; + ++it; + break; + case 's': + source = true; + ++it; + break; + case 'u': + unused = true; + ++it; + break; + default: + throw fmt::format_error("invalid format for 'Options'"); + } + } + + return it; + } + auto format(const Options& options, fmt::format_context& ctx) const -> fmt::format_context::iterator; @@ -1038,8 +1105,6 @@ private: bool key_only{false}; /// Include the 'source' attribute, if present bool source{false}; - /// Format string to passed down to subsections - std::string format_string; }; } // namespace details } // namespace bout diff --git a/include/bout/options_io.hxx b/include/bout/options_io.hxx index 509305aad0..81a21a62c5 100644 --- a/include/bout/options_io.hxx +++ b/include/bout/options_io.hxx @@ -1,3 +1,4 @@ +/// \file /// Parent class for IO to binary files and streams /// /// @@ -5,8 +6,8 @@ /// /// 1. Dump files, containing time history: /// -/// auto dump = OptionsIOFactory::getInstance().createOutput(); -/// dump->write(data); +/// auto dump = OptionsIOFactory::getInstance().createOutput(); +/// dump->write(data); /// /// where data is an Options tree. By default dump files are configured /// with the root `output` section, or an Option tree can be passed to @@ -14,19 +15,19 @@ /// /// 2. Restart files: /// -/// auto restart = OptionsIOFactory::getInstance().createOutput(); -/// restart->write(data); +/// auto restart = OptionsIOFactory::getInstance().createOutput(); +/// restart->write(data); /// /// where data is an Options tree. By default restart files are configured /// with the root `restart_files` section, or an Option tree can be passed to /// `createRestart`. /// /// 3. Ad-hoc single files -/// Note: The caller should consider how multiple processors interact with the file. +/// Note: The caller should consider how multiple processors interact with the file. /// -/// auto file = OptionsIOFactory::getInstance().createFile("some_file.nc"); -/// or -/// auto file = OptionsIO::create("some_file.nc"); +/// auto file = OptionsIOFactory::getInstance().createFile("some_file.nc"); +/// // or +/// auto file = OptionsIO::create("some_file.nc"); /// /// @@ -42,8 +43,48 @@ #include #include +class Mesh; + namespace bout { +/// Parent class for IO to binary files and streams +/// +/// +/// Usage: +/// +/// 1. Dump files, containing time history: +/// +/// auto dump = OptionsIOFactory::getInstance().createOutput(); +/// dump->write(data); +/// +/// where data is an Options tree. By default dump files are configured +/// with the root `output` section, or an Option tree can be passed to +/// `createOutput`. +/// +/// 2. Restart files: +/// +/// auto restart = OptionsIOFactory::getInstance().createRestart(); +/// restart->write(data); +/// +/// where data is an Options tree. By default restart files are configured +/// with the root `restart_files` section, or an Option tree can be passed to +/// `createRestart`. +/// +/// 3. Ad-hoc single files +/// Note: The caller should consider how multiple processors interact with the file. +/// +/// auto file = OptionsIOFactory::getInstance().createFile("some_file.nc"); +/// or +/// auto file = OptionsIO::create("some_file.nc"); +/// +/// 4. Ad-hoc parallel files +/// This adds also metric information, such that the file can be read with +/// boutdata or xBOUT +/// +/// OptionIO::write("some_file", data, mesh); +/// +/// if mesh is omitted, no grid information is added. +/// class OptionsIO { public: /// No default constructor, as settings are required @@ -51,7 +92,7 @@ public: /// Constructor specifies the kind of file, and options to control /// the name of file, mode of operation etc. - OptionsIO(Options&) {} + OptionsIO(Options& /*unused*/) {} virtual ~OptionsIO() = default; @@ -73,10 +114,18 @@ public: /// ADIOS: Indicate completion of an output step. virtual void verifyTimesteps() const = 0; + /// NetCDF: Flush file to disk + virtual void flush() {} + /// Create an OptionsIO for I/O to the given file. /// This uses the default file type and default options. static std::unique_ptr create(const std::string& file); + /// Write some data to a file with a given name prefix + /// This will be done in parallel. If Mesh is given, also mesh data will be + /// added, which is needed for xBOUT or boutdata to read the files. + static void write(const std::string& prefix, Options& data, Mesh* mesh = nullptr); + /// Create an OptionsIO for I/O to the given file. /// The file will be configured using the given `config` options: /// - "type" : string The file type e.g. "netcdf" or "adios" diff --git a/include/bout/optionsreader.hxx b/include/bout/optionsreader.hxx index de3d40514d..ca9778b3c4 100644 --- a/include/bout/optionsreader.hxx +++ b/include/bout/optionsreader.hxx @@ -1,17 +1,17 @@ -/*!************************************************************************ +/*! \file * Singleton class for reading options files * * Uses a bridge pattern to access OptionParser classes to parse * different file formats * * Handles the command-line parsing -* * -************************************************************************** +*/ +/************************************************************************* * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk -* +* * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -36,7 +36,8 @@ class OptionsReader; #include "bout/options.hxx" -#include "fmt/core.h" +#include +#include #include #include @@ -46,11 +47,11 @@ class OptionsReader; /// Example /// ------- /// -/// Options opt; -/// OptionsReader::getInstance()->read(&opt, "somefile.inp"); -/// -/// opt now contains a tree of sections and options from the input file "somefile.inp" +/// Options opt; +/// OptionsReader::getInstance()->read(&opt, "somefile.inp"); /// +/// ``opt`` now contains a tree of sections and options from the input +/// file "somefile.inp" class OptionsReader { public: /// Return a pointer to the instance singleton @@ -69,9 +70,10 @@ public: /// @param[in] file The name of the file. printf style arguments can be used to create the file name. void read(Options* options, const std::string& filename); - template - void read(Options* options, const S& format, const Args&... args) { - return read(options, fmt::format(format, args...)); + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + void read(Options* options, fmt::format_string format, Args&&... args) { + return read(options, fmt::vformat(format, fmt::make_format_args(args...))); } /// Write options to file @@ -80,9 +82,10 @@ public: /// @param[in] file The name of the file to (over)write void write(Options* options, const std::string& filename); - template - void write(Options* options, const S& format, const Args&... args) { - return write(options, fmt::format(format, args...)); + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + void write(Options* options, fmt::format_string format, Args&&... args) { + return write(options, fmt::vformat(format, fmt::make_format_args(args...))); } /// Parse options from the command line diff --git a/include/bout/output.hxx b/include/bout/output.hxx index 2862899067..1399f2cbd7 100644 --- a/include/bout/output.hxx +++ b/include/bout/output.hxx @@ -1,7 +1,7 @@ +/// \file +/// Logging, for printing messages/errors etc. + /************************************************************************** - * Output, for printing messages/errors etc. - * - ************************************************************************** * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk @@ -29,54 +29,62 @@ class Output; #ifndef BOUT_OUTPUT_H #define BOUT_OUTPUT_H -#include "bout/multiostream.hxx" #include -#include #include #include #include "bout/assert.hxx" -#include "bout/boutexception.hxx" -#include "bout/sys/gettext.hxx" // for gettext _() macro +#include "bout/build_defines.hxx" +#include "bout/multiostream.hxx" +#include "bout/sys/gettext.hxx" // IWYU pragma: keep for gettext _() macro #include "bout/unused.hxx" -#include "fmt/core.h" +#include +#include + +#include using std::endl; /// Class for text output to stdout and/or log file -/*! - This class can be used to output either in fmt format: - - output.write("A string {:s} and number {:d}\n", str, i); - - or as a C++ stream buffer: - - output << "A string " << str << " and number " << i << endl; - - If a file has been opened (i.e. the processor's log file) then the string - will be written to the file. In addition, output to stdout can be enabled - and disabled. -*/ +/// +/// This class can be used to output either in ``fmt`` format: +/// +/// output.write("A string {:s} and number {:d}\n", str, i); +/// +/// or as a C++ stream buffer: +/// +/// output << "A string " << str << " and number " << i << endl; +/// +/// If a file has been opened (i.e. the processor's log file) then the string +/// will be written to the file. In addition, output to stdout can be enabled +/// and disabled. class Output : private multioutbuf_init>, public std::basic_ostream> { - using _Tr = std::char_traits; - using multioutbuf_init = ::multioutbuf_init; + using Tr = std::char_traits; + using multioutbuf_init = ::multioutbuf_init; public: - Output() : multioutbuf_init(), std::basic_ostream(multioutbuf_init::buf()) { + Output() : multioutbuf_init(), std::basic_ostream(multioutbuf_init::buf()) { Output::enable(); } + Output(const Output&) = delete; + Output(Output&&) = delete; + Output& operator=(const Output&) = delete; + Output& operator=(Output&&) = delete; + /// Specify a log file to open Output(const std::string& filename) { Output::enable(); open(filename); } - template - Output(const S& format, const Args&... args) : Output(fmt::format(format, args...)) {} + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + Output(fmt::format_string format, Args&&... args) + : Output(fmt::vformat(format, fmt::make_format_args(args...))) {} ~Output() override { close(); } @@ -86,9 +94,10 @@ public: /// Open an output log file int open(const std::string& filename); - template - int open(const S& format, const Args&... args) { - return open(fmt::format(format, args...)); + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + int open(fmt::format_string format, Args&&... args) { + return open(fmt::vformat(format, fmt::make_format_args(args...))); } /// Close the log file @@ -97,25 +106,25 @@ public: /// Write a string using fmt format virtual void write(const std::string& message); - template - void write(const S& format, const Args&... args) { - write(fmt::format(format, args...)); + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + void write(fmt::format_string format, Args&&... args) { + write(fmt::vformat(format, fmt::make_format_args(args...))); } /// Same as write, but only to screen virtual void print(const std::string& message); - template - void print(const S& format, const Args&... args) { - print(fmt::format(format, args...)); + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + void print(fmt::format_string format, Args&&... args) { + print(fmt::vformat(format, fmt::make_format_args(args...))); } /// Add an output stream. All output will be sent to all streams - void add(std::basic_ostream& str) { multioutbuf_init::buf()->add(str); } + void add(std::basic_ostream& str) { multioutbuf_init::buf()->add(str); } /// Remove an output stream - void remove(std::basic_ostream& str) { - multioutbuf_init::buf()->remove(str); - } + void remove(std::basic_ostream& str) { multioutbuf_init::buf()->remove(str); } static Output* getInstance(); ///< Return pointer to instance @@ -126,7 +135,7 @@ protected: private: std::ofstream file; ///< Log file stream - bool enabled; ///< Whether output to stdout is enabled + bool enabled{}; ///< Whether output to stdout is enabled }; /// Class which behaves like Output, but has no effect. @@ -136,14 +145,14 @@ private: class DummyOutput : public Output { public: template - void write([[maybe_unused]] const S& format, [[maybe_unused]] const Args&... args){}; + void write([[maybe_unused]] const S& format, [[maybe_unused]] Args&&... args) {}; template - void print([[maybe_unused]] const S& format, [[maybe_unused]] const Args&... args){}; - void write([[maybe_unused]] const std::string& message) override{}; - void print([[maybe_unused]] const std::string& message) override{}; - void enable() override{}; - void disable() override{}; - void enable([[maybe_unused]] bool enable){}; + void print([[maybe_unused]] const S& format, [[maybe_unused]] Args&&... args) {}; + void write([[maybe_unused]] const std::string& message) override {}; + void print([[maybe_unused]] const std::string& message) override {}; + void enable() override {}; + void disable() override {}; + void enable([[maybe_unused]] bool enable) {}; bool isEnabled() override { return false; } }; @@ -156,24 +165,25 @@ class ConditionalOutput : public Output { public: /// @param[in] base The Output object which will be written to if enabled /// @param[in] enabled Should this be enabled by default? - ConditionalOutput(Output* base, bool enabled = true) : base(base), enabled(enabled){}; + ConditionalOutput(Output* base, bool enabled = true) : base(base), enabled(enabled) {}; /// Constuctor taking ConditionalOutput. This allows several layers of conditions /// /// @param[in] base A ConditionalOutput which will be written to if enabled /// - ConditionalOutput(ConditionalOutput* base) : base(base), enabled(base->enabled){}; + ConditionalOutput(ConditionalOutput* base) : base(base), enabled(base->enabled) {}; /// If enabled, writes a string using fmt formatting /// by calling base->write /// This string is then sent to log file and stdout (on processor 0) void write(const std::string& message) override; - template - void write(const S& format, const Args&... args) { + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + void write(fmt::format_string format, Args&&... args) { if (enabled) { ASSERT1(base != nullptr); - base->write(fmt::format(format, args...)); + base->write(fmt::vformat(format, fmt::make_format_args(args...))); } } @@ -181,11 +191,12 @@ public: /// note: unlike write, this is not also sent to log files void print(const std::string& message) override; - template - void print(const S& format, const Args&... args) { + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + void print(fmt::format_string format, Args&&... args) { if (enabled) { ASSERT1(base != nullptr); - base->print(fmt::format(format, args...)); + base->print(fmt::vformat(format, fmt::make_format_args(args...))); } } @@ -216,8 +227,6 @@ private: /// The lower-level Output to send output to Output* base; -protected: - friend class WithQuietOutput; /// Does this instance output anything? bool enabled; }; @@ -227,7 +236,7 @@ protected: /// output_debug << "debug message"; /// compile but have no effect if BOUT_USE_OUTPUT_DEBUG is false template -DummyOutput& operator<<(DummyOutput& out, T const& UNUSED(t)) { +DummyOutput& operator<<(DummyOutput& out, const T& UNUSED(t)) { return out; } @@ -251,7 +260,7 @@ inline ConditionalOutput& operator<<(ConditionalOutput& out, stream_manipulator } template -ConditionalOutput& operator<<(ConditionalOutput& out, T const& t) { +ConditionalOutput& operator<<(ConditionalOutput& out, const T& t) { if (out.isEnabled()) { *out.getBase() << t; } @@ -276,18 +285,23 @@ ConditionalOutput& operator<<(ConditionalOutput& out, const T* t) { /// // output now enabled class WithQuietOutput { public: - explicit WithQuietOutput(ConditionalOutput& output_in) : output(output_in) { - state = output.enabled; - output.disable(); + WithQuietOutput(const WithQuietOutput&) = delete; + WithQuietOutput(WithQuietOutput&&) = delete; + WithQuietOutput& operator=(const WithQuietOutput&) = delete; + WithQuietOutput& operator=(WithQuietOutput&&) = delete; + explicit WithQuietOutput(ConditionalOutput& output_in) + : output(&output_in), state(output->isEnabled()) { + output->disable(); } - ~WithQuietOutput() { output.enable(state); } + ~WithQuietOutput() { output->enable(state); } private: - ConditionalOutput& output; + ConditionalOutput* output; bool state; }; +// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) /// To allow statements like "output.write(...)" or "output << ..." /// Output for debugging #ifdef BOUT_USE_OUTPUT_DEBUG @@ -303,5 +317,6 @@ extern ConditionalOutput output_verbose; ///< less interesting messages /// Generic output, given the same level as output_progress extern ConditionalOutput output; +// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) #endif // BOUT_OUTPUT_H diff --git a/include/bout/output_bout_types.hxx b/include/bout/output_bout_types.hxx index b67762521b..77ea8ebf2d 100644 --- a/include/bout/output_bout_types.hxx +++ b/include/bout/output_bout_types.hxx @@ -5,10 +5,21 @@ #ifndef OUTPUT_BOUT_TYPES_H #define OUTPUT_BOUT_TYPES_H +#include "bout/bout_types.hxx" +#include "bout/mesh.hxx" +#include "bout/output.hxx" // IWYU pragma: keep +#include "bout/region.hxx" +#include "bout/traits.hxx" + +#include +#include #include -#include "bout/output.hxx" -#include "bout/region.hxx" +#include +#include +#include +#include +#include template struct fmt::formatter> { @@ -17,7 +28,8 @@ struct fmt::formatter> { // Parses format specifications of the form ['c' | 'i']. constexpr auto parse(format_parse_context& ctx) { - auto it = ctx.begin(), end = ctx.end(); + const auto* it = ctx.begin(); + const auto* end = ctx.end(); if (it != end && (*it == 'c' || *it == 'i')) { presentation = *it++; } @@ -50,4 +62,224 @@ struct fmt::formatter> { } }; +namespace bout { +namespace details { +template +/// Transpose a region so that it iterates in Z first, then Y, then X +/// +/// Caution: this is the most inefficient memory order! +auto region_transpose(const Region& region) -> Region; + +auto colour(BoutReal value, BoutReal min, BoutReal max) -> fmt::text_style; + +// Parses the range [begin, end) as an unsigned integer. This function assumes +// that the range is non-empty and the first character is a digit. +// +// Taken from fmt +// Copyright (c) 2012 - present, Victor Zverovich +// SPDX-License-Identifier: MIT +constexpr auto parse_nonnegative_int(const char*& begin, const char* end, + int error_value) noexcept -> int { + const auto* p = begin; + unsigned value = *p - '0'; + unsigned prev = 0; + ++p; + + while (p != end && '0' <= *p && *p <= '9') { + prev = value; + value = (value * 10) + unsigned(*p - '0'); + ++p; + } + auto num_digits = p - begin; + begin = p; + const auto digits10 = static_cast(sizeof(int) * CHAR_BIT * 3 / 10); + if (num_digits <= digits10) { + return static_cast(value); + } + // Check for overflow. + const unsigned max = INT_MAX; + return num_digits == digits10 + 1 and (prev * 10ULL) + unsigned(p[-1] - '0') <= max + ? static_cast(value) + : error_value; +} +} // namespace details +} // namespace bout + +/// Formatter for Fields +/// +/// Format specification: +/// +/// - ``n``: Don't show indices +/// - ``r''``: Use given region (default: ``RGN_ALL``) +/// - ``T``: Transpose field so X is first dimension +/// - ``#``: Plot slices as 2D heatmap +/// - ``e``: Number of elements at each edge to show +/// - ``f``: Show full field +template +struct fmt::formatter, char>> { +private: + fmt::formatter underlying; + + static constexpr auto default_region = "RGN_ALL"; + std::string_view region = default_region; + + bool show_indices = true; + bool transpose = false; + bool plot = false; + int edgeitems = 4; + bool show_full = false; + +public: + constexpr auto parse(format_parse_context& ctx) { + const auto* it = ctx.begin(); + const auto* end = ctx.end(); + + if (it == end) { + return underlying.parse(ctx); + } + + while (it != end and *it != ':' and *it != '}') { + // Other cases handled explicitly below + // NOLINTNEXTLINE(bugprone-switch-missing-default-case) + switch (*it) { + case 'e': + ++it; + edgeitems = bout::details::parse_nonnegative_int(it, end, -1); + if (edgeitems == -1) { + throw fmt::format_error("number is too big"); + } + break; + case 'f': + show_full = true; + ++it; + break; + case 'r': + ++it; + if (*it != '\'') { + throw fmt::format_error("invalid format for Field"); + } + { + const auto* rgn_start = ++it; + std::size_t size = 0; + while (*it != '\'') { + ++size; + ++it; + } + region = std::string_view(rgn_start, size); + } + ++it; + break; + case 'n': + show_indices = false; + ++it; + break; + case 'T': + transpose = true; + ++it; + break; + case '#': + plot = true; + show_indices = false; + ++it; + break; + } + } + + if (it != end and *it != '}') { + if (*it != ':') { + throw fmt::format_error("invalid format specifier"); + } + ++it; + } + + ctx.advance_to(it); + return underlying.parse(ctx); + } + + auto format(const T& f, format_context& ctx) const -> format_context::iterator { + using namespace bout::details; + + const auto* mesh = f.getMesh(); + + const auto rgn_str = std::string{region}; + const auto rgn_ = f.getRegion(rgn_str); + const auto rgn = transpose ? region_transpose(rgn_) : rgn_; + + const auto i = rgn.begin(); + int previous_x = i->x(); + int previous_y = i->y(); + int previous_z = i->z(); + + const auto last_i = rgn.getIndices().rbegin(); + const int last_x = last_i->x(); + const int last_y = last_i->y(); + const int last_z = last_i->z(); + + // Indices of edges + const int start_x = previous_x + edgeitems; + const int start_y = previous_y + edgeitems; + const int start_z = previous_z + edgeitems; + const int end_x = last_x - edgeitems; + const int end_y = last_y - edgeitems; + const int end_z = last_z - edgeitems; + + // Range of the data for plotting + BoutReal plot_min = 0.0; + BoutReal plot_max = 0.0; + if (plot) { + plot_min = min(f, false, rgn_str); + plot_max = max(f, false, rgn_str); + } + + // Separators + const auto block_sep = fmt::runtime("\n\n"); + const auto item_sep = fmt::runtime(plot ? "" : " "); + const auto x_sep = transpose ? item_sep : block_sep; + const auto z_sep = transpose ? block_sep : item_sep; + + // If we've shown the skip sep already this dim + bool shown_skip = false; + constexpr auto skip_sep = "..."; + + BOUT_FOR_SERIAL(i, rgn) { + const auto ix = i.x(); + const auto iy = i.y(); + const auto iz = i.z(); + + const bool should_show = + show_full + or ((ix < start_x or ix > end_x) and (iy < start_y or iy > end_y) + and (iz < start_z or iz > end_z)); + + if ((not shown_skip or should_show) and iz > previous_z) { + format_to(ctx.out(), z_sep); + } + if ((not shown_skip or should_show) and iy > previous_y) { + format_to(ctx.out(), "\n"); + } + if ((not shown_skip or should_show) and ix > previous_x) { + format_to(ctx.out(), x_sep); + } + + if (show_indices and should_show) { + format_to(ctx.out(), "{:c}: ", i); + } + if (plot) { + format_to(ctx.out(), "{}", styled("█", colour(f[i], plot_min, plot_max))); + } else if (should_show) { + underlying.format(f[i], ctx); + format_to(ctx.out(), ";"); + shown_skip = false; + } else if (not shown_skip) { + format_to(ctx.out(), skip_sep); + shown_skip = true; + } + previous_x = ix; + previous_y = iy; + previous_z = iz; + } + return format_to(ctx.out(), ""); + } +}; + #endif // OUTPUT_BOUT_TYPES_H diff --git a/include/bout/parallel_boundary_op.hxx b/include/bout/parallel_boundary_op.hxx index d8620e892b..6bd692f2a2 100644 --- a/include/bout/parallel_boundary_op.hxx +++ b/include/bout/parallel_boundary_op.hxx @@ -2,13 +2,15 @@ #define BOUT_PAR_BNDRY_OP_H #include "bout/boundary_op.hxx" +#include "bout/boundary_region_iter.hxx" #include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/field3d.hxx" #include "bout/field_factory.hxx" -#include "bout/parallel_boundary_region.hxx" +#include "bout/sys/expressionparser.hxx" #include "bout/unused.hxx" -#include "bout/utils.hxx" -#include +#include ////////////////////////////////////////////////// // Base class @@ -16,30 +18,79 @@ class BoundaryOpPar : public BoundaryOpBase { public: BoundaryOpPar() = default; - BoundaryOpPar(BoundaryRegionPar* region, std::shared_ptr value) + BoundaryOpPar(bout::boundary::BoundaryRegionFCI* region, + std::shared_ptr value) : bndry(region), gen_values(std::move(value)), value_type(ValueType::GEN) {} - BoundaryOpPar(BoundaryRegionPar* region, Field3D* value) + BoundaryOpPar(bout::boundary::BoundaryRegionFCI* region, Field3D* value) : bndry(region), field_values(value), value_type(ValueType::FIELD) {} - BoundaryOpPar(BoundaryRegionPar* region, BoutReal value) + BoundaryOpPar(bout::boundary::BoundaryRegionFCI* region, BoutReal value) : bndry(region), real_value(value), value_type(ValueType::REAL) {} - BoundaryOpPar(BoundaryRegionPar* region) + BoundaryOpPar(bout::boundary::BoundaryRegionFCI* region) : bndry(region), real_value(0.), value_type(ValueType::REAL) {} + BoundaryOpPar(bout::boundary::BoundaryRegionX* region, + std::shared_ptr value) + : bndryX(region), gen_values(std::move(value)), value_type(ValueType::GEN) {} + BoundaryOpPar(bout::boundary::BoundaryRegionX* region, Field3D* value) + : bndryX(region), field_values(value), value_type(ValueType::FIELD) {} + BoundaryOpPar(bout::boundary::BoundaryRegionX* region, BoutReal value) + : bndryX(region), real_value(value) {} + BoundaryOpPar(bout::boundary::BoundaryRegionX* region) : bndryX(region) {} + BoundaryOpPar(bout::boundary::BoundaryRegionY* region, + std::shared_ptr value) + : bndryY(region), gen_values(std::move(value)), value_type(ValueType::GEN) {} + BoundaryOpPar(bout::boundary::BoundaryRegionY* region, Field3D* value) + : bndryY(region), field_values(value), value_type(ValueType::FIELD) {} + BoundaryOpPar(bout::boundary::BoundaryRegionY* region, BoutReal value) + : bndryY(region), real_value(value) {} + BoundaryOpPar(bout::boundary::BoundaryRegionY* region) : bndryY(region) {} + BoundaryOpPar(BoundaryOpPar* region, std::shared_ptr value) + : bndry(region->bndry), gen_values(std::move(value)), value_type(ValueType::GEN) {} + BoundaryOpPar(BoundaryOpPar* region, Field3D* value) + : bndry(region->bndry), field_values(value), value_type(ValueType::FIELD) {} + BoundaryOpPar(BoundaryOpPar* region, BoutReal value) + : bndry(region->bndry), real_value(value) {} + BoundaryOpPar(BoundaryOpPar* region) : bndry(region->bndry) {} ~BoundaryOpPar() override = default; // Note: All methods must implement clone, except for modifiers (see below) - virtual BoundaryOpPar* clone(BoundaryRegionPar* region, + virtual BoundaryOpPar* clone(bout::boundary::BoundaryRegionFCI* region, const std::list& args) = 0; - virtual BoundaryOpPar* clone(BoundaryRegionPar* region, Field3D* f) = 0; + virtual BoundaryOpPar* clone(bout::boundary::BoundaryRegionFCI* region, Field3D* f) = 0; virtual BoundaryOpPar* - clone(BoundaryRegionPar* region, const std::list& args, + clone(bout::boundary::BoundaryRegionFCI* region, const std::list& args, + const std::map& UNUSED(keywords)) { + return clone(region, args); + } + virtual BoundaryOpPar* clone(bout::boundary::BoundaryRegionX* region, + const std::list& args) = 0; + virtual BoundaryOpPar* clone(bout::boundary::BoundaryRegionX* region, Field3D* f) = 0; + virtual BoundaryOpPar* + clone(bout::boundary::BoundaryRegionX* region, const std::list& args, + const std::map& UNUSED(keywords)) { + return clone(region, args); + } + virtual BoundaryOpPar* clone(bout::boundary::BoundaryRegionY* region, + const std::list& args) = 0; + virtual BoundaryOpPar* clone(bout::boundary::BoundaryRegionY* region, Field3D* f) = 0; + virtual BoundaryOpPar* + clone(bout::boundary::BoundaryRegionY* region, const std::list& args, + const std::map& UNUSED(keywords)) { + return clone(region, args); + } + virtual BoundaryOpPar* clone(BoundaryOpPar* region, + const std::list& args) = 0; + virtual BoundaryOpPar* clone(BoundaryOpPar* region, Field3D* f) = 0; + virtual BoundaryOpPar* + clone(BoundaryOpPar* region, const std::list& args, const std::map& UNUSED(keywords)) { - // If not implemented, call two-argument version return clone(region, args); } - BoundaryRegionPar* bndry{nullptr}; +private: + bout::boundary::BoundaryRegionFCI* bndry{nullptr}; + bout::boundary::BoundaryRegionX* bndryX{nullptr}; + bout::boundary::BoundaryRegionY* bndryY{nullptr}; -protected: /// Possible ways to get boundary values std::shared_ptr gen_values; Field3D* field_values{nullptr}; @@ -49,7 +100,12 @@ protected: enum class ValueType { GEN, FIELD, REAL }; const ValueType value_type{ValueType::REAL}; - BoutReal getValue(const BoundaryRegionPar& bndry, BoutReal t); + BoutReal getValue(const bout::boundary::BoundaryRegionFCI::Point& bndry, BoutReal t); + BoutReal getValue(const bout::boundary::BoundaryRegionX::Iterator& bndry, BoutReal t); + BoutReal getValue(const bout::boundary::BoundaryRegionY::Iterator& bndry, BoutReal t); + + template + friend class BoundaryOpParTemp; }; template @@ -59,8 +115,63 @@ public: using BoundaryOpPar::clone; - // Note: All methods must implement clone, except for modifiers (see below) - BoundaryOpPar* clone(BoundaryRegionPar* region, + BoundaryOpPar* clone(BoundaryOpPar* region, + const std::list& args) override { + if (!args.empty()) { + try { + real_value = stringToReal(args.front()); + return new T(region, real_value); + } catch (const BoutException&) { + std::shared_ptr newgen = nullptr; + // First argument should be an expression + newgen = FieldFactory::get()->parse(args.front()); + return new T(region, newgen); + } + } + + return new T(region); + } + BoundaryOpPar* clone(bout::boundary::BoundaryRegionFCI* region, + const std::list& args) override { + if (!args.empty()) { + try { + real_value = stringToReal(args.front()); + return new T(region, real_value); + } catch (const BoutException&) { + std::shared_ptr newgen = nullptr; + // First argument should be an expression + newgen = FieldFactory::get()->parse(args.front()); + return new T(region, newgen); + } + } + + return new T(region); + } + + BoundaryOpPar* clone(bout::boundary::BoundaryRegionFCI* region, Field3D* f) override { + return new T(region, f); + } + BoundaryOpPar* clone(bout::boundary::BoundaryRegionX* region, + const std::list& args) override { + if (!args.empty()) { + try { + real_value = stringToReal(args.front()); + return new T(region, real_value); + } catch (const BoutException&) { + std::shared_ptr newgen = nullptr; + // First argument should be an expression + newgen = FieldFactory::get()->parse(args.front()); + return new T(region, newgen); + } + } + + return new T(region); + } + + BoundaryOpPar* clone(bout::boundary::BoundaryRegionX* region, Field3D* f) override { + return new T(region, f); + } + BoundaryOpPar* clone(bout::boundary::BoundaryRegionY* region, const std::list& args) override { if (!args.empty()) { try { @@ -77,7 +188,10 @@ public: return new T(region); } - BoundaryOpPar* clone(BoundaryRegionPar* region, Field3D* f) override { + BoundaryOpPar* clone(bout::boundary::BoundaryRegionY* region, Field3D* f) override { + return new T(region, f); + } + BoundaryOpPar* clone(BoundaryOpPar* region, Field3D* f) override { return new T(region, f); } @@ -91,16 +205,38 @@ public: void apply(Field3D& f) override { return apply(f, 0); } void apply(Field3D& f, BoutReal t) override { - f.ynext(bndry->dir).allocate(); // Ensure unique before modifying - - auto dy = f.getCoordinates()->dy; - - for (bndry->first(); !bndry->isDone(); bndry->next()) { - BoutReal value = getValue(*bndry, t); - if (isNeumann) { - value *= dy[bndry->ind()]; + if (bndry != nullptr) { + f.ynext(bndry->dir()).allocate(); // Ensure unique before modifying + auto dy = f.getCoordinates()->dy(); + for (auto pnt : *bndry) { + BoutReal value = getValue(pnt, t); + if (isNeumann) { + value *= dy[pnt.ind()]; + } + static_cast(this)->apply_stencil(f, pnt, value); + } + } + if (bndryX != nullptr) { + f.allocate(); + auto dy = f.getCoordinates()->dx(); + for (auto pnt : *bndryX) { + BoutReal value = getValue(pnt, t); + if (isNeumann) { + value *= dy[pnt.ind()]; + } + static_cast(this)->apply_stencil(f, pnt, value); + } + } + if (bndryY != nullptr) { + f.allocate(); + auto dy = f.getCoordinates()->dy(); + for (auto pnt : *bndryY) { + BoutReal value = getValue(pnt, t); + if (isNeumann) { + value *= dy[pnt.ind()]; + } + static_cast(this)->apply_stencil(f, pnt, value); } - static_cast(this)->apply_stencil(f, bndry, value); } } }; @@ -111,24 +247,27 @@ public: class BoundaryOpPar_dirichlet_o1 : public BoundaryOpParTemp { public: using BoundaryOpParTemp::BoundaryOpParTemp; - static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) { - bndry->dirichlet_o1(f, value); + template + static void apply_stencil(Field3D& f, Iter& pnt, BoutReal value) { + dirichlet_o1(pnt, f, value); } }; class BoundaryOpPar_dirichlet_o2 : public BoundaryOpParTemp { public: using BoundaryOpParTemp::BoundaryOpParTemp; - static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) { - bndry->dirichlet_o2(f, value); + template + static void apply_stencil(Field3D& f, Iter& pnt, BoutReal value) { + dirichlet_o2(pnt, f, value); } }; class BoundaryOpPar_dirichlet_o3 : public BoundaryOpParTemp { public: using BoundaryOpParTemp::BoundaryOpParTemp; - static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) { - bndry->dirichlet_o3(f, value); + template + static void apply_stencil(Field3D& f, Iter& pnt, BoutReal value) { + dirichlet_o3(pnt, f, value); } }; @@ -136,8 +275,9 @@ class BoundaryOpPar_neumann_o1 : public BoundaryOpParTemp { public: using BoundaryOpParTemp::BoundaryOpParTemp; - static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) { - bndry->neumann_o1(f, value); + template + static void apply_stencil(Field3D& f, Iter& pnt, BoutReal value) { + neumann_o1(pnt, f, value); } }; @@ -145,8 +285,9 @@ class BoundaryOpPar_neumann_o2 : public BoundaryOpParTemp { public: using BoundaryOpParTemp::BoundaryOpParTemp; - static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) { - bndry->neumann_o2(f, value); + template + static void apply_stencil(Field3D& f, Iter& pnt, BoutReal value) { + neumann_o2(pnt, f, value); } }; @@ -154,8 +295,9 @@ class BoundaryOpPar_neumann_o3 : public BoundaryOpParTemp { public: using BoundaryOpParTemp::BoundaryOpParTemp; - static void apply_stencil(Field3D& f, const BoundaryRegionPar* bndry, BoutReal value) { - bndry->neumann_o3(f, value); + template + static void apply_stencil(Field3D& f, Iter& pnt, BoutReal value) { + neumann_o3(pnt, f, value); } }; diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx deleted file mode 100644 index 4d5278d00f..0000000000 --- a/include/bout/parallel_boundary_region.hxx +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef BOUT_PAR_BNDRY_H -#define BOUT_PAR_BNDRY_H - -#include "bout/boundary_region.hxx" -#include "bout/bout_types.hxx" -#include - -#include -#include - -/** - * Boundary region for parallel direction. This contains a vector of points that are - * inside the boundary. - * - */ - -namespace parallel_stencil { -// generated by src/mesh/parallel_boundary_stencil.cxx.py -inline BoutReal pow(BoutReal val, int exp) { - // constexpr int expval = exp; - // static_assert(expval == 2 or expval == 3, "This pow is only for exponent 2 or 3"); - if (exp == 2) { - return val * val; - } - ASSERT3(exp == 3); - return val * val * val; -} -inline BoutReal dirichlet_o1(BoutReal UNUSED(spacing0), BoutReal value0) { - return value0; -} -inline BoutReal dirichlet_o2(BoutReal spacing0, BoutReal value0, BoutReal spacing1, - BoutReal value1) { - return (spacing0 * value1 - spacing1 * value0) / (spacing0 - spacing1); -} -inline BoutReal neumann_o2(BoutReal UNUSED(spacing0), BoutReal value0, BoutReal spacing1, - BoutReal value1) { - return -spacing1 * value0 + value1; -} -inline BoutReal dirichlet_o3(BoutReal spacing0, BoutReal value0, BoutReal spacing1, - BoutReal value1, BoutReal spacing2, BoutReal value2) { - return (pow(spacing0, 2) * spacing1 * value2 - pow(spacing0, 2) * spacing2 * value1 - - spacing0 * pow(spacing1, 2) * value2 + spacing0 * pow(spacing2, 2) * value1 - + pow(spacing1, 2) * spacing2 * value0 - spacing1 * pow(spacing2, 2) * value0) - / ((spacing0 - spacing1) * (spacing0 - spacing2) * (spacing1 - spacing2)); -} -inline BoutReal neumann_o3(BoutReal spacing0, BoutReal value0, BoutReal spacing1, - BoutReal value1, BoutReal spacing2, BoutReal value2) { - return (2 * spacing0 * spacing1 * value2 - 2 * spacing0 * spacing2 * value1 - + pow(spacing1, 2) * spacing2 * value0 - pow(spacing1, 2) * value2 - - spacing1 * pow(spacing2, 2) * value0 + pow(spacing2, 2) * value1) - / ((spacing1 - spacing2) * (2 * spacing0 - spacing1 - spacing2)); -} -} // namespace parallel_stencil - -class BoundaryRegionPar : public BoundaryRegionBase { - - struct RealPoint { - BoutReal s_x; - BoutReal s_y; - BoutReal s_z; - }; - - struct Indices { - // Indices of the boundary point - Ind3D index; - // Intersection with boundary in index space - RealPoint intersection; - // Distance to intersection - BoutReal length; - // Angle between field line and boundary - // BoutReal angle; - // How many points we can go in the opposite direction - signed char valid; - }; - - using IndicesVec = std::vector; - using IndicesIter = IndicesVec::iterator; - - /// Vector of points in the boundary - IndicesVec bndry_points; - /// Current position in the boundary points - IndicesIter bndry_position; - -public: - BoundaryRegionPar(const std::string& name, int dir, Mesh* passmesh) - : BoundaryRegionBase(name, passmesh), dir(dir) { - ASSERT0(std::abs(dir) == 1); - BoundaryRegionBase::isParallel = true; - } - BoundaryRegionPar(const std::string& name, BndryLoc loc, int dir, Mesh* passmesh) - : BoundaryRegionBase(name, loc, passmesh), dir(dir) { - BoundaryRegionBase::isParallel = true; - ASSERT0(std::abs(dir) == 1); - } - - /// Add a point to the boundary - void add_point(Ind3D ind, BoutReal x, BoutReal y, BoutReal z, BoutReal length, - signed char valid) { - bndry_points.push_back({ind, {x, y, z}, length, valid}); - } - void add_point(int ix, int iy, int iz, BoutReal x, BoutReal y, BoutReal z, - BoutReal length, signed char valid) { - bndry_points.push_back({xyz2ind(ix, iy, iz, localmesh), {x, y, z}, length, valid}); - } - - // final, so they can be inlined - void first() final { bndry_position = begin(bndry_points); } - void next() final { ++bndry_position; } - bool isDone() final { return (bndry_position == end(bndry_points)); } - - // getter - Ind3D ind() const { return bndry_position->index; } - BoutReal s_x() const { return bndry_position->intersection.s_x; } - BoutReal s_y() const { return bndry_position->intersection.s_y; } - BoutReal s_z() const { return bndry_position->intersection.s_z; } - BoutReal length() const { return bndry_position->length; } - signed char valid() const { return bndry_position->valid; } - - // setter - void setValid(signed char val) { bndry_position->valid = val; } - - bool contains(const BoundaryRegionPar& bndry) const { - return std::binary_search( - begin(bndry_points), end(bndry_points), *bndry.bndry_position, - [](const Indices& i1, const Indices& i2) { return i1.index < i2.index; }); - } - - // extrapolate a given point to the boundary - BoutReal extrapolate_o1(const Field3D& f) const { return f[ind()]; } - BoutReal extrapolate_o2(const Field3D& f) const { - ASSERT3(valid() >= 0); - if (valid() < 1) { - return extrapolate_o1(f); - } - return f[ind()] * (1 + length()) - f.ynext(-dir)[ind().yp(-dir)] * length(); - } - - // dirichlet boundary code - void dirichlet_o1(Field3D& f, BoutReal value) const { - f.ynext(dir)[ind().yp(dir)] = value; - } - - void dirichlet_o2(Field3D& f, BoutReal value) const { - if (length() < small_value) { - return dirichlet_o1(f, value); - } - ynext(f) = parallel_stencil::dirichlet_o2(1, f[ind()], 1 - length(), value); - // ynext(f) = f[ind()] * (1 + 1/length()) + value / length(); - } - - void dirichlet_o3(Field3D& f, BoutReal value) const { - ASSERT3(valid() >= 0); - if (valid() < 1) { - return dirichlet_o2(f, value); - } - if (length() < small_value) { - ynext(f) = parallel_stencil::dirichlet_o2(2, yprev(f), 1 - length(), value); - } else { - ynext(f) = - parallel_stencil::dirichlet_o3(2, yprev(f), 1, f[ind()], 1 - length(), value); - } - } - - // NB: value needs to be scaled by dy - // neumann_o1 is actually o2 if we would use an appropriate one-sided stencil. - // But in general we do not, and thus for normal C2 stencils, this is 1st order. - void neumann_o1(Field3D& f, BoutReal value) const { ynext(f) = f[ind()] + value; } - - // NB: value needs to be scaled by dy - void neumann_o2(Field3D& f, BoutReal value) const { - ASSERT3(valid() >= 0); - if (valid() < 1) { - return neumann_o1(f, value); - } - ynext(f) = yprev(f) + 2 * value; - } - - // NB: value needs to be scaled by dy - void neumann_o3(Field3D& f, BoutReal value) const { - ASSERT3(valid() >= 0); - if (valid() < 1) { - return neumann_o1(f, value); - } - ynext(f) = - parallel_stencil::neumann_o3(1 - length(), value, 1, f[ind()], 2, yprev(f)); - } - - const int dir; - -private: - constexpr static BoutReal small_value = 1e-2; - - // BoutReal get(const Field3D& f, int off) - const BoutReal& ynext(const Field3D& f) const { return f.ynext(dir)[ind().yp(dir)]; } - BoutReal& ynext(Field3D& f) const { return f.ynext(dir)[ind().yp(dir)]; } - const BoutReal& yprev(const Field3D& f) const { return f.ynext(-dir)[ind().yp(-dir)]; } - BoutReal& yprev(Field3D& f) const { return f.ynext(-dir)[ind().yp(-dir)]; } - static Ind3D xyz2ind(int x, int y, int z, Mesh* mesh) { - const int ny = mesh->LocalNy; - const int nz = mesh->LocalNz; - return Ind3D{(x * ny + y) * nz + z, ny, nz}; - } -}; - -#endif // BOUT_PAR_BNDRY_H diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index 49dea67743..81653aa255 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -9,6 +9,7 @@ #include "bout/bout_types.hxx" #include "bout/dcomplex.hxx" #include "bout/field3d.hxx" +#include "bout/field_data.hxx" #include "bout/options.hxx" #include "bout/unused.hxx" @@ -119,6 +120,8 @@ public: */ void calcParallelSlices(Field3D& f) override; + using ParallelTransform::toFieldAligned; + /*! * The field is already aligned in Y, so this * does nothing @@ -136,6 +139,8 @@ public: return result.setDirectionY(YDirectionType::Aligned); } + using ParallelTransform::fromFieldAligned; + /*! * The field is already aligned in Y, so this * does nothing @@ -191,6 +196,8 @@ public: */ void calcParallelSlices(Field3D& f) override; + using ParallelTransform::toFieldAligned; + /*! * Uses FFTs and a phase shift to align the grid points * with the y coordinate (along magnetic field usually). @@ -204,6 +211,8 @@ public: FieldPerp toFieldAligned(const FieldPerp& f, const std::string& region = "RGN_ALL") override; + using ParallelTransform::fromFieldAligned; + /*! * Converts a field back to X-Z orthogonal coordinates * from field aligned coordinates. diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index 90dd188d8a..c81ce5947e 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -6,9 +6,9 @@ * up a linear system. * ************************************************************************** - * Copyright 2019 C. MacMackin + * Copyright 2019 - 2025 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -40,18 +40,57 @@ #include #include +#include +#include #include #include +#include #include #include +#include #include #include #include #include #include +#include +#include #include #include +#include + +#include + +namespace bout { +namespace petsc { +struct VecDeleter { + void operator()(Vec* vec_ptr) const { + VecDestroy(vec_ptr); + delete vec_ptr; + } +}; + +/// Unique pointer wrapper around PETSc Vec +/// Assumes that the Vec has been allocated on the heap. +/// +/// e.g. UniqueVec(new Vec{}); +using UniqueVec = std::unique_ptr; + +struct MatDeleter { + void operator()(Mat* mat_ptr) const { + MatDestroy(mat_ptr); + delete mat_ptr; + } +}; + +/// Unique pointer wrapper around PETSc Mat +/// Assumes that the Mat has been allocated on the heap. +/// +/// e.g. UniqueMat(new Mat{}); +using UniqueMat = std::unique_ptr; +} // namespace petsc +} // namespace bout /*! * A class which wraps PETSc vector objects, allowing them to be @@ -61,7 +100,7 @@ template class PetscVector; template -void swap(PetscVector& first, PetscVector& second); +void swap(PetscVector& first, PetscVector& second) noexcept; template inline MPI_Comm getComm([[maybe_unused]] const T& field) { @@ -70,7 +109,7 @@ inline MPI_Comm getComm([[maybe_unused]] const T& field) { template <> inline MPI_Comm getComm([[maybe_unused]] const FieldPerp& field) { - return field.getMesh()->getXcomm(); + return field.getMesh()->getXZcomm(); } template @@ -79,13 +118,6 @@ public: static_assert(bout::utils::is_Field_v, "PetscVector only works with Fields"); using ind_type = typename T::ind_type; - struct VectorDeleter { - void operator()(Vec* vec) const { - VecDestroy(vec); - delete vec; - } - }; - PetscVector() : vector(new Vec{}) {} ~PetscVector() = default; @@ -151,7 +183,7 @@ public: return *this; } - friend void swap(PetscVector& first, PetscVector& second); + friend void swap(PetscVector& first, PetscVector& second) noexcept; BoutReal& operator()(const ind_type& index) { #if CHECKLEVEL >= 1 @@ -230,23 +262,23 @@ public: const Vec* get() const { return vector.get(); } private: - PetscLib lib{}; - std::unique_ptr vector = nullptr; + PetscLib lib; + bout::petsc::UniqueVec vector = nullptr; IndexerPtr indexConverter{}; CELL_LOC location = CELL_LOC::deflt; bool initialised = false; - Array vector_values{}; + Array vector_values; }; /*! - * A class which wraps PETSc vector objects, allowing them to be + * A class which wraps PETSc matrix objects, allowing them to be * indexed using the BOUT++ scheme. It provides the option of setting * a y-offset that interpolates onto field lines. */ template class PetscMatrix; template -void swap(PetscMatrix& first, PetscMatrix& second); +void swap(PetscMatrix& first, PetscMatrix& second) noexcept; template class PetscMatrix { @@ -254,21 +286,14 @@ public: static_assert(bout::utils::is_Field_v, "PetscMatrix only works with Fields"); using ind_type = typename T::ind_type; - struct MatrixDeleter { - void operator()(Mat* mat) const { - MatDestroy(mat); - delete mat; - } - }; - /// Default constructor does nothing PetscMatrix() : matrix(new Mat()) {} ~PetscMatrix() = default; /// Copy constructor PetscMatrix(const PetscMatrix& mat) - : matrix(new Mat()), indexConverter(mat.indexConverter), pt(mat.pt), - yoffset(mat.yoffset), initialised(mat.initialised) { + : matrix(new Mat(), bout::petsc::MatDeleter{}), indexConverter(mat.indexConverter), + pt(mat.pt), yoffset(mat.yoffset), initialised(mat.initialised) { MatDuplicate(*mat.matrix, MAT_COPY_VALUES, matrix.get()); } @@ -280,11 +305,11 @@ public: } // Construct a matrix capable of operating on the specified field, - // preallocating memory if requeted and possible. + // preallocating memory if requested and possible. PetscMatrix(IndexerPtr indConverter, bool preallocate = true) - : matrix(new Mat()), indexConverter(indConverter), + : matrix(new Mat(), bout::petsc::MatDeleter{}), indexConverter(indConverter), pt(&indConverter->getMesh()->getCoordinates()->getParallelTransform()) { - MPI_Comm comm = std::is_same_v ? indConverter->getMesh()->getXcomm() + MPI_Comm comm = std::is_same_v ? indConverter->getMesh()->getXZcomm() : BoutComm::get(); const int size = indexConverter->size(); @@ -318,7 +343,7 @@ public: rhs.initialised = false; return *this; } - friend void swap(PetscMatrix& first, PetscMatrix& second); + friend void swap(PetscMatrix& first, PetscMatrix& second) noexcept; /*! * A class which is used to assign to a particular element of a PETSc @@ -346,7 +371,7 @@ public: ASSERT2(positions.size() == weights.size()); #if CHECK > 2 for (const auto val : weights) { - ASSERT3(finite(val)); + ASSERT3(std::isfinite(val)); } #endif if (positions.empty()) { @@ -363,29 +388,29 @@ public: } } Element& operator=(const Element& other) { - AUTO_TRACE(); + if (this == &other) { return *this; } - ASSERT3(finite(static_cast(other))); + ASSERT3(std::isfinite(static_cast(other))); *this = static_cast(other); return *this; } Element& operator=(BoutReal val) { - AUTO_TRACE(); - ASSERT3(finite(val)); + + ASSERT3(std::isfinite(val)); value = val; setValues(val, INSERT_VALUES); return *this; } Element& operator+=(BoutReal val) { - AUTO_TRACE(); - ASSERT3(finite(val)); - auto columnPosition = std::find(positions.begin(), positions.end(), petscCol); + + ASSERT3(std::isfinite(val)); + auto columnPosition = std::ranges::find(positions, petscCol); if (columnPosition != positions.end()) { const int index = std::distance(positions.begin(), columnPosition); value += weights[index] * val; - ASSERT3(finite(value)); + ASSERT3(std::isfinite(value)); } setValues(val, ADD_VALUES); return *this; @@ -394,7 +419,6 @@ public: private: void setValues(BoutReal val, InsertMode mode) { - TRACE("PetscMatrix setting values at ({}, {})", petscRow, petscCol); ASSERT3(positions.size() > 0); std::vector values; std::transform(weights.begin(), weights.end(), std::back_inserter(values), @@ -405,7 +429,8 @@ public: status = MatSetValues(*petscMatrix, 1, &petscRow, positions.size(), positions.data(), values.data(), mode); if (status != 0) { - throw BoutException("Error when setting elements of a PETSc matrix."); + throw BoutException("Error when setting elements of a PETSc matrix at ({}, {})", + petscRow, petscCol); } } Mat* petscMatrix; @@ -531,7 +556,7 @@ private: * vice versa. */ template -void swap(PetscVector& first, PetscVector& second) { +void swap(PetscVector& first, PetscVector& second) noexcept { std::swap(first.vector, second.vector); std::swap(first.indexConverter, second.indexConverter); std::swap(first.location, second.location); @@ -543,7 +568,7 @@ void swap(PetscVector& first, PetscVector& second) { * vice versa. */ template -void swap(PetscMatrix& first, PetscMatrix& second) { +void swap(PetscMatrix& first, PetscMatrix& second) noexcept { std::swap(first.matrix, second.matrix); std::swap(first.indexConverter, second.indexConverter); std::swap(first.pt, second.pt); @@ -573,7 +598,7 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { namespace bout { template constexpr auto cast_MatFDColoringFn(T func) { - return func; + return reinterpret_cast(func); // NOLINT(*-reinterpret-cast) } } // namespace bout #else diff --git a/include/bout/petsc_operators.hxx b/include/bout/petsc_operators.hxx new file mode 100644 index 0000000000..5a7df5b088 --- /dev/null +++ b/include/bout/petsc_operators.hxx @@ -0,0 +1,1082 @@ +#pragma once + +#ifndef BOUT_PETSC_OPERATORS +#define BOUT_PETSC_OPERATORS + +#include "bout/build_defines.hxx" + +#if BOUT_HAS_PETSC + +#include "bout/array.hxx" +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/field3d.hxx" +#include "bout/mesh.hxx" +#include "bout/output_bout_types.hxx" +#include "bout/petsc_interface.hxx" +#include "bout/petsclib.hxx" +#include "bout/region.hxx" +#include "bout/utils.hxx" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/// @brief Tag type identifying the cell space C. +/// +/// Used as a compile-time template parameter to distinguish vectors and operators +/// that live in the cell space from those in the forward or backward leg spaces. +/// Mismatched space tags produce a compile error rather than a runtime failure. +struct CellSpaceTag {}; + +/// @brief Tag type identifying the forward leg space L+. +/// +/// Operators and vectors tagged with this type map to or from the forward (y+1) +/// leg space. See @ref BackwardLegSpaceTag and @ref CellSpaceTag. +struct ForwardLegSpaceTag {}; + +/// @brief Tag type identifying the backward leg space L-. +/// +/// Operators and vectors tagged with this type map to or from the backward (y-1) +/// leg space. See @ref ForwardLegSpaceTag and @ref CellSpaceTag. +struct BackwardLegSpaceTag {}; + +template +class PetscOperator; + +/// Used to indicate whether forward or backward boundary 'legs' should be used +enum class BoundaryDirection { Forward, Backward, Both }; + +class PetscCellMapping; + +/// @brief Shared-pointer alias for a const PetscCellMapping. +using PetscCellMappingPtr = std::shared_ptr; + +/// @brief Bidirectional index mapping between mesh-file stored numbering and PETSc +/// row ownership. +/// +/// Every vector space (cell space, forward leg space, backward leg space) is defined +/// by a global stored numbering written to the mesh file by the Python weights module. +/// PETSc distributes rows contiguously across MPI ranks, so the local PETSc row range +/// [rowStart(), rowEnd()) does not in general coincide with the stored indices. +/// +/// This class maintains: +/// - the list of stored indices owned by the local rank, in PETSc row order; +/// - a hash map for O(1) stored → PETSc lookup; +/// - a permutation matrix @c mat_stored_to_petsc (PETSc ordering → stored numbering) +/// and its transpose @c mat_petsc_to_stored (stored numbering → PETSc ordering), +/// used to translate operator column indices during matrix assembly. +/// +/// Subclasses specialise the constructor to populate these structures for a particular +/// space from mesh metadata. +class PetscIndexMapping { +public: + PetscIndexMapping() = default; + virtual ~PetscIndexMapping(); + + PetscIndexMapping(const PetscIndexMapping&) = delete; + PetscIndexMapping& operator=(const PetscIndexMapping&) = delete; + PetscIndexMapping(PetscIndexMapping&&) = delete; + PetscIndexMapping& operator=(PetscIndexMapping&&) = delete; + + /// @brief Number of rows owned locally by this MPI rank. + PetscInt localSize() const { + return static_cast(local_stored_indices.size()); + } + + /// @brief Total number of rows in this space across all MPI ranks. + PetscInt globalSize() const { return global_size; } + + /// @brief Global PETSc index of the first row owned by this MPI rank. + PetscInt rowStart() const { return row_start; } + + /// @brief Global PETSc index one past the last row owned by this MPI rank. + /// + /// The locally owned rows are the half-open interval [rowStart(), rowEnd()). + PetscInt rowEnd() const { return row_end; } + + /// @brief Stored mesh-file indices owned locally, listed in PETSc row order. + /// + /// Entry @c i corresponds to global PETSc row rowStart() + i. + const std::vector& localStoredIndices() const { return local_stored_indices; } + + /// @brief Convert a locally owned stored index to its global PETSc row index. + /// + /// @param stored_index A mesh-file stored index that must be owned by this rank. + /// @returns The corresponding global PETSc row index. + /// @throws BoutException if @p stored_index is not owned locally. + PetscInt storedToPetsc(int stored_index) const; + + /// @brief Return the permutation matrix that maps PETSc row ordering to stored + /// mesh-file numbering. + /// + /// This is the transpose of @c mat_stored_to_petsc and is used in + /// @ref PetscOperator::assembleFromCSR to translate stored column indices into + /// PETSc column indices via a post-multiplication. + Mat getPetscToStored() const { return mat_petsc_to_stored; } + +protected: + /// @brief BOUT++ PETSc library handle; ensures PETSc is initialised. + PetscLib lib; + + /// @brief Construct the permutation matrices and populate internal lookup structures. + /// + /// Assigns contiguous PETSc rows starting from the rank-local offset determined by + /// PETSc's ownership partitioning. Each stored index in @p stored_indices maps to + /// one PETSc row, in the order given. + /// + /// @param nlocal Number of rows owned by this rank. + /// @param nglobal Total number of rows across all ranks. + /// @param stored_indices Mesh-file stored indices for the locally owned rows, in + /// the order they should appear in the PETSc vector. + void buildPermutation(PetscInt nlocal, PetscInt nglobal, + const std::vector& stored_indices); + + PetscInt global_size{0}; ///< Total global row count. + PetscInt row_start{0}; ///< First global PETSc row owned locally. + PetscInt row_end{0}; ///< One-past-last global PETSc row owned locally. + std::vector local_stored_indices; ///< Stored indices in local PETSc row order. + std::unordered_map local_stored_to_petsc; ///< Stored → PETSc lookup. + Mat mat_stored_to_petsc{nullptr}; ///< Permutation: stored numbering → PETSc ordering. + Mat mat_petsc_to_stored{nullptr}; ///< Permutation: PETSc ordering → stored numbering. +}; + +/// @brief Cell-space index mapping that bridges stored cell numbers, PETSc row +/// ownership, and BOUT++ Field3D index arithmetic. +/// +/// The cell space C contains five disjoint subsets of cells, appended in order: +/// 1. Evolving interior cells (the primary unknowns). +/// 2. Inner radial X-boundary cells. +/// 3. Outer radial X-boundary cells. +/// 4. Forward parallel boundary cells (one virtual cell per interior source cell +/// whose forward map intersects the radial boundary). +/// 5. Backward parallel boundary cells (analogous for the backward map). +/// +/// The local PETSc vector stores these in the same order. The @c mapLocal* methods +/// iterate over subsets 1–3 (interior + X-boundary) while @c mapLocalYup and +/// @c mapLocalYdown cover subsets 4 and 5 respectively. +/// +/// @c mapOwnedInteriorCells iterates only the evolving interior cells (subset 1) and +/// provides global PETSc row indices, making it suitable for assembling matrices. +class PetscCellMapping : public PetscIndexMapping { +public: + /// @brief Construct the cell-space mapping from mesh metadata fields. + /// + /// Populates all five cell subsets and calls @ref buildPermutation with the + /// concatenated list of stored indices. + /// + /// @param cell_number Field3D of stored cell numbers for interior and + /// X-boundary cells. Negative entries are skipped. + /// @param forward_cell_number Field3D of stored cell numbers for forward parallel + /// boundary virtual cells. Negative entries are skipped. + /// @param backward_cell_number Field3D of stored cell numbers for backward parallel + /// boundary virtual cells. Negative entries are skipped. + /// @param total_cells Total number of cells in the global cell space, + /// as computed by the Python weights module. + PetscCellMapping(const Field3D& cell_number, const Field3D& forward_cell_number, + const Field3D& backward_cell_number, int total_cells); + + /// @brief Build the region of evolving interior cells from a cell-number field. + /// + /// Iterates RGN_NOBNDRY and retains indices where @p cell_number is non-negative. + /// + /// @param cell_number Field3D of stored cell numbers. + /// @returns Region containing the Ind3D indices of all valid interior cells. + static Region create_region(const Field3D& cell_number); + + /// @brief Build the region of inner radial X-boundary cells. + /// + /// Iterates RGN_INNER_X and retains indices where @p cell_number is non-negative. + /// + /// @param cell_number Field3D of stored cell numbers. + /// @returns Region containing the Ind3D indices of valid inner-X boundary cells. + static Region create_region_xin(const Field3D& cell_number); + + /// @brief Build the region of outer radial X-boundary cells. + /// + /// Iterates RGN_OUTER_X and retains indices where @p cell_number is non-negative. + /// + /// @param cell_number Field3D of stored cell numbers. + /// @returns Region containing the Ind3D indices of valid outer-X boundary cells. + static Region create_region_xout(const Field3D& cell_number); + + /// @brief Iterate over locally owned evolving interior cells, providing global + /// PETSc row indices. + /// + /// Calls @p func(petsc_row, field_index, stored_cell_number) for each cell in + /// the evolving region that is owned by this MPI rank. @p petsc_row is the global + /// PETSc index and is suitable for use as a row or column argument to MatSetValues. + /// + /// @tparam Function Callable with signature + /// (PetscInt row, Ind3D i, int stored) -> void. + /// @param func Callback invoked for each owned interior cell. + template + void mapOwnedInteriorCells(Function func) const { + PetscInt row = rowStart(); + BOUT_FOR_SERIAL(i, evolving_region) { + func(row, i, ROUND(cell_number[i])); + ++row; + } + } + + /// @brief Iterate over all locally stored field cells (interior + X-boundary), + /// providing local PETSc vector indices. + /// + /// Covers the evolving interior region, inner-X boundary, and outer-X boundary + /// in that order. The local index starts at zero on each rank and increases + /// contiguously. Use this to read from or write to a local PETSc Vec array + /// obtained via VecGetArray. + /// + /// @tparam Function Callable with signature + /// (PetscInt local_row, Ind3D i) -> void. + /// @param func Callback invoked for each locally stored field cell. + template + void mapLocalField(Function func) const { + PetscInt row = 0; + const std::vector>> regions = { + evolving_region, xin_region, xout_region}; + for (const auto& region : regions) { + BOUT_FOR_SERIAL(i, region.get()) { + func(row, i); + ++row; + } + } + } + + /// @brief Iterate over locally stored forward parallel boundary cells, providing + /// local PETSc vector indices. + /// + /// The local index starts immediately after the field cells covered by + /// @ref mapLocalField. The Field3D index passed to @p func is the y+1 neighbour + /// of the source cell (i.yp()), matching how field.yup() is indexed. + /// + /// @tparam Function Callable with signature + /// (PetscInt local_row, Ind3D i_yp) -> void. + /// @param func Callback invoked for each locally stored forward boundary cell. + template + void mapLocalYup(Function func) const { + PetscInt row = evolving_region.size() + xin_region.size() + xout_region.size(); + BOUT_FOR_SERIAL(i, yup_region) { + func(row, i.yp()); + ++row; + } + } + + /// @brief Iterate over locally stored backward parallel boundary cells, providing + /// local PETSc vector indices. + /// + /// The local index starts immediately after the forward boundary cells covered by + /// @ref mapLocalYup. The Field3D index passed to @p func is the y-1 neighbour + /// of the source cell (i.ym()), matching how field.ydown() is indexed. + /// + /// @tparam Function Callable with signature + /// (PetscInt local_row, Ind3D i_ym) -> void. + /// @param func Callback invoked for each locally stored backward boundary cell. + template + void mapLocalYdown(Function func) const { + PetscInt row = evolving_region.size() + xin_region.size() + xout_region.size() + + yup_region.size(); + BOUT_FOR_SERIAL(i, ydown_region) { + func(row, i.ym()); + ++row; + } + } + + friend PetscOperator + makeNeumannOperator(const PetscCellMappingPtr& mapping, BoundaryDirection direction); + +private: + Field3D cell_number; ///< Stored cell numbers for interior/X-boundary cells. + Field3D + forward_cell_number; ///< Stored cell numbers for forward boundary virtual cells. + Field3D + backward_cell_number; ///< Stored cell numbers for backward boundary virtual cells. + Region evolving_region; ///< Interior evolving cells. + Region xin_region; ///< Inner radial X-boundary cells. + Region xout_region; ///< Outer radial X-boundary cells. + Region yup_region; ///< Forward parallel boundary virtual cells. + Region ydown_region; ///< Backward parallel boundary virtual cells. +}; + +/// @brief Index mapping for forward (L+) or backward (L-) leg spaces. +/// +/// Each interior source cell contributes one or two leg rows depending on whether +/// its mapped sub-samples are entirely interior, entirely boundary, or mixed. +/// The leg indices are assigned by the Python weights module and stored in the mesh +/// file as Field3D arrays (e.g. forward_leg_interior_number). +/// +/// On construction, duplicate indices are removed and the remaining indices are +/// sorted before being passed to @ref buildPermutation. +class PetscLegMapping : public PetscIndexMapping { +public: + /// @brief Construct a leg-space mapping. + /// + /// @param total_legs Global number of leg rows in this space. + /// @param local_leg_indices Stored leg indices owned by this MPI rank. Duplicates + /// are removed internally before building the permutation. + PetscLegMapping(int total_legs, std::vector local_leg_indices); +}; + +/// @brief Shared-pointer alias for a const PetscLegMapping. +using PetscLegMappingPtr = std::shared_ptr; + +/// @brief Type-safe wrapper around a PETSc Vec belonging to a particular vector space. +/// +/// The compile-time @p SpaceTag (one of @ref CellSpaceTag, @ref ForwardLegSpaceTag, +/// @ref BackwardLegSpaceTag) prevents accidental arithmetic between vectors from +/// incompatible spaces. All binary operations assert that both operands share the +/// same mapping pointer, catching dimension mismatches at runtime. +/// +/// Vectors are non-copyable but movable, matching the ownership semantics of the +/// underlying PETSc Vec. +/// +/// @tparam SpaceTag One of CellSpaceTag, ForwardLegSpaceTag, BackwardLegSpaceTag. +template +class PetscSpaceVector { + using UniqueVec = bout::petsc::UniqueVec; + +public: + /// @brief Default constructor; produces an empty (unusable) vector. + PetscSpaceVector() = default; + + /// @brief Construct a zero-initialised vector for the given space. + /// + /// Allocates a PETSc MPI vector sized according to @p mapping->localSize() and + /// @p mapping->globalSize(). + /// + /// @param mapping Shared ownership of the space mapping. + explicit PetscSpaceVector(std::shared_ptr mapping) + : mapping(std::move(mapping)), + vec(createVec(this->mapping->localSize(), this->mapping->globalSize())) {} + + /// @brief Construct from an existing mapping and a pre-built PETSc Vec. + /// + /// Takes ownership of @p vec. + /// + /// @param mapping Shared ownership of the space mapping. + /// @param vec An already-assembled PETSc Vec. Ownership is transferred. + PetscSpaceVector(std::shared_ptr mapping, UniqueVec vec) + : mapping(std::move(mapping)), vec(std::move(vec)) {} + + PetscSpaceVector(const PetscSpaceVector&) = delete; + PetscSpaceVector& operator=(const PetscSpaceVector&) = delete; + PetscSpaceVector(PetscSpaceVector&&) noexcept = default; + PetscSpaceVector& operator=(PetscSpaceVector&&) noexcept = default; + + /// @brief Return the underlying PETSc Vec handle (non-owning). + Vec raw() const { return *this->vec; } + + /// @brief Return the shared space mapping. + const std::shared_ptr& getMapping() const { return mapping; } + + /// @brief Return a deep copy of this vector. + /// + /// Allocates a new PETSc Vec with the same size and mapping, then copies values. + PetscSpaceVector copy() const { + UniqueVec out{new Vec{nullptr}}; + BOUT_DO_PETSC(VecDuplicate(*this->vec, out.get())); + BOUT_DO_PETSC(VecCopy(*this->vec, *out.get())); + return PetscSpaceVector(this->mapping, std::move(out)); + } + + /// @brief Return a new vector equal to @c (*this) * @p scalar. + /// + /// @param scalar Scalar multiplier. + PetscSpaceVector operator*(BoutReal scalar) const& { + auto out = this->copy(); + BOUT_DO_PETSC(VecScale(out.raw(), scalar)); + return out; + } + + /// Multiply by a scalar, modifying a temporary in-place + PetscSpaceVector operator*(BoutReal scalar) && { + BOUT_DO_PETSC(VecScale(this->raw(), scalar)); + return std::move(*this); + } + + /// @brief Return a new vector equal to @c (*this) + @p rhs. + /// + /// @param rhs Must share the same mapping as @c *this. + PetscSpaceVector operator+(const PetscSpaceVector& rhs) const& { + ASSERT0(mapping == rhs.mapping); + auto out = this->copy(); + BOUT_DO_PETSC(VecAXPY(out.raw(), 1.0, rhs.raw())); + return out; + } + + PetscSpaceVector operator+(const PetscSpaceVector& rhs) && { + ASSERT0(mapping == rhs.mapping); + BOUT_DO_PETSC(VecAXPY(this->raw(), 1.0, rhs.raw())); + return std::move(*this); + } + + /// @brief Return a new vector equal to @c (*this) - @p rhs. + /// + /// @param rhs Must share the same mapping as @c *this. + PetscSpaceVector operator-(const PetscSpaceVector& rhs) const& { + ASSERT0(mapping == rhs.mapping); + auto out = this->copy(); + BOUT_DO_PETSC(VecAXPY(out.raw(), -1.0, rhs.raw())); + return out; + } + + PetscSpaceVector operator-(const PetscSpaceVector& rhs) && { + ASSERT0(mapping == rhs.mapping); + BOUT_DO_PETSC(VecAXPY(this->raw(), -1.0, rhs.raw())); + return std::move(*this); + } + + /// @brief Return a new vector whose entries are the element-wise product + /// @c lhs[i] * rhs[i]. + /// + /// @param lhs Left operand; must share a mapping with @p rhs. + /// @param rhs Right operand. + static PetscSpaceVector pointwiseMultiply(const PetscSpaceVector& lhs, + const PetscSpaceVector& rhs) { + ASSERT0(lhs.mapping == rhs.mapping); + auto out = lhs.copy(); + BOUT_DO_PETSC(VecPointwiseMult(out.raw(), lhs.raw(), rhs.raw())); + return out; + } + + /// @brief Return a new vector whose entries are @c 1 / in[i]. + /// + /// @param in Input vector. No entry may be zero. + static PetscSpaceVector reciprocal(const PetscSpaceVector& in) { + auto out = in.copy(); + BOUT_DO_PETSC(VecReciprocal(out.raw())); + return out; + } + +private: + /// @brief Allocate a new zeroed PETSc MPI vector of the given size. + /// + /// @param local_size Number of locally owned entries. + /// @param global_size Total number of entries across all ranks. + static UniqueVec createVec(PetscInt local_size, PetscInt global_size) { + UniqueVec out{new Vec{nullptr}}; + BOUT_DO_PETSC(VecCreate(BoutComm::get(), out.get())); + BOUT_DO_PETSC(VecSetType(*out, VECMPI)); + BOUT_DO_PETSC(VecSetSizes(*out, local_size, global_size)); + return out; + } + + std::shared_ptr mapping; ///< Space mapping (shared ownership). + UniqueVec vec; ///< Underlying PETSc Vec (owned). +}; + +// Tagged vector aliases — these provide compile-time checks of compatible operations. +/// @brief PETSc vector in the cell space C. +using PetscCellVector = PetscSpaceVector; +/// @brief PETSc vector in the forward leg space L+. +using PetscForwardLegVector = PetscSpaceVector; +/// @brief PETSc vector in the backward leg space L-. +using PetscBackwardLegVector = PetscSpaceVector; + +/// @brief Populate a PetscCellVector from a Field3D and its parallel slices. +/// +/// The cell vector is filled in the order defined by @ref PetscCellMapping: +/// evolving interior cells (from @p field), inner/outer X-boundary cells +/// (from @p field), forward boundary virtual cells (from @p field.yup()), and +/// backward boundary virtual cells (from @p field.ydown()). +/// +/// @param mapping Shared cell-space mapping. +/// @param field Source field; must have parallel slices split and allocated. +/// @returns A fully assembled PetscCellVector. +PetscCellVector makePetscCellVector(const PetscCellMappingPtr& mapping, + const Field3D& field); + +/// @brief Extract a Field3D (with parallel slices) from a PetscCellVector. +/// +/// Reverses @ref makePetscCellVector: interior and X-boundary values are written to +/// @c result, forward boundary values to @c result.yup(), and backward boundary +/// values to @c result.ydown(). +/// +/// @param vec Source vector; must use a PetscCellMapping. +/// @param prototype Field3D whose mesh, coordinates, and metadata are copied to +/// initialise the result. +/// @returns A newly allocated Field3D with split parallel slices. +Field3D toField3D(const PetscCellVector& vec, const Field3D& prototype); + +/// @brief Type-safe sparse linear operator mapping from one space to another. +/// +/// Wraps a PETSc Mat and enforces compatible space pairings at compile time via +/// the @p OutSpaceTag and @p InSpaceTag template parameters. The underlying matrix +/// stores values in PETSc's internal ordering; translation from mesh-file stored +/// column indices to PETSc column indices is performed during construction via a +/// post-multiplication by @ref PetscIndexMapping::getPetscToStored. +/// +/// Operators are non-copyable but movable. Binary operations (addition, subtraction, +/// scalar multiplication, composition) return new operators without modifying +/// their operands, unless the rvalue-qualified @c operator*(BoutReal) overload is +/// selected, which scales in place. +/// +/// @tparam OutSpaceTag Tag for the output (row) space. +/// @tparam InSpaceTag Tag for the input (column) space. +template +class PetscOperator { + using UniqueMat = bout::petsc::UniqueMat; + +public: + /// @brief Default constructor; produces an empty (unusable) operator. + PetscOperator() = default; + ~PetscOperator() = default; + + /// @brief Construct an operator from a CSR-format sparse matrix stored in the mesh. + /// + /// Assembles the PETSc matrix from stored (non-PETSc) row and column indices by + /// calling @ref assembleFromCSR. + /// + /// @param out_mapping Shared mapping for the output (row) space. + /// @param in_mapping Shared mapping for the input (column) space. + /// @param rows CSR row-pointer array (size = number_of_rows + 1). + /// @param cols CSR column-index array, using stored (mesh-file) indices. + /// @param weights CSR nonzero-value array. + PetscOperator(std::shared_ptr out_mapping, + std::shared_ptr in_mapping, Array rows, + Array cols, Array weights) + : out_mapping(std::move(out_mapping)), in_mapping(std::move(in_mapping)) { + assembleFromCSR(rows, cols, weights); + } + + /// @brief Construct an operator from an already-assembled PETSc Mat. + /// + /// Takes ownership of @p mat. + /// + /// @param out_mapping Shared mapping for the output (row) space. + /// @param in_mapping Shared mapping for the input (column) space. + /// @param mat Pre-assembled PETSc Mat. Ownership is transferred. + PetscOperator(std::shared_ptr out_mapping, + std::shared_ptr in_mapping, UniqueMat mat) + : out_mapping(std::move(out_mapping)), in_mapping(std::move(in_mapping)), + mat_operator(std::move(mat)) {} + + // Operators are non-copyable (PETSc matrices are expensive to copy) but movable. + PetscOperator(const PetscOperator&) = delete; + PetscOperator& operator=(const PetscOperator&) = delete; + PetscOperator(PetscOperator&&) noexcept = default; + PetscOperator& operator=(PetscOperator&&) noexcept = default; + + /// @brief Apply the operator to a typed vector: @c result = A * rhs. + /// + /// @param rhs Input vector; must share the same mapping as this operator's + /// input space. + /// @returns A new output-space vector holding the result. + PetscSpaceVector + operator()(const PetscSpaceVector& rhs) const { + ASSERT0(in_mapping == rhs.getMapping()); + PetscSpaceVector result(out_mapping); + BOUT_DO_PETSC(MatMult(*this->mat_operator, rhs.raw(), result.raw())); + return result; + } + + /// @brief Apply the operator to a Field3D: converts to a cell vector then applies. + /// + /// Only available when @p InSpaceTag is @ref CellSpaceTag and @p OutSpaceTag is + /// not @ref CellSpaceTag. The Field3D is packed into a PetscCellVector via + /// @ref makePetscCellVector before applying the matrix. + /// + /// @param rhs Source field; must have parallel slices split and allocated. + /// @returns A new output-space vector holding the result. + template + && !std::is_same_v>> + PetscSpaceVector operator()(const Field3D& rhs) const { + auto in = makePetscCellVector( + std::static_pointer_cast(in_mapping), rhs); + return (*this)(in); + } + + /// Apply operator to a Field3D, returning a Field3D. + /// Enable if both input and output mapppings are in Cell Space + template + && std::is_same_v>> + Field3D operator()(const Field3D& rhs) const { + auto in = makePetscCellVector( + std::static_pointer_cast(in_mapping), rhs); + return toField3D((*this)(in), rhs); + } + + /// @brief Return the transpose operator mapping from OutSpaceTag to InSpaceTag. + /// + /// Allocates a new PETSc Mat via MatTranspose (MAT_INITIAL_MATRIX). The mappings + /// are swapped: the transposed operator's input mapping is this operator's output + /// mapping, and vice versa. + PetscOperator transpose() const { + UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC(MatTranspose(*mat_operator, MAT_INITIAL_MATRIX, out.get())); + return PetscOperator(in_mapping, out_mapping, + std::move(out)); + } + + /// @brief Return a new operator equal to @c (*this) + @p rhs. + /// + /// Both operands must share the same input and output mappings. Uses + /// UNKNOWN_NONZERO_PATTERN, so the sparsity structure of the result may differ + /// from either operand. + /// + /// @param rhs Operator to add; must have the same in/out mappings. + PetscOperator operator+(const PetscOperator& rhs) const { + ASSERT0(out_mapping == rhs.out_mapping); + ASSERT0(in_mapping == rhs.in_mapping); + UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC(MatDuplicate(*this->mat_operator, MAT_COPY_VALUES, out.get())); + BOUT_DO_PETSC(MatAXPY(*out, 1.0, *rhs.mat_operator, UNKNOWN_NONZERO_PATTERN)); + return PetscOperator(out_mapping, in_mapping, std::move(out)); + } + + /// @brief Return a new operator equal to @c (*this) - @p rhs. + /// + /// Both operands must share the same input and output mappings. Uses + /// UNKNOWN_NONZERO_PATTERN; see @ref operator+. + /// + /// @param rhs Operator to subtract; must have the same in/out mappings. + PetscOperator operator-(const PetscOperator& rhs) const { + ASSERT0(out_mapping == rhs.out_mapping); + ASSERT0(in_mapping == rhs.in_mapping); + UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC(MatDuplicate(*this->mat_operator, MAT_COPY_VALUES, out.get())); + BOUT_DO_PETSC(MatAXPY(*out, -1.0, *rhs.mat_operator, UNKNOWN_NONZERO_PATTERN)); + return PetscOperator(out_mapping, in_mapping, std::move(out)); + } + + /// @brief Return a new operator equal to @c (*this) * @p scalar (lvalue overload). + /// + /// Duplicates the matrix before scaling, leaving @c *this unchanged. + /// + /// @param scalar Scalar multiplier. + PetscOperator operator*(BoutReal scalar) const& { + UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC(MatDuplicate(*this->mat_operator, MAT_COPY_VALUES, out.get())); + BOUT_DO_PETSC(MatScale(*out, scalar)); + return PetscOperator(out_mapping, in_mapping, std::move(out)); + } + + /// @brief Scale this operator in place and return it (rvalue overload). + /// + /// More efficient than the lvalue overload when @c *this is a temporary, + /// as no matrix duplication is needed. + /// + /// @param scalar Scalar multiplier. + PetscOperator operator*(BoutReal scalar) && { + BOUT_DO_PETSC(MatScale(*this->mat_operator, scalar)); + return std::move(*this); + } + + /// @brief Return the underlying PETSc Mat handle (non-owning). + /// + /// Intended for use by the free @c operator* (matrix composition) and other + /// low-level callers that need direct PETSc access. + Mat raw() const { return *this->mat_operator; } + + /// @brief Construct a diagonal operator from a vector of diagonal entries. + /// + /// Only available when @p OutSpaceTag == @p InSpaceTag (square, same-space + /// operator). Builds an MPIAIJ matrix with one nonzero per row via + /// MatDiagonalSet. + /// + /// @param mapping Shared mapping for both the row and column space. + /// @param diag Vector of diagonal values; must share @p mapping. + /// @returns A new diagonal operator. + static PetscOperator diagonal(std::shared_ptr mapping, + const PetscSpaceVector& diag) { + static_assert(std::is_same_v, + "Diagonal operators require the same input and output space"); + UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC(MatCreate(BoutComm::get(), out.get())); + BOUT_DO_PETSC(MatSetType(*out, MATMPIAIJ)); + BOUT_DO_PETSC(MatSetSizes(*out, mapping->localSize(), mapping->localSize(), + mapping->globalSize(), mapping->globalSize())); + // Note: Off-diagonal blocks are empty because this is a square matrix + BOUT_DO_PETSC(MatMPIAIJSetPreallocation(*out, 1, nullptr, 0, nullptr)); + BOUT_DO_PETSC(MatDiagonalSet(*out, diag.raw(), INSERT_VALUES)); + BOUT_DO_PETSC(MatAssemblyBegin(*out, MAT_FINAL_ASSEMBLY)); + BOUT_DO_PETSC(MatAssemblyEnd(*out, MAT_FINAL_ASSEMBLY)); + return PetscOperator(mapping, mapping, std::move(out)); + } + +private: + /// @brief Assemble the operator matrix from a mesh-file CSR representation. + /// + /// Iterates over the locally owned output rows (identified via + /// @c out_mapping->localStoredIndices()), looks up each row's nonzeros in the + /// CSR arrays, and inserts them using global PETSc row indices. Column indices + /// are given in stored (mesh-file) numbering; the final matrix is obtained by + /// post-multiplying the assembled temporary by + /// @c in_mapping->getPetscToStored() to convert to PETSc column ordering. + /// + /// @param rows CSR row-pointer array (size = total_stored_rows + 1). + /// @param cols CSR column-index array in stored (mesh-file) numbering. + /// @param weights CSR nonzero-value array. + void assembleFromCSR(const Array& rows, const Array& cols, + const Array& weights) { + const UniqueMat temp{new Mat{nullptr}}; + BOUT_DO_PETSC(MatCreate(BoutComm::get(), temp.get())); + BOUT_DO_PETSC(MatSetType(*temp, MATMPIAIJ)); + BOUT_DO_PETSC(MatSetSizes(*temp, out_mapping->localSize(), PETSC_DECIDE, + out_mapping->globalSize(), in_mapping->globalSize())); + + PetscInt col_start{0}; + PetscInt col_end{0}; + BOUT_DO_PETSC(MatGetOwnershipRangeColumn(*temp, &col_start, &col_end)); + + const auto& local_rows = out_mapping->localStoredIndices(); + std::vector d_nnz(local_rows.size(), 0); + std::vector o_nnz(local_rows.size(), 0); + for (PetscInt local_row = 0; local_row < static_cast(local_rows.size()); + ++local_row) { + const int stored_row = local_rows[local_row]; + if (stored_row < 0 || stored_row + 1 >= static_cast(rows.size())) { + continue; + } + const int start = rows[stored_row]; + const int end = rows[stored_row + 1]; + for (int index = start; index < end; ++index) { + const PetscInt stored_col = cols[index]; + if (col_start <= stored_col && stored_col < col_end) { + ++d_nnz[local_row]; + } else { + ++o_nnz[local_row]; + } + } + } + BOUT_DO_PETSC(MatMPIAIJSetPreallocation(*temp, 0, + d_nnz.empty() ? nullptr : d_nnz.data(), 0, + o_nnz.empty() ? nullptr : o_nnz.data())); + + for (PetscInt local_row = 0; local_row < static_cast(local_rows.size()); + ++local_row) { + const int stored_row = local_rows[local_row]; + if (stored_row < 0 || stored_row + 1 >= static_cast(rows.size())) { + continue; + } + const int start = rows[stored_row]; + const int end = rows[stored_row + 1]; + if (end <= start) { + continue; + } + const PetscInt petsc_row = out_mapping->rowStart() + local_row; + BOUT_DO_PETSC(MatSetValues(*temp, 1, &petsc_row, end - start, &cols[start], + &weights[start], INSERT_VALUES)); + } + BOUT_DO_PETSC(MatAssemblyBegin(*temp, MAT_FINAL_ASSEMBLY)); + BOUT_DO_PETSC(MatAssemblyEnd(*temp, MAT_FINAL_ASSEMBLY)); + + // Post-multiply by the stored→PETSc permutation to convert column numbering. + UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC(MatMatMult(*temp, in_mapping->getPetscToStored(), MAT_INITIAL_MATRIX, + PETSC_DETERMINE, out.get())); + mat_operator = std::move(out); + } + + std::shared_ptr out_mapping; ///< Row-space mapping. + std::shared_ptr in_mapping; ///< Column-space mapping. + UniqueMat mat_operator{new Mat{nullptr}}; ///< Underlying PETSc Mat. + + template + friend PetscOperator operator*(const PetscOperator& lhs, + const PetscOperator& rhs); +}; + +/// @brief Compose two compatible operators: @c result = lhs * rhs. +/// +/// The output space of @p rhs must match the input space of @p lhs, enforced at +/// compile time by the @p MidSpaceTag parameter. The resulting operator maps from +/// @p rhs's input space to @p lhs's output space. +/// +/// @tparam OutSpaceTag Output space of @p lhs and of the result. +/// @tparam MidSpaceTag Input space of @p lhs and output space of @p rhs. +/// @tparam InSpaceTag Input space of @p rhs and of the result. +/// @param lhs Left (outer) operator. +/// @param rhs Right (inner) operator. +/// @returns A new operator representing the composition. +template +PetscOperator +operator*(const PetscOperator& lhs, + const PetscOperator& rhs) { + ASSERT0(lhs.in_mapping == rhs.out_mapping); + typename PetscOperator::UniqueMat out{new Mat{nullptr}}; + BOUT_DO_PETSC( + MatMatMult(lhs.raw(), rhs.raw(), MAT_INITIAL_MATRIX, PETSC_DETERMINE, out.get())); + return PetscOperator(lhs.out_mapping, rhs.in_mapping, + std::move(out)); +} + +/// @brief Operator mapping from cell space C to forward leg space L+. +using PetscForwardOperator = PetscOperator; +/// @brief Operator mapping from cell space C to backward leg space L-. +using PetscBackwardOperator = PetscOperator; +/// @brief Operator mapping from forward leg space L+ to cell space C. +using PetscForwardToCellOperator = PetscOperator; +/// @brief Operator mapping from backward leg space L- to cell space C. +using PetscBackwardToCellOperator = PetscOperator; +/// @brief Operator mapping within the cell space C. +using PetscCellOperator = PetscOperator; +/// @brief Operator mapping within the forward leg space L+. +using PetscForwardLegOperator = PetscOperator; +/// @brief Operator mapping within the backward leg space L-. +using PetscBackwardLegOperator = PetscOperator; + +/// @brief Factory that constructs cell-space and leg-space operators from mesh metadata. +/// +/// On construction, reads all required fields and integer scalars from the mesh and +/// sets up the @ref PetscCellMapping, forward @ref PetscLegMapping, and backward +/// @ref PetscLegMapping. Individual primitive operators (interpolation, injection, +/// leg weights) are constructed on demand. The high-level set of parallel operators +/// needed for Support-Operator-Method diffusion is assembled by @ref getParallel. +class PetscOperators { +public: + /// @brief Construct the operator factory from a BOUT++ mesh. + /// + /// Reads the following fields from @p mesh: + /// - @c cell_number, @c forward_cell_number, @c backward_cell_number (Field3D) + /// - @c total_cells, @c n_forward_legs, @c n_backward_legs (int) + /// - @c forward_leg_interior_number, @c forward_leg_boundary_number (Field3D) + /// - @c backward_leg_interior_number, @c backward_leg_boundary_number (Field3D) + /// + /// @param mesh Non-owning pointer to the BOUT++ mesh. Must outlive this object. + /// @throws BoutException if any required field or scalar is missing from the mesh. + explicit PetscOperators(Mesh* mesh); + + /// @brief Build the forward interpolation operator F: L+ ← C. + /// + /// Maps cell-space values to forward leg space using the CSR arrays stored in the + /// mesh (@c forward_rows, @c forward_columns, @c forward_weights). + PetscForwardOperator forward() const; + + /// @brief Build the backward interpolation operator B: L- ← C. + /// + /// Maps cell-space values to backward leg space using the CSR arrays stored in the + /// mesh (@c backward_rows, @c backward_columns, @c backward_weights). + PetscBackwardOperator backward() const; + + /// @brief Build the forward injection operator I+: L+ ← C. + /// + /// Places the value of each interior source cell into its corresponding forward leg + /// row(s), with weight 1. Boundary leg rows point to the virtual boundary cell in C. + PetscForwardOperator injectForward() const; + + /// @brief Build the backward injection operator I-: L- ← C. + /// + /// Analogous to @ref injectForward for the backward leg space. + PetscBackwardOperator injectBackward() const; + + /// @brief Load the forward leg-weight vector w+: L+. + /// + /// Each entry holds the quadrature weight of the corresponding forward leg row, + /// equal to the interior or boundary fraction of that leg's sub-sample integral. + PetscForwardLegVector forwardLegWeights() const; + + /// @brief Load the backward leg-weight vector w-: L-. + /// + /// Analogous to @ref forwardLegWeights for the backward leg space. + PetscBackwardLegVector backwardLegWeights() const; + + /// @brief Build a diagonal cell-space operator from a Field3D of values. + /// + /// @param f Field3D of diagonal entries; must have parallel slices allocated. + /// @returns A diagonal PetscCellOperator. + PetscCellOperator diagonal(const Field3D& f) const; + + /// @brief Build a diagonal forward-leg-space operator from a leg vector. + /// + /// @param v Forward leg vector of diagonal entries. + /// @returns A diagonal PetscForwardLegOperator. + PetscForwardLegOperator diagonal(const PetscForwardLegVector& v) const; + + /// @brief Build a diagonal backward-leg-space operator from a leg vector. + /// + /// @param v Backward leg vector of diagonal entries. + /// @returns A diagonal PetscBackwardLegOperator. + PetscBackwardLegOperator diagonal(const PetscBackwardLegVector& v) const; + + /// @brief Collection of parallel differential operators assembled for the + /// Support Operator Method (SOM). + /// + /// All operators are constructed together in @ref getParallel so that intermediate + /// quantities (leg weights, interpolated dl, dV) are shared correctly. + /// + /// Naming convention: the subscript on Grad/Div/Restrict refers to which side of + /// the cell face the operator acts on, not the leg space it lives in. + /// - @c Grad_plus / @c Div_plus: forward-side half-step operators (C to L+). + /// - @c Grad_minus / @c Div_minus: backward-side half-step operators (C to L-). + /// - @c Restrict_minus = I+^T * W+: weighted restriction from L+ back to C, + /// paired with the minus-side gradient. + /// - @c Restrict_plus = I-^T * W-: weighted restriction from L- back to C, + /// paired with the plus-side gradient. + struct Parallel { + /// Central parallel gradient: C ← C. + PetscCellOperator Grad_par; + /// Support-operator parallel divergence paired with Grad_par: C ← C. + PetscCellOperator Div_par; + /// Combined SOM parallel Laplacian (Div_par ∘ Grad_par): C ← C. + PetscCellOperator Div_par_Grad_par; + /// Cell volume J * dx * dy * dz. + Field3D dV; + + /// Half-step gradient on the backward (y-1) side: L- ← C. + PetscBackwardOperator Grad_minus; + /// Half-step gradient on the forward (y+1) side: L+ ← C. + PetscForwardOperator Grad_plus; + /// SOM divergence paired with Grad_plus: C ← L+. + PetscForwardToCellOperator Div_minus; + /// SOM divergence paired with Grad_minus: C ← L-. + PetscBackwardToCellOperator Div_plus; + + /// Raw backward interpolation operator B: L- ← C. + PetscBackwardOperator Backward; + /// Raw forward interpolation operator F: L+ ← C. + PetscForwardOperator Forward; + + /// Injection operator into backward leg space I-: L- ← C. + PetscBackwardOperator Inject_minus; + /// Injection operator into forward leg space I+: L+ ← C. + PetscForwardOperator Inject_plus; + + /// Average interpolation to backward leg positions: L- ← C. + PetscBackwardOperator Interp_minus; + /// Average interpolation to forward leg positions: L+ ← C. + PetscForwardOperator Interp_plus; + + /// Weighted restriction from L+ to C: I+^T * W+. + PetscForwardToCellOperator Restrict_minus; + /// Weighted restriction from L- to C: I-^T * W-. + PetscBackwardToCellOperator Restrict_plus; + + /// @brief Compute the SOM parallel diffusion Div_par(K * Grad_par(f)). + /// + /// Evaluates the half-step fluxes separately on each side, multiplies by the + /// interpolated diffusion coefficient K, and averages the two divergence + /// contributions. + /// + /// @param K Diffusion coefficient field; must have parallel slices allocated. + /// @param f Field to differentiate; must have parallel slices allocated. + /// @returns Field3D containing Div_par(K * Grad_par(f)) at interior cells. + Field3D Div_par_K_Grad_par(const Field3D& K, const Field3D& f) const; + }; + + /// @brief Assemble and return the full set of parallel SOM operators. + /// + /// Constructs all primitive operators (Forward, Backward, Inject_plus, + /// Inject_minus, leg weights), derives the interpolation, gradient, restriction, + /// and divergence operators, and returns them packaged in a @ref Parallel struct. + /// Intermediate Field3D quantities (dl, dV) are computed from the mesh + /// coordinates and boundary conditions are applied before use. + /// + /// @returns A @ref Parallel struct containing all assembled operators. + Parallel getParallel() const; + +private: + /// @brief Read a Field3D from the mesh, throwing if the field is absent. + /// + /// @param mesh Non-owning mesh pointer. + /// @param name Field name as stored in the mesh file. + /// @returns The requested Field3D. + /// @throws BoutException if the field is not found. + static Field3D meshGetField3D(Mesh* mesh, const std::string& name); + + /// @brief Read an Array from the mesh, throwing if absent. + /// + /// @tparam T Element type of the array. + /// @param name Array name as stored in the mesh file. + /// @returns The requested Array. + /// @throws BoutException if the array is not found. + template + Array meshGetArray(const std::string& name) const { + Array result; + if (mesh->get(result, name) != 0) { + throw BoutException("PetscOperators requires array '{}'", name); + } + return result; + } + + /// @brief Read a scalar integer from the mesh, throwing if absent. + /// + /// @param name Scalar name as stored in the mesh file. + /// @returns The requested integer value. + /// @throws BoutException if the scalar is not found. + int meshGetInt(const std::string& name) const; + + /// @brief Build a leg-space injection operator for the given direction. + /// + /// Iterates owned interior cells and inserts a unit entry for each interior or + /// boundary leg row, mapping to the corresponding cell-space column. Column + /// indices come from @p interior_leg_number and @p boundary_leg_number. + /// + /// @tparam LegTag @ref ForwardLegSpaceTag or @ref BackwardLegSpaceTag. + /// @param interior_leg_number Field3D of stored interior leg row numbers. + /// @param boundary_leg_number Field3D of stored boundary leg row numbers. + /// @param leg_mapping Shared mapping for the leg space. + /// @returns The assembled injection operator LegTag ← CellSpaceTag. + template + PetscOperator + buildInjection(const Field3D& interior_leg_number, const Field3D& boundary_leg_number, + std::shared_ptr leg_mapping) const; + + /// @brief Load a leg-weight vector from a named mesh array. + /// + /// Reads the flat array @p name from the mesh, then scatters values into the + /// local PETSc vector using the mapping's stored index list. Stored indices that + /// are out of range are assigned weight 0. + /// + /// @tparam LegVector @ref PetscForwardLegVector or @ref PetscBackwardLegVector. + /// @param name Array name in the mesh file (e.g. "forward_leg_weights"). + /// @param mapping Shared mapping for the leg space. + /// @returns A fully populated leg-weight vector. + template + LegVector loadLegWeights(const std::string& name, + std::shared_ptr mapping) const { + auto values = meshGetArray(name); + LegVector out(mapping); + PetscScalar* x{nullptr}; + BOUT_DO_PETSC(VecGetArray(out.raw(), &x)); + const auto& local = mapping->localStoredIndices(); + for (PetscInt i = 0; i < static_cast(local.size()); ++i) { + const int stored = local[i]; + x[i] = (stored >= 0 && stored < static_cast(values.size())) ? values[stored] + : 0.0; + } + BOUT_DO_PETSC(VecRestoreArray(out.raw(), &x)); + return out; + } + + Mesh* mesh{nullptr}; ///< Non-owning pointer to the BOUT++ mesh. + PetscCellMappingPtr cell_mapping; ///< Cell-space index mapping. + PetscLegMappingPtr forward_leg_mapping; ///< Forward leg-space index mapping. + PetscLegMappingPtr backward_leg_mapping; ///< Backward leg-space index mapping. + Field3D forward_leg_interior_number; ///< Stored interior leg numbers for L+. + Field3D forward_leg_boundary_number; ///< Stored boundary leg numbers for L+. + Field3D backward_leg_interior_number; ///< Stored interior leg numbers for L-. + Field3D backward_leg_boundary_number; ///< Stored boundary leg numbers for L-. +}; + +/// @brief Build the Neumann boundary operator N : C → C. +/// +/// For each cell that has a forward or backward boundary virtual cell, +/// copies the adjacent interior cell value into the virtual cell row. +/// All other rows are identity. Used to ensure Restrict_minus has non-zero +/// rows for boundary cells so that boundary conditions propagate into +/// Grad_par and Div_par. +/// +/// @param direction Which Y boundary cells will be set +/// +/// @returns A PetscCellOperator representing the Neumann boundary mapping. +PetscCellOperator makeNeumannOperator(const PetscCellMappingPtr& mapping, + BoundaryDirection direction); + +#else + +#warning PETSc not available. No PetscOperators. + +#endif + +#endif // BOUT_PETSC_OPERATORS diff --git a/include/bout/petsc_preconditioner.hxx b/include/bout/petsc_preconditioner.hxx new file mode 100644 index 0000000000..f413d28d3b --- /dev/null +++ b/include/bout/petsc_preconditioner.hxx @@ -0,0 +1,123 @@ +/************************************************************************** + * Reusable PETSc coloring-based Jacobian preconditioner support + * + * This class factors out the duplicated code in PETSc-based solvers for: + * - building a Jacobian sparsity pattern (via stencil assumptions) + * - creating a MatFDColoring context for efficient finite-difference Jacobians + * + **************************************************************************/ + +#ifndef BOUT_PETSC_PRECONDITIONER_H +#define BOUT_PETSC_PRECONDITIONER_H + +#include "bout/bout_enum_class.hxx" +#include "bout/build_defines.hxx" + +BOUT_ENUM_CLASS_NS(bout, PetscMatrixExportFormat, binary, ascii); + +BOUT_ENUM_CLASS_NS( + bout, JacobianExportKind, + system, ///< Jacobian of the full nonlinear system solved by the solver + scaled, ///< Jacobian after solver-coordinate transforms such as variable scaling + rhs ///< Jacobian of the raw model RHS in physical variables +); + +#if BOUT_HAS_PETSC + +#include "bout/petsc_interface.hxx" +#include "bout/petsclib.hxx" + +#include + +#include +#include + +#include + +class Options; +class Field3D; + +class PetscPreconditioner { +public: + PetscPreconditioner() = default; + ~PetscPreconditioner() { reset(); } + + PetscPreconditioner(const PetscPreconditioner&) = delete; + PetscPreconditioner& operator=(const PetscPreconditioner&) = delete; + PetscPreconditioner(PetscPreconditioner&&) = delete; + PetscPreconditioner& operator=(PetscPreconditioner&&) = delete; + + /// Create and assemble a finite-difference Jacobian matrix `Jfd` with a sparsity + /// pattern derived from the solver's variable layout and a user-specified stencil. + /// + /// `index` should be generated by the calling solver (e.g. `Solver::globalIndex(0)`). + /// Safe to call multiple times; any existing PETSc objects are destroyed first. + PetscErrorCode createJacobianPattern(Field3D& index, Options& options, PetscInt nlocal, + int n2d, int n3d, MPI_Comm comm); + + /// Recalculate the PETSc coloring and finite-difference coloring context + /// for the currently stored `Jfd` matrix. + template + PetscErrorCode updateColoring(ColoringFunction function, void* ctx) { + // Re-calculate the coloring + MatColoring coloring{nullptr}; + PetscCall(MatColoringCreate(Jfd, &coloring)); + PetscCall(MatColoringSetType(coloring, MATCOLORINGGREEDY)); + PetscCall(MatColoringSetFromOptions(coloring)); + + // Calculate new index sets + ISColoring iscoloring{nullptr}; + PetscCall(MatColoringApply(coloring, &iscoloring)); + PetscCall(MatColoringDestroy(&coloring)); + + // Replace the old coloring with the new one + PetscCall(MatFDColoringDestroy(&fdcoloring)); + PetscCall(MatFDColoringCreate(Jfd, iscoloring, &fdcoloring)); + PetscCall( + MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(function), ctx)); + PetscCall(MatFDColoringSetFromOptions(fdcoloring)); + PetscCall(MatFDColoringSetUp(Jfd, iscoloring, fdcoloring)); + PetscCall(ISColoringDestroy(&iscoloring)); + + PetscFunctionReturn(PETSC_SUCCESS); + } + + Mat jacobian() const { return Jfd; } + MatFDColoring coloring() const { return fdcoloring; } + + /// Save an arbitrary PETSc matrix to disk using ``MatView``. + /// + /// This is a low-level utility used by solver-specific diagnostic code. It only + /// writes the matrix itself in PETSc binary or ASCII format; companion metadata + /// such as variable names and index mapping must be written separately by the + /// calling solver. + static PetscErrorCode saveMatrix( + Mat matrix, const std::string& filename, + bout::PetscMatrixExportFormat format = bout::PetscMatrixExportFormat::binary); + /// Save the internally owned coloring Jacobian matrix ``Jfd``. + PetscErrorCode saveMatrix( + const std::string& filename, + bout::PetscMatrixExportFormat format = bout::PetscMatrixExportFormat::binary) const; + + void reset(); + +private: + Mat Jfd{nullptr}; + MatFDColoring fdcoloring{nullptr}; +}; + +#else + +// PETSc is not available, but keep the type defined so headers can be included +// unconditionally in PETSc-enabled compilation units. +class PetscPreconditioner { +public: + void saveMatrix(const std::string& UNUSED(filename), + bout::PetscMatrixExportFormat UNUSED(format) = + bout::PetscMatrixExportFormat::binary) const {} + void reset() {} +}; + +#endif // BOUT_HAS_PETSC + +#endif // BOUT_PETSC_PRECONDITIONER_H diff --git a/include/bout/petsclib.hxx b/include/bout/petsclib.hxx index 2008671286..637943bd12 100644 --- a/include/bout/petsclib.hxx +++ b/include/bout/petsclib.hxx @@ -1,31 +1,31 @@ /*!************************************************************************ * Provides access to the PETSc library, handling initialisation and - * finalisation. + * finalisation. * * Usage * ----- * * #include - * + * * class MyClass { * public: - * + * * private: * PetscLib lib; * }; - * + * * * This will then automatically initialise Petsc the first time an object * is created, and finalise it when the last object is destroyed. * * This header tries to workaround some annoying PETSc features, and * so it *must* be included before *any* PETSc header. - * + * ************************************************************************** - * Copyright 2012 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2012 - 2026 BOUT++ contributors + * + * Contact: Ben Dudson, dudson2@llnl.gov * - * Contact: Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -48,6 +48,8 @@ #include "bout/build_defines.hxx" +#include + class Options; #if BOUT_HAS_PETSC @@ -60,12 +62,13 @@ class Options; #define PETSC_HAVE_BROKEN_RECURSIVE_MACRO #include // IWYU pragma: export +#include #include #include "bout/boutexception.hxx" // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define BOUT_DO_PETSC(cmd) PetscLib::assertIerr((cmd), #cmd) +#define BOUT_DO_PETSC(cmd) PetscLib::assertIerr((cmd), #cmd, __FILE__, __LINE__) /*! * Handles initialisation and finalisation of PETSc library. @@ -113,6 +116,9 @@ public: /// was passed to the constructor. void setOptionsFromInputFile(SNES& snes); + /// Set options for a TS time integrator + void setOptionsFromInputFile(TS& ts); + /*! * Force cleanup. This will call PetscFinalize, printing a warning * if any instances of PetscLib still exist @@ -120,10 +126,17 @@ public: static void cleanup(); static inline void assertIerr(PetscErrorCode ierr, - const std::string& petsc_op = "PETSc operation") { - if (ierr != 0) { - throw BoutException("{:s} failed with {:d}", petsc_op, ierr); + const std::string& petsc_op = "PETSc operation", + const char* file = nullptr, int linenr = 0) { + if (PetscLikely(ierr == PETSC_SUCCESS)) { + return; } + + const char* err_msg = nullptr; + PetscErrorMessage(ierr, &err_msg, nullptr); + throw BoutException("{:s} failed at {}:{} with {:d} [{}]", petsc_op, + (file != nullptr) ? file : "unknown_file", linenr, ierr, + (err_msg != nullptr) ? err_msg : ""); } static BoutException SNESFailure(SNES& snes); diff --git a/include/bout/physicsmodel.hxx b/include/bout/physicsmodel.hxx index 21fe1f15c0..2dc50dcfee 100644 --- a/include/bout/physicsmodel.hxx +++ b/include/bout/physicsmodel.hxx @@ -1,14 +1,13 @@ /*!************************************************************************ * \file physicsmodel.hxx - * + * * @brief Base class for Physics Models - * - * + * ************************************************************************** * Copyright 2013-2025 BOUT++ contributors * * Contact: Ben Dudson, dudson2@llnl.gov - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -41,6 +40,9 @@ class PhysicsModel; #include "bout/unused.hxx" #include "bout/utils.hxx" +#include +#include +#include #include #include @@ -158,9 +160,9 @@ public: * * Output * ------ - * + * * The time derivatives will be put in the ddt() variables - * + * * Returns a flag: 0 indicates success, non-zero an error flag */ int runRHS_se(BoutReal time, bool linear = false); @@ -209,7 +211,7 @@ public: bool hasPreconSlow() const { return (userprecon_s != nullptr); } /*! - * Run the preconditioner. The system state should be in the + * Run the preconditioner. The system state should be in the * evolving variables, and the vector to be solved in the ddt() variables. * The result will be put in the ddt() variables. * @@ -227,7 +229,7 @@ public: /*! * Run the Jacobian-vector multiplication function - * + * * Note: this is usually only called by the Solver */ int runJacobian(BoutReal t); @@ -249,10 +251,10 @@ protected: // The init and rhs functions are implemented by user code to specify problem /*! * @brief This function is called once by the solver at the start of a simulation. - * + * * A valid PhysicsModel must implement this function - * - * Variables should be read from the inputs, and the variables to + * + * Variables should be read from the inputs, and the variables to * be evolved should be specified. */ virtual int init(bool restarting) = 0; @@ -266,7 +268,7 @@ protected: /*! * @brief This function is called by the time integration solver * at least once per time step - * + * * Variables being evolved will be set by the solver * before the call, and this function must calculate * and set the time-derivatives. @@ -304,10 +306,10 @@ protected: /// Add additional variables other than the evolving variables to the restart files virtual void restartVars(Options& options); - /* + /* If split operator is set to true, then convective() and diffusive() are called instead of rhs() - + For implicit-explicit schemes, convective() will typically be treated explicitly, whilst diffusive() will be treated implicitly. For unsplit methods, both convective and diffusive will be called @@ -376,7 +378,7 @@ protected: * * @param[in] var The variable to evolve * @param[in] name The name to use for variable initialisation and output - * + * * Note that the variable must not be destroyed (e.g. go out of scope) * after this call, since a pointer to \p var is stored in the solver. * @@ -400,11 +402,11 @@ protected: * Specify a constrained variable \p var, which will be * adjusted to make \p F_var equal to zero. * If the solver does not support constraints then this will throw an exception - * + * * @param[in] var The variable the solver should modify * @param[in] F_var The control variable, which the user will set * @param[in] name The name to use for initialisation and output - * + * */ bool bout_constrain(Field3D& var, Field3D& F_var, const char* name); @@ -421,6 +423,9 @@ protected: PhysicsModel* model; }; + /// Set timestep counter for flushing file + void setFlushCounter(std::size_t iteration) { flush_counter = iteration; } + private: /// State for outputs Options output_options; @@ -448,33 +453,36 @@ private: bool initialised{false}; /// write restarts and pass outputMonitor method inside a Monitor subclass PhysicsModelMonitor modelMonitor{this}; + /// How often to flush to disk + std::size_t flush_frequency{1}; + /// Current timestep counter + std::size_t flush_counter{0}; }; /*! - * Macro to define a simple main() which creates - * the given model and runs it. This should be sufficient - * for most use cases, but a user can define their own - * main() function if needed. + * Macro to define a simple ``main()`` which creates the given model + * and runs it. This should be sufficient for most use cases, but a + * user can define their own ``main()`` function if needed. * * Example * ------- * - * class MyModel : public PhysicsModel { - * .. - * }; + * class MyModel : public PhysicsModel { + * // ... + * }; * - * BOUTMAIN(MyModel); + * BOUTMAIN(MyModel); */ #define BOUTMAIN(ModelClass) \ int main(int argc, char** argv) { \ - int init_err = BoutInitialise(argc, argv); \ - if (init_err < 0) { \ - return 0; \ - } \ - if (init_err > 0) { \ - return init_err; \ - } \ try { \ + int init_err = BoutInitialise(argc, argv); \ + if (init_err < 0) { \ + return 0; \ + } \ + if (init_err > 0) { \ + return init_err; \ + } \ auto model = bout::utils::make_unique(); \ auto solver = Solver::create(); \ solver->setModel(model.get()); \ @@ -482,8 +490,8 @@ private: solver->addMonitor(bout_monitor.get(), Solver::BACK); \ solver->solve(); \ } catch (const BoutException& e) { \ - output << "Error encountered: " << e.what(); \ - output << e.getBacktrace() << endl; \ + output.write("Error encountered: {}\n", e.what()); \ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); \ MPI_Abort(BoutComm::get(), 1); \ } \ BoutFinalise(); \ @@ -530,8 +538,7 @@ private: /// Add fields to the solver. /// This should accept up to ten arguments -#define SOLVE_FOR(...) \ - { MACRO_FOR_EACH(SOLVE_FOR1, __VA_ARGS__) } +#define SOLVE_FOR(...) {MACRO_FOR_EACH(SOLVE_FOR1, __VA_ARGS__)} /// Write this variable once to the grid file #define SAVE_ONCE1(var) dump.addOnce(var, #var); @@ -571,8 +578,7 @@ private: dump.addOnce(var6, #var6); \ } -#define SAVE_ONCE(...) \ - { MACRO_FOR_EACH(SAVE_ONCE1, __VA_ARGS__) } +#define SAVE_ONCE(...) {MACRO_FOR_EACH(SAVE_ONCE1, __VA_ARGS__)} /// Write this variable every timestep #define SAVE_REPEAT1(var) dump.addRepeat(var, #var); @@ -612,7 +618,6 @@ private: dump.addRepeat(var6, #var6); \ } -#define SAVE_REPEAT(...) \ - { MACRO_FOR_EACH(SAVE_REPEAT1, __VA_ARGS__) } +#define SAVE_REPEAT(...) {MACRO_FOR_EACH(SAVE_REPEAT1, __VA_ARGS__)} #endif // BOUT_PHYSICS_MODEL_H diff --git a/include/bout/rajalib.hxx b/include/bout/rajalib.hxx index b9f6913459..859463325e 100644 --- a/include/bout/rajalib.hxx +++ b/include/bout/rajalib.hxx @@ -1,4 +1,4 @@ -/*! +/*! \file * RAJA library utilities and wrappers * * Defines: @@ -14,6 +14,7 @@ */ #pragma once +#include "bout/array.hxx" #ifndef RAJALIB_H #define RAJALIB_H @@ -23,6 +24,15 @@ #include "RAJA/RAJA.hpp" // using RAJA lib +#if BOUT_HAS_CUDA +// TODO: Make configurable +const int CUDA_BLOCK_SIZE = 256; +using EXEC_POL = RAJA::cuda_exec; +//using EXEC_POL = RAJA::loop_exec; +#else // not BOUT_USE_CUDA +using EXEC_POL = RAJA::loop_exec; +#endif // end BOUT_USE_CUDA + /// Wrapper around RAJA::forall /// Enables computations to be done on CPU or GPU (CUDA). /// @@ -81,7 +91,7 @@ struct RajaForAll { // Note: must be a local variable const int* _ob_i_ind_raw = &_ob_i_ind[0]; RAJA::forall(RAJA::RangeSegment(0, _ob_i_ind.size()), - [=] RAJA_DEVICE(int id) { + [=] RAJA_DEVICE(int id) mutable { // Look up index and call user function f(_ob_i_ind_raw[id]); }); @@ -127,7 +137,7 @@ private: /// to create variables which shadow the class members. /// #define BOUT_FOR_RAJA(index, region, ...) \ - RajaForAll(region) << [ =, ##__VA_ARGS__ ] RAJA_DEVICE(int index) + RajaForAll(region) << [ =, ##__VA_ARGS__ ] RAJA_DEVICE(int index) mutable #else // BOUT_HAS_RAJA diff --git a/include/bout/region.hxx b/include/bout/region.hxx index bb1cf82bf1..e47be5a551 100644 --- a/include/bout/region.hxx +++ b/include/bout/region.hxx @@ -1,9 +1,9 @@ /************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors * * Region class by D. Dickinson 2018 * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -49,9 +49,11 @@ #include #include +#include "bout/array.hxx" #include "bout/assert.hxx" #include "bout/bout_types.hxx" #include "bout/boutexception.hxx" +#include "bout/build_config.hxx" #include "bout/build_defines.hxx" #include "bout/openmpwrap.hxx" // IWYU pragma: keep @@ -139,7 +141,7 @@ class BoutMask; BOUT_FOR_OMP(index, (region), for schedule(BOUT_OPENMP_SCHEDULE) nowait) // NOLINTEND(cppcoreguidelines-macro-usage,bugprone-macro-parentheses) -enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2 }; +enum class IND_TYPE { IND_3D = 0, IND_2D = 1, IND_PERP = 2, IND_GLOBAL_3D = 3 }; /// Indices base class for Fields -- Regions are dereferenced into these /// @@ -170,8 +172,8 @@ struct SpecificInd { int ny = -1, nz = -1; ///< Sizes of y and z dimensions SpecificInd() = default; - SpecificInd(int i, int ny, int nz) : ind(i), ny(ny), nz(nz){}; - explicit SpecificInd(int i) : ind(i){}; + SpecificInd(int i, int ny, int nz) : ind(i), ny(ny), nz(nz) {}; + explicit SpecificInd(int i) : ind(i) {}; /// Allow explicit conversion to an int explicit operator int() const { return ind; } @@ -239,47 +241,49 @@ struct SpecificInd { /// and is determined by the `dir` template argument. The offset corresponds /// to the `dd` template argument. template - inline SpecificInd plus() const { + SpecificInd plus() const { static_assert(dir == DIRECTION::X || dir == DIRECTION::Y || dir == DIRECTION::Z || dir == DIRECTION::YAligned || dir == DIRECTION::YOrthogonal, "Unhandled DIRECTION in SpecificInd::plus"); switch (dir) { - case (DIRECTION::X): + case DIRECTION::X: return xp(dd); - case (DIRECTION::Y): - case (DIRECTION::YAligned): - case (DIRECTION::YOrthogonal): + case DIRECTION::Y: + case DIRECTION::YAligned: + case DIRECTION::YOrthogonal: return yp(dd); - case (DIRECTION::Z): + case DIRECTION::Z: return zp(dd); } + BOUT_UNREACHABLE(); } /// Templated routine to return index.?m(offset), where `?` is one of {x,y,z} /// and is determined by the `dir` template argument. The offset corresponds /// to the `dd` template argument. template - inline SpecificInd minus() const { + SpecificInd minus() const { static_assert(dir == DIRECTION::X || dir == DIRECTION::Y || dir == DIRECTION::Z || dir == DIRECTION::YAligned || dir == DIRECTION::YOrthogonal, "Unhandled DIRECTION in SpecificInd::minus"); switch (dir) { - case (DIRECTION::X): + case DIRECTION::X: return xm(dd); - case (DIRECTION::Y): - case (DIRECTION::YAligned): - case (DIRECTION::YOrthogonal): + case DIRECTION::Y: + case DIRECTION::YAligned: + case DIRECTION::YOrthogonal: return ym(dd); - case (DIRECTION::Z): + case DIRECTION::Z: return zm(dd); } + BOUT_UNREACHABLE(); } - inline SpecificInd xp(int dx = 1) const { return {ind + (dx * ny * nz), ny, nz}; } + SpecificInd xp(int dx = 1) const { return {ind + (dx * ny * nz), ny, nz}; } /// The index one point -1 in x - inline SpecificInd xm(int dx = 1) const { return xp(-dx); } + SpecificInd xm(int dx = 1) const { return xp(-dx); } /// The index one point +1 in y - inline SpecificInd yp(int dy = 1) const { + SpecificInd yp(int dy = 1) const { #if CHECK >= 4 if (y() + dy < 0 or y() + dy >= ny) { throw BoutException("Offset in y ({:d}) would go out of bounds at {:d}", dy, ind); @@ -289,12 +293,12 @@ struct SpecificInd { return {ind + (dy * nz), ny, nz}; } /// The index one point -1 in y - inline SpecificInd ym(int dy = 1) const { return yp(-dy); } + SpecificInd ym(int dy = 1) const { return yp(-dy); } /// The index one point +1 in z. Wraps around zend to zstart /// An alternative, non-branching calculation is : /// ind + dz - nz * ((ind + dz) / nz - ind / nz) /// but this appears no faster (and perhaps slower). - inline SpecificInd zp(int dz = 1) const { + SpecificInd zp(int dz = 1) const { ASSERT3(dz >= 0); dz = dz <= nz ? dz : dz % nz; //Fix in case dz > nz, if not force it to be in range return {(ind + dz) % nz < dz ? ind - nz + dz : ind + dz, ny, nz}; @@ -303,58 +307,29 @@ struct SpecificInd { /// An alternative, non-branching calculation is : /// ind - dz + nz * ( (nz + ind) / nz - (nz + ind - dz) / nz) /// but this appears no faster (and perhaps slower). - inline SpecificInd zm(int dz = 1) const { + SpecificInd zm(int dz = 1) const { dz = dz <= nz ? dz : dz % nz; //Fix in case dz > nz, if not force it to be in range ASSERT3(dz >= 0); return {(ind) % nz < dz ? ind + nz - dz : ind - dz, ny, nz}; } /// Automatically select zm or zp depending on sign - inline SpecificInd zpm(int dz) const { return dz > 0 ? zp(dz) : zm(-dz); } + SpecificInd zpm(int dz) const { return dz > 0 ? zp(dz) : zm(-dz); } // and for 2 cells - inline SpecificInd xpp() const { return xp(2); } - inline SpecificInd xmm() const { return xm(2); } - inline SpecificInd ypp() const { return yp(2); } - inline SpecificInd ymm() const { return ym(2); } - inline SpecificInd zpp() const { return zp(2); } - inline SpecificInd zmm() const { return zm(2); } + SpecificInd xpp() const { return xp(2); } + SpecificInd xmm() const { return xm(2); } + SpecificInd ypp() const { return yp(2); } + SpecificInd ymm() const { return ym(2); } + SpecificInd zpp() const { return zp(2); } + SpecificInd zmm() const { return zm(2); } /// Generic offset of \p index in multiple directions simultaneously - inline SpecificInd offset(int dx, int dy, int dz) const { - return zpm(dz).yp(dy).xp(dx); - } -}; - -/// Relational operators -template -inline bool operator==(const SpecificInd& lhs, const SpecificInd& rhs) { - return lhs.ind == rhs.ind; -} - -template -inline bool operator!=(const SpecificInd& lhs, const SpecificInd& rhs) { - return !operator==(lhs, rhs); -} - -template -inline bool operator<(const SpecificInd& lhs, const SpecificInd& rhs) { - return lhs.ind < rhs.ind; -} - -template -inline bool operator>(const SpecificInd& lhs, const SpecificInd& rhs) { - return operator<(rhs, lhs); -} + SpecificInd offset(int dx, int dy, int dz) const { return zpm(dz).yp(dy).xp(dx); } -template -inline bool operator>=(const SpecificInd& lhs, const SpecificInd& rhs) { - return !operator<(lhs, rhs); -} - -template -inline bool operator<=(const SpecificInd& lhs, const SpecificInd& rhs) { - return !operator>(lhs, rhs); -} + /// Relational operator + auto operator<=>(const SpecificInd& rhs) const { return ind <=> rhs.ind; } + bool operator==(const SpecificInd& rhs) const { return ind == rhs.ind; } +}; /// Arithmetic operators with integers template @@ -386,6 +361,7 @@ inline SpecificInd operator-(SpecificInd lhs, const SpecificInd& rhs) { using Ind3D = SpecificInd; using Ind2D = SpecificInd; using IndPerp = SpecificInd; +using IndG3D = SpecificInd; /// Get string representation of Ind3D inline std::string toString(const Ind3D& i) { @@ -490,10 +466,9 @@ template class Region { // Following prevents a Region being created with anything other // than Ind2D, Ind3D or IndPerp as template type - static_assert( - std::is_base_of_v< - Ind2D, T> || std::is_base_of_v || std::is_base_of_v, - "Region must be templated with one of IndPerp, Ind2D or Ind3D"); + static_assert(std::is_base_of_v || std::is_base_of_v + || std::is_base_of_v, + "Region must be templated with one of IndPerp, Ind2D or Ind3D"); public: using data_type = T; @@ -569,7 +544,7 @@ public: }; Region(RegionIndices& indices, int maxregionblocksize = MAXREGIONBLOCKSIZE) - : indices(indices), blocks(getContiguousBlocks(maxregionblocksize)){}; + : indices(indices), blocks(getContiguousBlocks(maxregionblocksize)) {}; // We need to first set the blocks, and only after that call getRegionIndices. // Do not put in the member initialisation @@ -594,17 +569,28 @@ public: const ContiguousBlocks& getBlocks() const { return blocks; }; const RegionIndices& getIndices() const { return indices; }; + const Array& getLinearIndices() const { + if (linearIndices.empty()) { + linearIndices = Array(indices.size()); + for (size_type i = 0; i < indices.size(); ++i) { + linearIndices[i] = indices[i].ind; + } + } + return linearIndices; + } /// Set the indices and ensure blocks updated void setIndices(RegionIndices& indicesIn, int maxregionblocksize = MAXREGIONBLOCKSIZE) { indices = indicesIn; blocks = getContiguousBlocks(maxregionblocksize); + invalidateLinearIndices(); }; /// Set the blocks and ensure indices updated void setBlocks(ContiguousBlocks& blocksIn) { blocks = blocksIn; indices = getRegionIndices(); + invalidateLinearIndices(); }; /// Return a new Region that has the same indices as this one but @@ -828,10 +814,13 @@ public: // sorted this would prevent this usage. private: - RegionIndices indices; //< Flattened indices - ContiguousBlocks blocks; //< Contiguous sections of flattened indices - int ny = -1; //< Size of y dimension - int nz = -1; //< Size of z dimension + RegionIndices indices; //< Flattened indices + ContiguousBlocks blocks; //< Contiguous sections of flattened indices + int ny = -1; //< Size of y dimension + int nz = -1; //< Size of z dimension + mutable Array linearIndices; //< Cached flattened integer indices + + void invalidateLinearIndices() const { linearIndices.clear(); } /// Helper function to create a RegionIndices, given the start and end /// points in x, y, z, and the total y, z lengths @@ -972,6 +961,12 @@ Region operator+(const Region& lhs, const Region& rhs) { return Region(indices); } +template +Region operator+(Region&& lhs, const Region& rhs) { + lhs += rhs; + return std::move(lhs); +} + /// Returns a new region based on input but with indices offset by /// a constant template diff --git a/include/bout/scorepwrapper.hxx b/include/bout/scorepwrapper.hxx index 81761530f0..8b37b2ff61 100644 --- a/include/bout/scorepwrapper.hxx +++ b/include/bout/scorepwrapper.hxx @@ -3,7 +3,6 @@ #include "bout/build_defines.hxx" -#include "bout/msg_stack.hxx" #include #if BOUT_HAS_SCOREP @@ -14,13 +13,25 @@ #define SCOREPLVL 0 #endif +/// The __PRETTY_FUNCTION__ variable is defined by GCC (and some other families) but is +/// not a part of the standard. The __func__ variable *is* a part of the c++11 standard so +/// we'd like to fall back to this if possible. However as these are variables/constants +/// and not macros we can't just check if __PRETTY_FUNCITON__ is defined or not. Instead +/// we need to say if we support this or not by defining BOUT_HAS_PRETTY_FUNCTION (to be +/// implemented in configure) +#if BOUT_HAS_PRETTY_FUNCTION +#define _thefunc_ __PRETTY_FUNCTION__ +#else +#define _thefunc_ __func__ +#endif + /// Instrument a function with scorep /// /// The scorep call is identical for all levels, so just define it here. /// If we don't have scorep support then just define a null function #if BOUT_HAS_SCOREP #define SCOREP_BASE_CALL(...) \ - SCOREP_USER_REGION(__thefunc__, SCOREP_USER_REGION_TYPE_FUNCTION) + SCOREP_USER_REGION(_thefunc_, SCOREP_USER_REGION_TYPE_FUNCTION) #else #define SCOREP_BASE_CALL(...) #endif diff --git a/include/bout/single_index_ops.hxx b/include/bout/single_index_ops.hxx index 60bd78bc36..3f4686c514 100644 --- a/include/bout/single_index_ops.hxx +++ b/include/bout/single_index_ops.hxx @@ -5,18 +5,11 @@ #ifndef SINGLE_INDEX_OPS_H #define SINGLE_INDEX_OPS_H -#include "field_accessor.hxx" - -#if BOUT_HAS_RAJA -//-- RAJA CUDA settings--------------------------------------------------------start -#if BOUT_HAS_CUDA -const int CUDA_BLOCK_SIZE = 256; // TODO: Make configurable -using EXEC_POL = RAJA::cuda_exec; -#else // not BOUT_USE_CUDA -using EXEC_POL = RAJA::loop_exec; -#endif // end BOUT_USE_CUDA -////-----------CUDA settings------------------------------------------------------end -#endif // end BOUT_HAS_RAJA +#include "bout/bout_types.hxx" +#include "bout/build_config.hxx" +#include "bout/field_accessor.hxx" +#include "bout/region.hxx" +#include "bout/utils.hxx" // Ind3D: i.zp(): BOUT_HOST_DEVICE inline int i_zp(const int id, const int nz) { @@ -239,8 +232,8 @@ BOUT_HOST_DEVICE inline BoutReal Delp2(const FieldAccessor& f, const i return (f.coords.G1(i) + f.coords.d1_dx(i) * f.coords.g11(i)) * (f[ixp] - f[ixm]) / (2.0 * dx) // DDX + f.coords.G3(i) * (f[izp] - f[izm]) / (2.0 * dz) // DDZ - + f.coords.g11(i) * (f[ixp] - 2.0 * f[i] + f[ixm]) / SQ(dx) // D2DX2 - + f.coords.g33(i) * (f[izp] - 2.0 * f[i] + f[izm]) / SQ(dz) // D2DZ2 + + f.coords.g11(i) * (f[ixp] + f[ixm] - 2.0 * f[i]) / SQ(dx) // D2DX2 + + f.coords.g33(i) * (f[izp] + f[izm] - 2.0 * f[i]) / SQ(dz) // D2DZ2 + 2 * f.coords.g13(i) * ((f[izpxp] - f[izpxm]) - (f[izmxp] - f[izmxm])) / (4. * dz * dx); // D2DXDZ } diff --git a/include/bout/solver.hxx b/include/bout/solver.hxx index 5b14fc09ed..1c26166b02 100644 --- a/include/bout/solver.hxx +++ b/include/bout/solver.hxx @@ -1,20 +1,10 @@ /************************************************************************** * Base class for all solvers. Specifies required interface functions * - * Changelog: - * - * 2009-08 Ben Dudson, Sean Farley - * * Major overhaul, and changed API. Trying to make consistent - * interface to PETSc and SUNDIALS solvers - * - * 2013-08 Ben Dudson - * * Added OO-style API, to allow multiple physics models to coexist - * For now both APIs are supported - * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -38,18 +28,27 @@ #include "bout/build_defines.hxx" +#include "bout/bout_enum_class.hxx" #include "bout/bout_types.hxx" #include "bout/boutexception.hxx" +#include "bout/globals.hxx" +#include "bout/mesh.hxx" #include "bout/monitor.hxx" #include "bout/options.hxx" -#include "bout/unused.hxx" +#include "bout/petsc_preconditioner.hxx" +#include "bout/region.hxx" +#include +#include +#include #include +#include /////////////////////////////////////////////////////////////////// // C function pointer types class Solver; +class SundialsNVectorInterface; /// RHS function pointer using rhsfunc = int (*)(BoutReal); @@ -92,7 +91,8 @@ constexpr auto SOLVERIMEXBDF2 = "imexbdf2"; constexpr auto SOLVERSNES = "snes"; constexpr auto SOLVERRKGENERIC = "rkgeneric"; -enum class SOLVER_VAR_OP { LOAD_VARS, LOAD_DERIVS, SET_ID, SAVE_VARS, SAVE_DERIVS }; +enum class FieldCategories : std::uint8_t { VARS, DERIVS, MMS }; +enum class SOLVER_VAR_OP : std::uint8_t { LOAD, SET_ID, SAVE }; /// A type to set where in the list monitors are added enum class MonitorPosition { BACK, FRONT }; @@ -371,6 +371,37 @@ public: int getIterationOffset() const { return iteration_offset; } protected: + friend class SundialsNVectorInterface; + + /// Per-variable metadata written alongside Jacobian diagnostics. + /// + /// ``offset`` gives the variable position within the per-cell ordering used by + /// the PETSc matrix. The full row/column mapping is reconstructed by combining + /// these records with ``jacobian_index_base`` from the dump files. + struct JacobianVariableMetadata { + int offset{0}; + std::string name; + std::string location; + bool evolve_bndry{false}; + bool constraint{false}; + std::string description; + }; + + /// Top-level JSON description of a saved Jacobian. + /// + /// This metadata is intentionally compact: per-variable properties are stored + /// once here, while per-cell offsets are reconstructed from + /// ``jacobian_index_base`` in the output data files. + struct JacobianMetadata { + int format_version{1}; + std::string solver_name; + int n2d{0}; + int n3d{0}; + std::vector variables_2d; + std::vector variables_3d; + std::string ordering; + }; + /// Number of command-line arguments static int* pargc; /// Command-line arguments @@ -401,6 +432,97 @@ protected: std::string description{""}; /// Description of what the variable is }; + /// A structure for iterating over fields + template + struct VarIterator { + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using pointer = T*; + using reference = T&; + using underlying_iterator = std::vector>::iterator; + using difference_type = std::iterator_traits::difference_type; + + VarIterator(underlying_iterator _it) : it(std::move(_it)) {} + + reference operator*() const { + if constexpr (C == FieldCategories::VARS) { + return *(it->var); + } else if constexpr (C == FieldCategories::DERIVS) { + return *(it->F_var); + } else { + static_assert(C == FieldCategories::MMS); + return *(it->MMS_err); + } + } + pointer operator->() const { + if constexpr (C == FieldCategories::VARS) { + return it->var; + } else if constexpr (C == FieldCategories::DERIVS) { + return it->F_var; + } else { + static_assert(C == FieldCategories::MMS); + return it->MMS_err.get(); + } + } + + VarIterator& operator++() { + it++; + return *this; + } + VarIterator operator++(int) { + VarIterator tmp = *this; + ++(*this); + return tmp; + } + VarIterator& operator+=(difference_type n) { + it += n; + return *this; + } + VarIterator operator+(difference_type n) const { return VarIterator(it + n); } + friend VarIterator operator+(difference_type n, const VarIterator& a) { + return VarIterator(n + a.it); + } + + VarIterator& operator--() { + it--; + return *this; + } + VarIterator operator--(int) { + VarIterator tmp = *this; + --(*this); + return tmp; + } + VarIterator& operator-=(difference_type n) { + it -= n; + return *this; + } + VarIterator operator-(difference_type n) const { return VarIterator(it - n); } + friend VarIterator operator-(difference_type n, const VarIterator& a) { + return VarIterator(n - a.it); + } + + difference_type operator-(const VarIterator& b) { return it - b.it; } + reference operator[](difference_type n) { return *VarIterator(it[n]); } + + auto operator<=>(const VarIterator& rhs) const = default; + + private: + underlying_iterator it{}; + }; + + template + struct VarRange { + using iterator = VarIterator; + + VarRange(std::vector>& vars) : _begin(vars.begin()), _end(vars.end()) {} + + iterator begin() const { return _begin; } + iterator end() const { return _end; } + + private: + iterator _begin, _end; + }; + /// Does \p var represent field \p name? template friend bool operator==(const VarStr& var, const std::string& name) { @@ -410,8 +532,7 @@ protected: /// Does \p vars contain a field with \p name? template bool contains(const std::vector>& vars, const std::string& name) { - const auto in_vars = std::find(begin(vars), end(vars), name); - return in_vars != end(vars); + return std::ranges::find(vars, name, &VarStr::name) != std::ranges::end(vars); } /// Vectors of variables to evolve @@ -472,19 +593,19 @@ protected: /// /// There are two important things to note about how \p iter is /// passed along to each monitor: - /// - The solvers all start their iteration numbering from zero, so the - /// initial state is calculated at \p iter = -1 + /// - The initial state is written at \p iter = 0, and solver output + /// steps are numbered from 1 to NOUT /// - Secondly, \p iter is passed along to each monitor *relative to /// that monitor's period* /// /// In practice, this means that each monitor is called like: /// /// monitor->call(solver, simulation_time, - /// ((iter + 1) / monitor->period) - 1, + /// iter / monitor->period, /// NOUT / monitor->period); /// - /// e.g. for a monitor with period 10, passing \p iter = 9 will - /// result in it being called with a value of `(9 + 1)/10 - 1 == 0` + /// e.g. for a monitor with period 10, passing \p iter = 10 will + /// result in it being called with a value of `10/10 == 1` int call_monitors(BoutReal simtime, int iter, int NOUT); /// Should timesteps be monitored? @@ -513,8 +634,34 @@ protected: void save_derivs(BoutReal* dudata); void set_id(BoutReal* udata); - /// Returns a Field3D containing the global indices + /// Returns a Field3D containing the global indices for each locally-owned DOF. Field3D globalIndex(int localStart); + /// Returns the base global index for the Jacobian ordering in each cell. + /// + /// Combined with the variable metadata JSON written by + /// ``writeJacobianMetadataJson()``, this allows PETSc matrix rows/columns to be + /// mapped back to variable names and ``(x, y, z)`` coordinates in Python. + Field3D jacobianIndexBase(int localStart = 0); + /// Return compact metadata for all evolved ``Field2D`` variables. + std::vector getJacobianMetadata2D() const; + /// Return compact metadata for all evolved ``Field3D`` variables. + std::vector getJacobianMetadata3D() const; + /// Build the complete Jacobian metadata record for JSON export. + JacobianMetadata getJacobianMetadata(const std::string& solver_name) const; + /// Write Jacobian metadata as JSON on rank 0. + /// + /// The JSON file is solver-independent; solver-specific matrix files and the + /// ``jacobian_index_base`` output together provide the remaining information + /// needed to reconstruct a labeled Jacobian in post-processing. + void writeJacobianMetadataJson(const std::string& filename, + const std::string& solver_name) const; + + /// Writes the Jacobian metadata on first call + void writeOnceJacobianMetadata(const std::string& solver_name); + +#if BOUT_HAS_PETSC + void writeJacobianMatrix(bout::JacobianExportKind kind, Mat jacobian); +#endif /// Maximum internal timestep BoutReal max_dt{-1.0}; @@ -542,6 +689,28 @@ protected: /// Get the currently set output timestep BoutReal getOutputTimestep() const { return output_timestep; } + /// Loop over variables (accessed by iterating the f2d_range and f3d_range + /// arguments) and domain. Used for all data operations for + /// consistency + template + void loop_vars(RangeF2D f2d_range, RangeF3D f3d_range, BoutReal* udata, + SOLVER_VAR_OP op) { + // Use global mesh: FIX THIS! + const Mesh* mesh = bout::globals::mesh; + + int p = 0; // Counter for location in udata array + + // All boundaries + for (const auto& i2d : mesh->getRegion2D("RGN_BNDRY")) { + loop_vars_op(f2d_range, f3d_range, i2d, udata, p, op, true); + } + + // Bulk of points + for (const auto& i2d : mesh->getRegion2D("RGN_NOBNDRY")) { + loop_vars_op(f2d_range, f3d_range, i2d, udata, p, op, false); + } + } + private: /// Generate a random UUID (version 4) and broadcast it to all processors std::string createRunID() const; @@ -557,6 +726,21 @@ private: std::string run_restart_from = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; /// Save `run_id` and `run_restart_from` every output bool save_repeat_run_id{false}; + /// Write ``jacobian_index_base`` to the dump files for Jacobian diagnostics. + bool save_jacobian_index_base{false}; + /// Has the Jacobian metadata file been written? + bool jacobian_metadata_written{false}; + /// Running counter appended to successive Jacobian saves + int jacobian_export_counter{0}; + /// Prefix for matrix files and ``*_metadata.json`` + std::string jacobian_export_prefix; + /// PETSc ``MatView`` format: binary or ascii + bout::PetscMatrixExportFormat jacobian_export_format; + + /// Return the matrix filename including the extension for the selected format. + std::string getJacobianMatrixFilename(const std::string& jacobian_export_prefix, + bout::JacobianExportKind kind, + bout::PetscMatrixExportFormat format); /// Current iteration (output time-step) number int iteration{0}; @@ -605,9 +789,124 @@ private: /// Should be run after user RHS is called void post_rhs(BoutReal t); - /// Loading data from BOUT++ to/from solver - void loop_vars_op(Ind2D i2d, BoutReal* udata, int& p, SOLVER_VAR_OP op, bool bndry); - void loop_vars(BoutReal* udata, SOLVER_VAR_OP op); + /// Perform an operation at a given Ind2D (jx,jy) location, moving + /// data between BOUT++ and solver. This can be done on arbitrary + /// sets of fields (accessed using f2d_range and f3d_range), provided they + /// are the same number, shape, size, etc. as the fields being + /// solved for. + template + void loop_vars_op(RangeF2D f2d_range, RangeF3D f3d_range, Ind2D i2d, BoutReal* udata, + int& p, SOLVER_VAR_OP op, bool bndry) { + /************************************************************************** + * Looping over variables + * + * NOTE: This part is very inefficient, and should be replaced ASAP + * Is the interleaving of variables needed or helpful to the solver? + **************************************************************************/ + // Use global mesh: FIX THIS! + const Mesh* mesh = bout::globals::mesh; + + const int nz = mesh->LocalNz; + + switch (op) { + case SOLVER_VAR_OP::LOAD: { + /// Load variables from IDA into BOUT++ + + // Loop over 2D variables + auto metadata_it = f2d.begin(); + for (auto& field : f2d_range) { + const auto& metadata = *metadata_it; + ++metadata_it; + if (bndry && !metadata.evolve_bndry) { + continue; + } + field[i2d] = udata[p]; + p++; + } + + for (int jz = 0; jz < nz; jz++) { + + auto metadata_it = f3d.begin(); + // Loop over 3D variables + for (auto& field : f3d_range) { + const auto& metadata = *metadata_it; + ++metadata_it; + if (bndry && !metadata.evolve_bndry) { + continue; + } + field[field.getMesh()->ind2Dto3D(i2d, jz)] = udata[p]; + p++; + } + } + break; + } + case SOLVER_VAR_OP::SET_ID: { + /// Set the type of equation (Differential or Algebraic) + + // Loop over 2D variables + for (const auto& metadata : f2d) { + if (bndry && !metadata.evolve_bndry) { + continue; + } + if (metadata.constraint) { + udata[p] = 0; + } else { + udata[p] = 1; + } + p++; + } + + for (int jz = 0; jz < nz; jz++) { + + // Loop over 3D variables + for (const auto& metadata : f3d) { + if (bndry && !metadata.evolve_bndry) { + continue; + } + if (metadata.constraint) { + udata[p] = 0; + } else { + udata[p] = 1; + } + p++; + } + } + + break; + } + case SOLVER_VAR_OP::SAVE: { + /// Save variables from BOUT++ into IDA (only used at start of simulation) + + // Loop over 2D variables + auto metadata_it = f2d.begin(); + for (const auto& field : f2d_range) { + const auto& metadata = *metadata_it; + ++metadata_it; + if (bndry && !metadata.evolve_bndry) { + continue; + } + udata[p] = field[i2d]; + p++; + } + + for (int jz = 0; jz < nz; jz++) { + + auto metadata_it = f3d.begin(); + // Loop over 3D variables + for (const auto& field : f3d_range) { + const auto& metadata = *metadata_it; + ++metadata_it; + if (bndry && !metadata.evolve_bndry) { + continue; + } + udata[p] = field[field.getMesh()->ind2Dto3D(i2d, jz)]; + p++; + } + } + break; + } + } + } /// Check if a variable has already been added bool varAdded(const std::string& name); diff --git a/include/bout/sundials_backports.hxx b/include/bout/sundials_backports.hxx index 1ab39595ec..bb17e593b2 100644 --- a/include/bout/sundials_backports.hxx +++ b/include/bout/sundials_backports.hxx @@ -32,10 +32,11 @@ // NOLINTBEGIN(cppcoreguidelines-macro-usage) #define SUNDIALS_VERSION_AT_LEAST(major, minor, patch) \ - ((major) < SUNDIALS_VERSION_MAJOR \ - || ((major) == SUNDIALS_VERSION_MAJOR \ - && ((minor) < SUNDIALS_VERSION_MINOR \ - || ((minor) == SUNDIALS_VERSION_MINOR && (patch) <= SUNDIALS_VERSION_PATCH)))) + ((major) < SUNDIALS_VERSION_MAJOR \ + || ((major) == SUNDIALS_VERSION_MAJOR \ + && ((minor) < SUNDIALS_VERSION_MINOR \ + || ((minor) == SUNDIALS_VERSION_MINOR \ + && (patch) <= SUNDIALS_VERSION_PATCH)))) #define SUNDIALS_VERSION_LESS_THAN(major, minor, patch) \ (!SUNDIALS_VERSION_AT_LEAST(major, minor, patch)) // NOLINTEND(cppcoreguidelines-macro-usage) @@ -77,13 +78,13 @@ inline sundials::Context createSUNContext([[maybe_unused]] MPI_Comm& comm) { #endif } -template -inline decltype(auto) callWithSUNContext(Func f, [[maybe_unused]] sundials::Context& ctx, +template +inline decltype(auto) callWithSUNContext(Func f, [[maybe_unused]] Ctx&& ctx, Args&&... args) { #if SUNDIALS_VERSION_LESS_THAN(6, 0, 0) return f(std::forward(args)...); #else - return f(std::forward(args)..., ctx); + return f(std::forward(args)..., std::forward(ctx)); #endif } diff --git a/include/bout/sys/expressionparser.hxx b/include/bout/sys/expressionparser.hxx index 660ad20ab3..f87ee2adbc 100644 --- a/include/bout/sys/expressionparser.hxx +++ b/include/bout/sys/expressionparser.hxx @@ -29,7 +29,8 @@ #include "bout/unused.hxx" -#include "fmt/core.h" +#include +#include #include #include @@ -64,12 +65,6 @@ public: return nullptr; } - [[deprecated("This will be removed in a future version. Implementations should " - "override the Context version of this function.")]] virtual double - generate(BoutReal x, BoutReal y, BoutReal z, BoutReal t) { - return generate(bout::generator::Context().set("x", x, "y", y, "z", z, "t", t)); - } - /// Generate a value at the given coordinates (x,y,z,t) /// This should be deterministic, always returning the same value given the same inputs /// @@ -78,7 +73,7 @@ public: /// them or an infinite recursion results. This is for backward /// compatibility for users and implementors. In a future version /// this function will be made pure virtual. - virtual double generate(const bout::generator::Context& ctx); + virtual double generate(const bout::generator::Context& ctx) = 0; /// Create a string representation of the generator, for debugging output virtual std::string str() const { return std::string("?"); } @@ -136,9 +131,7 @@ protected: /// Edit distance from original search term std::string::size_type distance; /// Comparison operator so this works in a std::multiset - friend bool operator<(const FuzzyMatch& lhs, const FuzzyMatch& rhs) { - return (lhs.distance < rhs.distance) and (lhs.name < rhs.name); - } + auto operator<=>(const FuzzyMatch&) const = default; }; /// Find approximate matches for \p name in the known generators. \p @@ -245,11 +238,16 @@ private: class ParseException : public std::exception { public: + ParseException(const ParseException&) = default; + ParseException(ParseException&&) = delete; + ParseException& operator=(const ParseException&) = default; + ParseException& operator=(ParseException&&) = delete; ParseException(const std::string& message_) : message(message_) {} - template - ParseException(const S& format, const Args&... args) - : message(fmt::format(format, args...)) {} + template + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + ParseException(fmt::format_string format, Args&&... args) + : message(fmt::vformat(format, fmt::make_format_args(args...))) {} ~ParseException() override = default; diff --git a/include/bout/sys/generator_context.hxx b/include/bout/sys/generator_context.hxx index bbe60fab65..080b4d8ed7 100644 --- a/include/bout/sys/generator_context.hxx +++ b/include/bout/sys/generator_context.hxx @@ -24,12 +24,8 @@ public: : Context(i.x(), i.y(), 0, (loc == CELL_ZLOW) ? CELL_CENTRE : loc, msh, t) {} /// Specify a cell index, together with the cell location, mesh and time - /// Context(int ix, int iy, int iz, CELL_LOC loc, Mesh* msh, BoutReal t); - /// Specify the values directly - Context(BoutReal x, BoutReal y, BoutReal z, Mesh* msh, BoutReal t); - /// If constructed without parameters, contains no values (null). /// Requesting x,y,z or t throws an exception Context() = default; @@ -37,13 +33,18 @@ public: /// The location on the boundary Context(const BoundaryRegion* bndry, int iz, CELL_LOC loc, BoutReal t, Mesh* msh); Context(const BoundaryRegion* bndry, CELL_LOC loc, BoutReal t, Mesh* msh) - : Context(bndry, 0, loc, t, msh){}; + : Context(bndry, 0, loc, t, msh) {}; BoutReal x() const { return get("x"); } BoutReal y() const { return get("y"); } BoutReal z() const { return get("z"); } BoutReal t() const { return get("t"); } + /// Cell indices + int ix() const { return ix_; } + int jy() const { return jy_; } + int kz() const { return kz_; } + /// Set the value of a parameter with given name Context& set(const std::string& name, BoutReal value) { parameters[name] = value; @@ -76,6 +77,10 @@ public: } private: + int ix_{0}; + int jy_{0}; + int kz_{0}; + Mesh* localmesh{nullptr}; ///< The mesh on which the position is defined /// Contains user-set values which can be set and retrieved diff --git a/include/bout/sys/gettext.hxx b/include/bout/sys/gettext.hxx index d67becd54d..751f51882e 100644 --- a/include/bout/sys/gettext.hxx +++ b/include/bout/sys/gettext.hxx @@ -1,3 +1,4 @@ +/// \file /// Support for i18n using GNU gettext #ifndef BOUT_GETTEXT_H @@ -7,15 +8,47 @@ #if BOUT_HAS_GETTEXT -#include +#include // IWYU pragma: keep + #include #define GETTEXT_PACKAGE "libbout" -#define _(string) dgettext(GETTEXT_PACKAGE, string) +// If we have C++23, we can get fmt to do compile-time checks of our format +// strings, _and_ have gettext do runtime replacement +#if __cpp_if_consteval >= 202106L +constexpr const char* dgettext_wrap(const char* __domainname, const char* __msgid) __THROW + __attribute_format_arg__(2); + +constexpr const char* dgettext_wrap(const char* __domainname, const char* __msgid) { + if consteval { + return __msgid; + } + return dgettext(__domainname, __msgid); +} + +/// Gettext i18n macro for text containing fmt format specifiers +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define _f(string) dgettext_wrap(GETTEXT_PACKAGE, string) #else +// We're pre-C++23, so all our i18n text must be fmt runtime formats +#include "fmt/base.h" // IWYU pragma: keep + +/// Gettext i18n macro for text containing fmt format specifiers +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define _f(string) fmt::runtime(dgettext(GETTEXT_PACKAGE, string)) +#endif + +/// Gettext i18n macro for plain text that doesn't need formatting +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define _(string) dgettext(GETTEXT_PACKAGE, string) + +#else // BOUT_HAS_GETTEXT +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define _f(string) string +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define _(string) string #endif // BOUT_HAS_GETTEXT diff --git a/include/bout/sys/parallel_stencils.hxx b/include/bout/sys/parallel_stencils.hxx new file mode 100644 index 0000000000..88396005ae --- /dev/null +++ b/include/bout/sys/parallel_stencils.hxx @@ -0,0 +1,34 @@ +#pragma once +#include +#include + +namespace bout::parallel_stencil { +// generated by src/mesh/parallel_boundary_stencil.cxx.py +using std::pow; + +inline BoutReal dirichlet_o1([[maybe_unused]] BoutReal spacing0, BoutReal value0) { + return value0; +} +inline BoutReal dirichlet_o2(BoutReal spacing0, BoutReal value0, BoutReal spacing1, + BoutReal value1) { + return (spacing0 * value1 - spacing1 * value0) / (spacing0 - spacing1); +} +inline BoutReal neumann_o2([[maybe_unused]] BoutReal spacing0, BoutReal value0, + BoutReal spacing1, BoutReal value1) { + return (-spacing1 * value0) + value1; +} +inline BoutReal dirichlet_o3(BoutReal spacing0, BoutReal value0, BoutReal spacing1, + BoutReal value1, BoutReal spacing2, BoutReal value2) { + return (pow(spacing0, 2) * spacing1 * value2 - pow(spacing0, 2) * spacing2 * value1 + - spacing0 * pow(spacing1, 2) * value2 + spacing0 * pow(spacing2, 2) * value1 + + pow(spacing1, 2) * spacing2 * value0 - spacing1 * pow(spacing2, 2) * value0) + / ((spacing0 - spacing1) * (spacing0 - spacing2) * (spacing1 - spacing2)); +} +inline BoutReal neumann_o3(BoutReal spacing0, BoutReal value0, BoutReal spacing1, + BoutReal value1, BoutReal spacing2, BoutReal value2) { + return (2 * spacing0 * spacing1 * value2 - 2 * spacing0 * spacing2 * value1 + + pow(spacing1, 2) * spacing2 * value0 - pow(spacing1, 2) * value2 + - spacing1 * pow(spacing2, 2) * value0 + pow(spacing2, 2) * value1) + / ((spacing1 - spacing2) * (2 * spacing0 - spacing1 - spacing2)); +} +} // namespace bout::parallel_stencil diff --git a/include/bout/sys/timer.hxx b/include/bout/sys/timer.hxx index f3beba27b1..c6a0c9020a 100644 --- a/include/bout/sys/timer.hxx +++ b/include/bout/sys/timer.hxx @@ -7,7 +7,6 @@ #include #include "bout/msg_stack.hxx" -#include "bout/output.hxx" /*! * Timing class for performance benchmarking and diagnosis @@ -133,5 +132,4 @@ public: static void printTimeReport(); }; -#define AUTO_TIME() Timer CONCATENATE(time_, __LINE__)(__thefunc__) #endif // BOUT_TIMER_H diff --git a/include/bout/sys/type_name.hxx b/include/bout/sys/type_name.hxx index be4d096b4d..fcd251bf7a 100644 --- a/include/bout/sys/type_name.hxx +++ b/include/bout/sys/type_name.hxx @@ -4,13 +4,19 @@ #ifndef TYPE_NAME_HXX #define TYPE_NAME_HXX +#include "bout/array.hxx" #include "bout/bout_types.hxx" + #include #include class Field2D; class Field3D; class FieldPerp; +template +class Matrix; +template +class Tensor; namespace bout { namespace utils { @@ -41,6 +47,19 @@ std::string typeName(); template <> std::string typeName(); + +template <> +std::string typeName>(); +template <> +std::string typeName>(); +template <> +std::string typeName>(); +template <> +std::string typeName>(); +template <> +std::string typeName>(); +template <> +std::string typeName>(); } // namespace utils } // namespace bout diff --git a/include/bout/sys/uuid.h b/include/bout/sys/uuid.h index d3d954e2fe..ecc8c0d4e3 100644 --- a/include/bout/sys/uuid.h +++ b/include/bout/sys/uuid.h @@ -1,14 +1,15 @@ -// Based on stduuid by Marius Bancila: https://github.com/mariusbancila/stduuid -// Originially copied from version at commit 5890c94bfac2f00f22a1c1481e5839c51d6a6f3f -// This version hacked by J. Omotani to make it C++14 compatible: -// - remove uses of span -// - brace-initialise std::atomic_short clock_sequence to avoid deleted -// move-constructor error -// - remove use of std::optional. Throw exceptions instead. -// - replace std::bytes with char -// - replace 'if constexpr' with plain 'if' -// - replace 'is_same_v<>' with 'is_same<>::value' -// - replace std::copy with strncpy in uuid_name_generator::reset() +/// Based on stduuid by Marius Bancila: https://github.com/mariusbancila/stduuid +/// +/// Originially copied from version at commit 5890c94bfac2f00f22a1c1481e5839c51d6a6f3f +/// This version hacked by J. Omotani to make it C++14 compatible: +/// - remove uses of span +/// - brace-initialise std::atomic_short clock_sequence to avoid deleted +/// move-constructor error +/// - remove use of std::optional. Throw exceptions instead. +/// - replace std::bytes with char +/// - replace 'if constexpr' with plain 'if' +/// - replace 'is_same_v<>' with 'is_same<>::value' +/// - replace std::copy with strncpy in uuid_name_generator::reset() // // Copyright (c) 2017 // @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +77,7 @@ namespace uuids { namespace detail { template -constexpr inline unsigned char hex2char(TChar const ch) { +constexpr unsigned char hex2char(const TChar ch) { if (ch >= static_cast('0') && ch <= static_cast('9')) return ch - static_cast('0'); if (ch >= static_cast('a') && ch <= static_cast('f')) @@ -86,14 +88,14 @@ constexpr inline unsigned char hex2char(TChar const ch) { } template -constexpr inline bool is_hex(TChar const ch) { +constexpr bool is_hex(const TChar ch) { return (ch >= static_cast('0') && ch <= static_cast('9')) || (ch >= static_cast('a') && ch <= static_cast('f')) || (ch >= static_cast('A') && ch <= static_cast('F')); } template -constexpr inline unsigned char hexpair2char(TChar const a, TChar const b) { +constexpr unsigned char hexpair2char(const TChar a, const TChar b) { return (hex2char(a) << 4) | hex2char(b); } @@ -104,7 +106,7 @@ class sha1 { static constexpr unsigned int block_bytes = 64; - inline static uint32_t left_rotate(uint32_t value, size_t const count) { + static uint32_t left_rotate(uint32_t value, const size_t count) { return (value << count) ^ (value >> (32 - count)); } @@ -129,7 +131,7 @@ class sha1 { } } - void process_block(void const* const start, void const* const end) { + void process_block(const void* const start, const void* const end) { const uint8_t* begin = static_cast(start); const uint8_t* finish = static_cast(end); while (begin != finish) { @@ -138,13 +140,13 @@ class sha1 { } } - void process_bytes(void const* const data, size_t const len) { + void process_bytes(const void* const data, const size_t len) { const uint8_t* block = static_cast(data); process_block(block, block + len); } - uint32_t const* get_digest(digest32_t digest) { - size_t const bitCount = this->m_byteCount * 8; + const uint32_t* get_digest(digest32_t digest) { + const size_t bitCount = this->m_byteCount * 8; process_byte(0x80); if (this->m_blockByteIndex > 56) { while (m_blockByteIndex != 0) { @@ -165,13 +167,13 @@ class sha1 { process_byte(static_cast((bitCount >> 24) & 0xFF)); process_byte(static_cast((bitCount >> 16) & 0xFF)); process_byte(static_cast((bitCount >> 8) & 0xFF)); - process_byte(static_cast((bitCount)&0xFF)); + process_byte(static_cast((bitCount) & 0xFF)); memcpy(digest, m_digest, 5 * sizeof(uint32_t)); return digest; } - uint8_t const* get_digest_bytes(digest8_t digest) { + const uint8_t* get_digest_bytes(digest8_t digest) { digest32_t d32; get_digest(d32); size_t di = 0; @@ -261,7 +263,7 @@ class sha1 { size_t m_byteCount; }; -static std::mt19937 clock_gen(std::random_device{}()); +static std::mt19937 clock_gen{std::random_device{}()}; static std::uniform_int_distribution clock_dis{-32768, 32767}; static std::atomic_short clock_sequence{clock_dis(clock_gen)}; } // namespace detail @@ -343,13 +345,13 @@ class uuid { public: using value_type = uint8_t; - constexpr uuid() noexcept : data({}){}; + constexpr uuid() noexcept : data({}) {}; uuid(value_type (&arr)[16]) noexcept { std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); } - uuid(std::array const& arr) noexcept { + uuid(const std::array& arr) noexcept { std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); } @@ -394,12 +396,10 @@ class uuid { void swap(uuid& other) noexcept { data.swap(other.data); } - inline char const* as_bytes() const { - return reinterpret_cast(data.data()); - } + const char* as_bytes() const { return reinterpret_cast(data.data()); } template - static bool is_valid_uuid(CharT const* str) noexcept { + static bool is_valid_uuid(const CharT* str) noexcept { bool firstDigit = true; int hasBraces = 0; size_t index = 0; @@ -454,12 +454,12 @@ class uuid { template , class Allocator = std::allocator> static bool - is_valid_uuid(std::basic_string const& str) noexcept { + is_valid_uuid(const std::basic_string& str) noexcept { return is_valid_uuid(str.c_str()); } template - static uuid from_string(CharT const* str) noexcept { + static uuid from_string(const CharT* str) noexcept { CharT digit = 0; bool firstDigit = true; int hasBraces = 0; @@ -511,40 +511,40 @@ class uuid { template , class Allocator = std::allocator> static uuid - from_string(std::basic_string const& str) noexcept { + from_string(const std::basic_string& str) noexcept { return from_string(str.c_str()); } private: std::array data{{0}}; - friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; - friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; + friend bool operator==(const uuid& lhs, const uuid& rhs) noexcept; + friend bool operator<(const uuid& lhs, const uuid& rhs) noexcept; template friend std::basic_ostream& operator<<(std::basic_ostream& s, - uuid const& id); + const uuid& id); }; // -------------------------------------------------------------------------------------------------------------------------- // operators and non-member functions // -------------------------------------------------------------------------------------------------------------------------- -inline bool operator==(uuid const& lhs, uuid const& rhs) noexcept { +inline bool operator==(const uuid& lhs, const uuid& rhs) noexcept { return lhs.data == rhs.data; } -inline bool operator!=(uuid const& lhs, uuid const& rhs) noexcept { +inline bool operator!=(const uuid& lhs, const uuid& rhs) noexcept { return !(lhs == rhs); } -inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept { +inline bool operator<(const uuid& lhs, const uuid& rhs) noexcept { return lhs.data < rhs.data; } template std::basic_ostream& operator<<(std::basic_ostream& s, - uuid const& id) { + const uuid& id) { // save current flags std::ios_base::fmtflags f(s.flags()); @@ -567,7 +567,7 @@ std::basic_ostream& operator<<(std::basic_ostream& s template , class Allocator = std::allocator> -inline std::basic_string to_string(uuid const& id) { +inline std::basic_string to_string(const uuid& id) { std::basic_stringstream sstr; sstr << id; return sstr.str(); @@ -691,11 +691,11 @@ using uuid_random_generator = basic_uuid_random_generator; class uuid_name_generator { public: - explicit uuid_name_generator(uuid const& namespace_uuid) noexcept + explicit uuid_name_generator(const uuid& namespace_uuid) noexcept : nsuuid(namespace_uuid) {} template - uuid operator()(CharT const* name) { + uuid operator()(const CharT* name) { size_t size = 0; if (std::is_same::value) size = strlen(name); @@ -709,7 +709,7 @@ class uuid_name_generator { template , class Allocator = std::allocator> - uuid operator()(std::basic_string const& name) { + uuid operator()(const std::basic_string& name) { reset(); process_characters(name.data(), name.size()); return make_uuid(); @@ -726,7 +726,7 @@ class uuid_name_generator { template ::value>> - void process_characters(char_type const* const characters, size_t const count) { + void process_characters(const char_type* const characters, const size_t count) { for (size_t i = 0; i < count; i++) { uint32_t c = characters[i]; hasher.process_byte(static_cast((c >> 0) & 0xFF)); @@ -736,7 +736,7 @@ class uuid_name_generator { } } - void process_characters(const char* const characters, size_t const count) { + void process_characters(const char* const characters, const size_t count) { hasher.process_bytes(characters, count); } @@ -846,7 +846,7 @@ struct hash { using argument_type = uuids::uuid; using result_type = std::size_t; - result_type operator()(argument_type const& uuid) const { + result_type operator()(const argument_type& uuid) const { std::hash hasher; return static_cast(hasher(uuids::to_string(uuid))); } diff --git a/include/bout/sys/variant.hxx b/include/bout/sys/variant.hxx index f47d67e229..1b541f096d 100644 --- a/include/bout/sys/variant.hxx +++ b/include/bout/sys/variant.hxx @@ -1,15 +1,15 @@ -/// +/// \file /// Variant utilities /// /// All in namespace bout::utils -/// variant -/// visit -/// holds_alternative -/// get /// -/// variantEqualTo -/// variantStaticCastOrThrow -/// variantToString +/// - `variant` +/// - `visit` +/// - `holds_alternative` +/// - `get` +/// - `variantEqualTo` +/// - `variantStaticCastOrThrow` +/// - `variantToString` /// /// Internal implementation in bout::utils::details diff --git a/include/bout/tokamak_coordinates.hxx b/include/bout/tokamak_coordinates.hxx new file mode 100644 index 0000000000..4bde1a9a97 --- /dev/null +++ b/include/bout/tokamak_coordinates.hxx @@ -0,0 +1,53 @@ +#ifndef BOUT_TOKAMAK_COORDINATES_HXX +#define BOUT_TOKAMAK_COORDINATES_HXX + +#include +#include +#include +#include + +class Mesh; + +namespace bout { +/// Variables used in the BOUT++ tokamak coordinate system. +/// +/// When created by `set_tokamak_coordinates`, all variables except +/// `I_unnormalised` are normalised. +struct TokamakCoordinates { + /// Major radius + FieldMetric Rxy; + /// Vertical height + FieldMetric Zxy; + /// Poloidal magnetic field + FieldMetric Bpxy; + /// Toroidal magnetic field + FieldMetric Btxy; + /// Total magnetic field + FieldMetric Bxy; + /// Poloidal arc length + FieldMetric hthe; + /// Integrated shear (normalised) + FieldMetric I; + /// Unnormalised integrated shear + FieldMetric I_unnormalised; +}; + +/// Read, normalise, calculate, and set the metric components for a BOUT++ +/// tokamak coordinate system. +/// +/// Sets the cell-centre `Coordinates` on \p mesh +/// +/// @param Lbar Spatial normalisation +/// @param Bbar Magnetic normalisation +/// @param no_shear Don't use integrated shear in coordinate system +/// @param shear_factor Integrated shear normalisation +TokamakCoordinates set_tokamak_coordinates(Mesh& mesh, BoutReal Lbar = 1.0, + BoutReal Bbar = 1.0, bool no_shear = false, + BoutReal shear_factor = 1.0); + +MetricNormaliser TokamakOrFCIMetricNormaliser(const Mesh* mesh, BoutReal Bnorm, + BoutReal rho_s0); + +} // namespace bout + +#endif //BOUT_TOKAMAK_COORDINATES_HXX diff --git a/include/bout/traits.hxx b/include/bout/traits.hxx index 4e03d6b526..5796c65879 100644 --- a/include/bout/traits.hxx +++ b/include/bout/traits.hxx @@ -1,6 +1,7 @@ #ifndef BOUT_TRAITS_H #define BOUT_TRAITS_H +#include #include class Field; @@ -112,6 +113,10 @@ using EnableIfFieldPerp = /// Enable a function if T is a subclass of Options template using EnableIfOptions = std::enable_if_t>; + +/// Create a `std::index_sequence` with the length of a tuple ``T`` +template +using tuple_index_sequence = std::make_index_sequence>; } // namespace utils } // namespace bout diff --git a/include/bout/twiddle.hxx b/include/bout/twiddle.hxx new file mode 100644 index 0000000000..6da72dd8ff --- /dev/null +++ b/include/bout/twiddle.hxx @@ -0,0 +1,1025 @@ +__constant__ double2 c_twiddle_16[16] = { + {1.0000000000000000, -0.0000000000000000}, // k=0 + {0.9238795325112867, -0.3826834323650898}, // k=1 + {0.7071067811865476, -0.7071067811865475}, // k=2 + {0.3826834323650898, -0.9238795325112867}, // k=3 + {0.0000000000000001, -1.0000000000000000}, // k=4 + {-0.3826834323650897, -0.9238795325112867}, // k=5 + {-0.7071067811865475, -0.7071067811865476}, // k=6 + {-0.9238795325112867, -0.3826834323650899}, // k=7 + {-1.0000000000000000, -0.0000000000000001}, // k=8 + {-0.9238795325112868, 0.3826834323650897}, // k=9 + {-0.7071067811865477, 0.7071067811865475}, // k=10 + {-0.3826834323650903, 0.9238795325112865}, // k=11 + {-0.0000000000000002, 1.0000000000000000}, // k=12 + {0.3826834323650900, 0.9238795325112866}, // k=13 + {0.7071067811865474, 0.7071067811865477}, // k=14 + {0.9238795325112865, 0.3826834323650904}, // k=15 +}; + +__constant__ double2 c_twiddle_32[32] = { + {1.0000000000000000, -0.0000000000000000}, // k=0 + {0.9807852804032304, -0.1950903220161282}, // k=1 + {0.9238795325112867, -0.3826834323650898}, // k=2 + {0.8314696123025452, -0.5555702330196022}, // k=3 + {0.7071067811865476, -0.7071067811865475}, // k=4 + {0.5555702330196023, -0.8314696123025452}, // k=5 + {0.3826834323650898, -0.9238795325112867}, // k=6 + {0.1950903220161283, -0.9807852804032304}, // k=7 + {0.0000000000000001, -1.0000000000000000}, // k=8 + {-0.1950903220161282, -0.9807852804032304}, // k=9 + {-0.3826834323650897, -0.9238795325112867}, // k=10 + {-0.5555702330196020, -0.8314696123025455}, // k=11 + {-0.7071067811865475, -0.7071067811865476}, // k=12 + {-0.8314696123025453, -0.5555702330196022}, // k=13 + {-0.9238795325112867, -0.3826834323650899}, // k=14 + {-0.9807852804032304, -0.1950903220161286}, // k=15 + {-1.0000000000000000, -0.0000000000000001}, // k=16 + {-0.9807852804032304, 0.1950903220161284}, // k=17 + {-0.9238795325112868, 0.3826834323650897}, // k=18 + {-0.8314696123025455, 0.5555702330196020}, // k=19 + {-0.7071067811865477, 0.7071067811865475}, // k=20 + {-0.5555702330196022, 0.8314696123025452}, // k=21 + {-0.3826834323650903, 0.9238795325112865}, // k=22 + {-0.1950903220161287, 0.9807852804032303}, // k=23 + {-0.0000000000000002, 1.0000000000000000}, // k=24 + {0.1950903220161283, 0.9807852804032304}, // k=25 + {0.3826834323650900, 0.9238795325112866}, // k=26 + {0.5555702330196018, 0.8314696123025455}, // k=27 + {0.7071067811865474, 0.7071067811865477}, // k=28 + {0.8314696123025452, 0.5555702330196022}, // k=29 + {0.9238795325112865, 0.3826834323650904}, // k=30 + {0.9807852804032303, 0.1950903220161287}, // k=31 +}; + +__constant__ double2 c_twiddle_64[64] = { + {1.0000000000000000, -0.0000000000000000}, // k=0 + {0.9951847266721969, -0.0980171403295606}, // k=1 + {0.9807852804032304, -0.1950903220161282}, // k=2 + {0.9569403357322088, -0.2902846772544623}, // k=3 + {0.9238795325112867, -0.3826834323650898}, // k=4 + {0.8819212643483550, -0.4713967368259976}, // k=5 + {0.8314696123025452, -0.5555702330196022}, // k=6 + {0.7730104533627370, -0.6343932841636455}, // k=7 + {0.7071067811865476, -0.7071067811865475}, // k=8 + {0.6343932841636455, -0.7730104533627370}, // k=9 + {0.5555702330196023, -0.8314696123025452}, // k=10 + {0.4713967368259978, -0.8819212643483549}, // k=11 + {0.3826834323650898, -0.9238795325112867}, // k=12 + {0.2902846772544623, -0.9569403357322089}, // k=13 + {0.1950903220161283, -0.9807852804032304}, // k=14 + {0.0980171403295608, -0.9951847266721968}, // k=15 + {0.0000000000000001, -1.0000000000000000}, // k=16 + {-0.0980171403295606, -0.9951847266721969}, // k=17 + {-0.1950903220161282, -0.9807852804032304}, // k=18 + {-0.2902846772544622, -0.9569403357322089}, // k=19 + {-0.3826834323650897, -0.9238795325112867}, // k=20 + {-0.4713967368259977, -0.8819212643483550}, // k=21 + {-0.5555702330196020, -0.8314696123025455}, // k=22 + {-0.6343932841636454, -0.7730104533627371}, // k=23 + {-0.7071067811865475, -0.7071067811865476}, // k=24 + {-0.7730104533627370, -0.6343932841636455}, // k=25 + {-0.8314696123025453, -0.5555702330196022}, // k=26 + {-0.8819212643483549, -0.4713967368259979}, // k=27 + {-0.9238795325112867, -0.3826834323650899}, // k=28 + {-0.9569403357322088, -0.2902846772544624}, // k=29 + {-0.9807852804032304, -0.1950903220161286}, // k=30 + {-0.9951847266721968, -0.0980171403295608}, // k=31 + {-1.0000000000000000, -0.0000000000000001}, // k=32 + {-0.9951847266721969, 0.0980171403295606}, // k=33 + {-0.9807852804032304, 0.1950903220161284}, // k=34 + {-0.9569403357322089, 0.2902846772544621}, // k=35 + {-0.9238795325112868, 0.3826834323650897}, // k=36 + {-0.8819212643483550, 0.4713967368259976}, // k=37 + {-0.8314696123025455, 0.5555702330196020}, // k=38 + {-0.7730104533627371, 0.6343932841636453}, // k=39 + {-0.7071067811865477, 0.7071067811865475}, // k=40 + {-0.6343932841636459, 0.7730104533627367}, // k=41 + {-0.5555702330196022, 0.8314696123025452}, // k=42 + {-0.4713967368259979, 0.8819212643483549}, // k=43 + {-0.3826834323650903, 0.9238795325112865}, // k=44 + {-0.2902846772544624, 0.9569403357322088}, // k=45 + {-0.1950903220161287, 0.9807852804032303}, // k=46 + {-0.0980171403295605, 0.9951847266721969}, // k=47 + {-0.0000000000000002, 1.0000000000000000}, // k=48 + {0.0980171403295601, 0.9951847266721969}, // k=49 + {0.1950903220161283, 0.9807852804032304}, // k=50 + {0.2902846772544621, 0.9569403357322089}, // k=51 + {0.3826834323650900, 0.9238795325112866}, // k=52 + {0.4713967368259976, 0.8819212643483550}, // k=53 + {0.5555702330196018, 0.8314696123025455}, // k=54 + {0.6343932841636456, 0.7730104533627369}, // k=55 + {0.7071067811865474, 0.7071067811865477}, // k=56 + {0.7730104533627367, 0.6343932841636459}, // k=57 + {0.8314696123025452, 0.5555702330196022}, // k=58 + {0.8819212643483548, 0.4713967368259979}, // k=59 + {0.9238795325112865, 0.3826834323650904}, // k=60 + {0.9569403357322088, 0.2902846772544625}, // k=61 + {0.9807852804032303, 0.1950903220161287}, // k=62 + {0.9951847266721969, 0.0980171403295605}, // k=63 +}; + +__constant__ double2 c_twiddle_128[128] = { + {1.0000000000000000, -0.0000000000000000}, // k=0 + {0.9987954562051724, -0.0490676743274180}, // k=1 + {0.9951847266721969, -0.0980171403295606}, // k=2 + {0.9891765099647810, -0.1467304744553617}, // k=3 + {0.9807852804032304, -0.1950903220161282}, // k=4 + {0.9700312531945440, -0.2429801799032639}, // k=5 + {0.9569403357322088, -0.2902846772544623}, // k=6 + {0.9415440651830208, -0.3368898533922201}, // k=7 + {0.9238795325112867, -0.3826834323650898}, // k=8 + {0.9039892931234433, -0.4275550934302821}, // k=9 + {0.8819212643483550, -0.4713967368259976}, // k=10 + {0.8577286100002721, -0.5141027441932217}, // k=11 + {0.8314696123025452, -0.5555702330196022}, // k=12 + {0.8032075314806449, -0.5956993044924334}, // k=13 + {0.7730104533627370, -0.6343932841636455}, // k=14 + {0.7409511253549591, -0.6715589548470183}, // k=15 + {0.7071067811865476, -0.7071067811865475}, // k=16 + {0.6715589548470183, -0.7409511253549591}, // k=17 + {0.6343932841636455, -0.7730104533627370}, // k=18 + {0.5956993044924335, -0.8032075314806448}, // k=19 + {0.5555702330196023, -0.8314696123025452}, // k=20 + {0.5141027441932217, -0.8577286100002721}, // k=21 + {0.4713967368259978, -0.8819212643483549}, // k=22 + {0.4275550934302822, -0.9039892931234433}, // k=23 + {0.3826834323650898, -0.9238795325112867}, // k=24 + {0.3368898533922201, -0.9415440651830208}, // k=25 + {0.2902846772544623, -0.9569403357322089}, // k=26 + {0.2429801799032640, -0.9700312531945440}, // k=27 + {0.1950903220161283, -0.9807852804032304}, // k=28 + {0.1467304744553617, -0.9891765099647810}, // k=29 + {0.0980171403295608, -0.9951847266721968}, // k=30 + {0.0490676743274181, -0.9987954562051724}, // k=31 + {0.0000000000000001, -1.0000000000000000}, // k=32 + {-0.0490676743274180, -0.9987954562051724}, // k=33 + {-0.0980171403295606, -0.9951847266721969}, // k=34 + {-0.1467304744553616, -0.9891765099647810}, // k=35 + {-0.1950903220161282, -0.9807852804032304}, // k=36 + {-0.2429801799032639, -0.9700312531945440}, // k=37 + {-0.2902846772544622, -0.9569403357322089}, // k=38 + {-0.3368898533922199, -0.9415440651830208}, // k=39 + {-0.3826834323650897, -0.9238795325112867}, // k=40 + {-0.4275550934302819, -0.9039892931234434}, // k=41 + {-0.4713967368259977, -0.8819212643483550}, // k=42 + {-0.5141027441932217, -0.8577286100002721}, // k=43 + {-0.5555702330196020, -0.8314696123025455}, // k=44 + {-0.5956993044924334, -0.8032075314806449}, // k=45 + {-0.6343932841636454, -0.7730104533627371}, // k=46 + {-0.6715589548470184, -0.7409511253549590}, // k=47 + {-0.7071067811865475, -0.7071067811865476}, // k=48 + {-0.7409511253549589, -0.6715589548470186}, // k=49 + {-0.7730104533627370, -0.6343932841636455}, // k=50 + {-0.8032075314806448, -0.5956993044924335}, // k=51 + {-0.8314696123025453, -0.5555702330196022}, // k=52 + {-0.8577286100002720, -0.5141027441932218}, // k=53 + {-0.8819212643483549, -0.4713967368259979}, // k=54 + {-0.9039892931234433, -0.4275550934302820}, // k=55 + {-0.9238795325112867, -0.3826834323650899}, // k=56 + {-0.9415440651830207, -0.3368898533922203}, // k=57 + {-0.9569403357322088, -0.2902846772544624}, // k=58 + {-0.9700312531945440, -0.2429801799032641}, // k=59 + {-0.9807852804032304, -0.1950903220161286}, // k=60 + {-0.9891765099647810, -0.1467304744553618}, // k=61 + {-0.9951847266721968, -0.0980171403295608}, // k=62 + {-0.9987954562051724, -0.0490676743274180}, // k=63 + {-1.0000000000000000, -0.0000000000000001}, // k=64 + {-0.9987954562051724, 0.0490676743274177}, // k=65 + {-0.9951847266721969, 0.0980171403295606}, // k=66 + {-0.9891765099647810, 0.1467304744553616}, // k=67 + {-0.9807852804032304, 0.1950903220161284}, // k=68 + {-0.9700312531945440, 0.2429801799032638}, // k=69 + {-0.9569403357322089, 0.2902846772544621}, // k=70 + {-0.9415440651830208, 0.3368898533922201}, // k=71 + {-0.9238795325112868, 0.3826834323650897}, // k=72 + {-0.9039892931234434, 0.4275550934302818}, // k=73 + {-0.8819212643483550, 0.4713967368259976}, // k=74 + {-0.8577286100002721, 0.5141027441932216}, // k=75 + {-0.8314696123025455, 0.5555702330196020}, // k=76 + {-0.8032075314806449, 0.5956993044924332}, // k=77 + {-0.7730104533627371, 0.6343932841636453}, // k=78 + {-0.7409511253549591, 0.6715589548470184}, // k=79 + {-0.7071067811865477, 0.7071067811865475}, // k=80 + {-0.6715589548470187, 0.7409511253549589}, // k=81 + {-0.6343932841636459, 0.7730104533627367}, // k=82 + {-0.5956993044924331, 0.8032075314806451}, // k=83 + {-0.5555702330196022, 0.8314696123025452}, // k=84 + {-0.5141027441932218, 0.8577286100002720}, // k=85 + {-0.4713967368259979, 0.8819212643483549}, // k=86 + {-0.4275550934302825, 0.9039892931234431}, // k=87 + {-0.3826834323650903, 0.9238795325112865}, // k=88 + {-0.3368898533922199, 0.9415440651830208}, // k=89 + {-0.2902846772544624, 0.9569403357322088}, // k=90 + {-0.2429801799032641, 0.9700312531945440}, // k=91 + {-0.1950903220161287, 0.9807852804032303}, // k=92 + {-0.1467304744553623, 0.9891765099647809}, // k=93 + {-0.0980171403295605, 0.9951847266721969}, // k=94 + {-0.0490676743274180, 0.9987954562051724}, // k=95 + {-0.0000000000000002, 1.0000000000000000}, // k=96 + {0.0490676743274177, 0.9987954562051724}, // k=97 + {0.0980171403295601, 0.9951847266721969}, // k=98 + {0.1467304744553619, 0.9891765099647809}, // k=99 + {0.1950903220161283, 0.9807852804032304}, // k=100 + {0.2429801799032638, 0.9700312531945440}, // k=101 + {0.2902846772544621, 0.9569403357322089}, // k=102 + {0.3368898533922196, 0.9415440651830209}, // k=103 + {0.3826834323650900, 0.9238795325112866}, // k=104 + {0.4275550934302821, 0.9039892931234433}, // k=105 + {0.4713967368259976, 0.8819212643483550}, // k=106 + {0.5141027441932216, 0.8577286100002722}, // k=107 + {0.5555702330196018, 0.8314696123025455}, // k=108 + {0.5956993044924329, 0.8032075314806453}, // k=109 + {0.6343932841636456, 0.7730104533627369}, // k=110 + {0.6715589548470183, 0.7409511253549591}, // k=111 + {0.7071067811865474, 0.7071067811865477}, // k=112 + {0.7409511253549589, 0.6715589548470187}, // k=113 + {0.7730104533627367, 0.6343932841636459}, // k=114 + {0.8032075314806451, 0.5956993044924332}, // k=115 + {0.8314696123025452, 0.5555702330196022}, // k=116 + {0.8577286100002720, 0.5141027441932219}, // k=117 + {0.8819212643483548, 0.4713967368259979}, // k=118 + {0.9039892931234431, 0.4275550934302825}, // k=119 + {0.9238795325112865, 0.3826834323650904}, // k=120 + {0.9415440651830208, 0.3368898533922200}, // k=121 + {0.9569403357322088, 0.2902846772544625}, // k=122 + {0.9700312531945440, 0.2429801799032642}, // k=123 + {0.9807852804032303, 0.1950903220161287}, // k=124 + {0.9891765099647809, 0.1467304744553624}, // k=125 + {0.9951847266721969, 0.0980171403295605}, // k=126 + {0.9987954562051724, 0.0490676743274181}, // k=127 +}; + +__constant__ double2 c_twiddle_256[256] = { + {1.0000000000000000, -0.0000000000000000}, // k=0 + {0.9996988186962042, -0.0245412285229123}, // k=1 + {0.9987954562051724, -0.0490676743274180}, // k=2 + {0.9972904566786902, -0.0735645635996674}, // k=3 + {0.9951847266721969, -0.0980171403295606}, // k=4 + {0.9924795345987100, -0.1224106751992162}, // k=5 + {0.9891765099647810, -0.1467304744553617}, // k=6 + {0.9852776423889412, -0.1709618887603012}, // k=7 + {0.9807852804032304, -0.1950903220161282}, // k=8 + {0.9757021300385286, -0.2191012401568698}, // k=9 + {0.9700312531945440, -0.2429801799032639}, // k=10 + {0.9637760657954398, -0.2667127574748984}, // k=11 + {0.9569403357322088, -0.2902846772544623}, // k=12 + {0.9495281805930367, -0.3136817403988915}, // k=13 + {0.9415440651830208, -0.3368898533922201}, // k=14 + {0.9329927988347390, -0.3598950365349881}, // k=15 + {0.9238795325112867, -0.3826834323650898}, // k=16 + {0.9142097557035307, -0.4052413140049899}, // k=17 + {0.9039892931234433, -0.4275550934302821}, // k=18 + {0.8932243011955153, -0.4496113296546065}, // k=19 + {0.8819212643483550, -0.4713967368259976}, // k=20 + {0.8700869911087115, -0.4928981922297840}, // k=21 + {0.8577286100002721, -0.5141027441932217}, // k=22 + {0.8448535652497071, -0.5349976198870972}, // k=23 + {0.8314696123025452, -0.5555702330196022}, // k=24 + {0.8175848131515837, -0.5758081914178453}, // k=25 + {0.8032075314806449, -0.5956993044924334}, // k=26 + {0.7883464276266063, -0.6152315905806268}, // k=27 + {0.7730104533627370, -0.6343932841636455}, // k=28 + {0.7572088465064846, -0.6531728429537768}, // k=29 + {0.7409511253549591, -0.6715589548470183}, // k=30 + {0.7242470829514670, -0.6895405447370668}, // k=31 + {0.7071067811865476, -0.7071067811865475}, // k=32 + {0.6895405447370669, -0.7242470829514669}, // k=33 + {0.6715589548470183, -0.7409511253549591}, // k=34 + {0.6531728429537768, -0.7572088465064845}, // k=35 + {0.6343932841636455, -0.7730104533627370}, // k=36 + {0.6152315905806268, -0.7883464276266062}, // k=37 + {0.5956993044924335, -0.8032075314806448}, // k=38 + {0.5758081914178453, -0.8175848131515837}, // k=39 + {0.5555702330196023, -0.8314696123025452}, // k=40 + {0.5349976198870973, -0.8448535652497070}, // k=41 + {0.5141027441932217, -0.8577286100002721}, // k=42 + {0.4928981922297841, -0.8700869911087113}, // k=43 + {0.4713967368259978, -0.8819212643483549}, // k=44 + {0.4496113296546066, -0.8932243011955153}, // k=45 + {0.4275550934302822, -0.9039892931234433}, // k=46 + {0.4052413140049899, -0.9142097557035307}, // k=47 + {0.3826834323650898, -0.9238795325112867}, // k=48 + {0.3598950365349883, -0.9329927988347388}, // k=49 + {0.3368898533922201, -0.9415440651830208}, // k=50 + {0.3136817403988916, -0.9495281805930367}, // k=51 + {0.2902846772544623, -0.9569403357322089}, // k=52 + {0.2667127574748984, -0.9637760657954398}, // k=53 + {0.2429801799032640, -0.9700312531945440}, // k=54 + {0.2191012401568698, -0.9757021300385286}, // k=55 + {0.1950903220161283, -0.9807852804032304}, // k=56 + {0.1709618887603014, -0.9852776423889412}, // k=57 + {0.1467304744553617, -0.9891765099647810}, // k=58 + {0.1224106751992163, -0.9924795345987100}, // k=59 + {0.0980171403295608, -0.9951847266721968}, // k=60 + {0.0735645635996675, -0.9972904566786902}, // k=61 + {0.0490676743274181, -0.9987954562051724}, // k=62 + {0.0245412285229123, -0.9996988186962042}, // k=63 + {0.0000000000000001, -1.0000000000000000}, // k=64 + {-0.0245412285229121, -0.9996988186962042}, // k=65 + {-0.0490676743274180, -0.9987954562051724}, // k=66 + {-0.0735645635996673, -0.9972904566786902}, // k=67 + {-0.0980171403295606, -0.9951847266721969}, // k=68 + {-0.1224106751992162, -0.9924795345987100}, // k=69 + {-0.1467304744553616, -0.9891765099647810}, // k=70 + {-0.1709618887603012, -0.9852776423889412}, // k=71 + {-0.1950903220161282, -0.9807852804032304}, // k=72 + {-0.2191012401568697, -0.9757021300385286}, // k=73 + {-0.2429801799032639, -0.9700312531945440}, // k=74 + {-0.2667127574748983, -0.9637760657954398}, // k=75 + {-0.2902846772544622, -0.9569403357322089}, // k=76 + {-0.3136817403988914, -0.9495281805930367}, // k=77 + {-0.3368898533922199, -0.9415440651830208}, // k=78 + {-0.3598950365349882, -0.9329927988347388}, // k=79 + {-0.3826834323650897, -0.9238795325112867}, // k=80 + {-0.4052413140049897, -0.9142097557035307}, // k=81 + {-0.4275550934302819, -0.9039892931234434}, // k=82 + {-0.4496113296546067, -0.8932243011955152}, // k=83 + {-0.4713967368259977, -0.8819212643483550}, // k=84 + {-0.4928981922297840, -0.8700869911087115}, // k=85 + {-0.5141027441932217, -0.8577286100002721}, // k=86 + {-0.5349976198870970, -0.8448535652497072}, // k=87 + {-0.5555702330196020, -0.8314696123025455}, // k=88 + {-0.5758081914178453, -0.8175848131515837}, // k=89 + {-0.5956993044924334, -0.8032075314806449}, // k=90 + {-0.6152315905806267, -0.7883464276266063}, // k=91 + {-0.6343932841636454, -0.7730104533627371}, // k=92 + {-0.6531728429537765, -0.7572088465064847}, // k=93 + {-0.6715589548470184, -0.7409511253549590}, // k=94 + {-0.6895405447370669, -0.7242470829514669}, // k=95 + {-0.7071067811865475, -0.7071067811865476}, // k=96 + {-0.7242470829514668, -0.6895405447370671}, // k=97 + {-0.7409511253549589, -0.6715589548470186}, // k=98 + {-0.7572088465064846, -0.6531728429537766}, // k=99 + {-0.7730104533627370, -0.6343932841636455}, // k=100 + {-0.7883464276266062, -0.6152315905806269}, // k=101 + {-0.8032075314806448, -0.5956993044924335}, // k=102 + {-0.8175848131515836, -0.5758081914178454}, // k=103 + {-0.8314696123025453, -0.5555702330196022}, // k=104 + {-0.8448535652497071, -0.5349976198870972}, // k=105 + {-0.8577286100002720, -0.5141027441932218}, // k=106 + {-0.8700869911087113, -0.4928981922297841}, // k=107 + {-0.8819212643483549, -0.4713967368259979}, // k=108 + {-0.8932243011955152, -0.4496113296546069}, // k=109 + {-0.9039892931234433, -0.4275550934302820}, // k=110 + {-0.9142097557035307, -0.4052413140049899}, // k=111 + {-0.9238795325112867, -0.3826834323650899}, // k=112 + {-0.9329927988347388, -0.3598950365349883}, // k=113 + {-0.9415440651830207, -0.3368898533922203}, // k=114 + {-0.9495281805930367, -0.3136817403988914}, // k=115 + {-0.9569403357322088, -0.2902846772544624}, // k=116 + {-0.9637760657954398, -0.2667127574748985}, // k=117 + {-0.9700312531945440, -0.2429801799032641}, // k=118 + {-0.9757021300385285, -0.2191012401568700}, // k=119 + {-0.9807852804032304, -0.1950903220161286}, // k=120 + {-0.9852776423889412, -0.1709618887603012}, // k=121 + {-0.9891765099647810, -0.1467304744553618}, // k=122 + {-0.9924795345987100, -0.1224106751992163}, // k=123 + {-0.9951847266721968, -0.0980171403295608}, // k=124 + {-0.9972904566786902, -0.0735645635996677}, // k=125 + {-0.9987954562051724, -0.0490676743274180}, // k=126 + {-0.9996988186962042, -0.0245412285229123}, // k=127 + {-1.0000000000000000, -0.0000000000000001}, // k=128 + {-0.9996988186962042, 0.0245412285229121}, // k=129 + {-0.9987954562051724, 0.0490676743274177}, // k=130 + {-0.9972904566786902, 0.0735645635996675}, // k=131 + {-0.9951847266721969, 0.0980171403295606}, // k=132 + {-0.9924795345987100, 0.1224106751992161}, // k=133 + {-0.9891765099647810, 0.1467304744553616}, // k=134 + {-0.9852776423889413, 0.1709618887603010}, // k=135 + {-0.9807852804032304, 0.1950903220161284}, // k=136 + {-0.9757021300385286, 0.2191012401568698}, // k=137 + {-0.9700312531945440, 0.2429801799032638}, // k=138 + {-0.9637760657954400, 0.2667127574748983}, // k=139 + {-0.9569403357322089, 0.2902846772544621}, // k=140 + {-0.9495281805930368, 0.3136817403988912}, // k=141 + {-0.9415440651830208, 0.3368898533922201}, // k=142 + {-0.9329927988347390, 0.3598950365349881}, // k=143 + {-0.9238795325112868, 0.3826834323650897}, // k=144 + {-0.9142097557035307, 0.4052413140049897}, // k=145 + {-0.9039892931234434, 0.4275550934302818}, // k=146 + {-0.8932243011955153, 0.4496113296546067}, // k=147 + {-0.8819212643483550, 0.4713967368259976}, // k=148 + {-0.8700869911087115, 0.4928981922297839}, // k=149 + {-0.8577286100002721, 0.5141027441932216}, // k=150 + {-0.8448535652497072, 0.5349976198870969}, // k=151 + {-0.8314696123025455, 0.5555702330196020}, // k=152 + {-0.8175848131515837, 0.5758081914178453}, // k=153 + {-0.8032075314806449, 0.5956993044924332}, // k=154 + {-0.7883464276266063, 0.6152315905806267}, // k=155 + {-0.7730104533627371, 0.6343932841636453}, // k=156 + {-0.7572088465064848, 0.6531728429537765}, // k=157 + {-0.7409511253549591, 0.6715589548470184}, // k=158 + {-0.7242470829514670, 0.6895405447370668}, // k=159 + {-0.7071067811865477, 0.7071067811865475}, // k=160 + {-0.6895405447370671, 0.7242470829514668}, // k=161 + {-0.6715589548470187, 0.7409511253549589}, // k=162 + {-0.6531728429537771, 0.7572088465064842}, // k=163 + {-0.6343932841636459, 0.7730104533627367}, // k=164 + {-0.6152315905806273, 0.7883464276266059}, // k=165 + {-0.5956993044924331, 0.8032075314806451}, // k=166 + {-0.5758081914178452, 0.8175848131515838}, // k=167 + {-0.5555702330196022, 0.8314696123025452}, // k=168 + {-0.5349976198870973, 0.8448535652497070}, // k=169 + {-0.5141027441932218, 0.8577286100002720}, // k=170 + {-0.4928981922297842, 0.8700869911087113}, // k=171 + {-0.4713967368259979, 0.8819212643483549}, // k=172 + {-0.4496113296546069, 0.8932243011955152}, // k=173 + {-0.4275550934302825, 0.9039892931234431}, // k=174 + {-0.4052413140049904, 0.9142097557035305}, // k=175 + {-0.3826834323650903, 0.9238795325112865}, // k=176 + {-0.3598950365349879, 0.9329927988347390}, // k=177 + {-0.3368898533922199, 0.9415440651830208}, // k=178 + {-0.3136817403988915, 0.9495281805930367}, // k=179 + {-0.2902846772544624, 0.9569403357322088}, // k=180 + {-0.2667127574748985, 0.9637760657954398}, // k=181 + {-0.2429801799032641, 0.9700312531945440}, // k=182 + {-0.2191012401568701, 0.9757021300385285}, // k=183 + {-0.1950903220161287, 0.9807852804032303}, // k=184 + {-0.1709618887603017, 0.9852776423889411}, // k=185 + {-0.1467304744553623, 0.9891765099647809}, // k=186 + {-0.1224106751992160, 0.9924795345987101}, // k=187 + {-0.0980171403295605, 0.9951847266721969}, // k=188 + {-0.0735645635996674, 0.9972904566786902}, // k=189 + {-0.0490676743274180, 0.9987954562051724}, // k=190 + {-0.0245412285229124, 0.9996988186962042}, // k=191 + {-0.0000000000000002, 1.0000000000000000}, // k=192 + {0.0245412285229120, 0.9996988186962042}, // k=193 + {0.0490676743274177, 0.9987954562051724}, // k=194 + {0.0735645635996670, 0.9972904566786902}, // k=195 + {0.0980171403295601, 0.9951847266721969}, // k=196 + {0.1224106751992156, 0.9924795345987101}, // k=197 + {0.1467304744553619, 0.9891765099647809}, // k=198 + {0.1709618887603013, 0.9852776423889412}, // k=199 + {0.1950903220161283, 0.9807852804032304}, // k=200 + {0.2191012401568697, 0.9757021300385286}, // k=201 + {0.2429801799032638, 0.9700312531945440}, // k=202 + {0.2667127574748982, 0.9637760657954400}, // k=203 + {0.2902846772544621, 0.9569403357322089}, // k=204 + {0.3136817403988911, 0.9495281805930368}, // k=205 + {0.3368898533922196, 0.9415440651830209}, // k=206 + {0.3598950365349876, 0.9329927988347391}, // k=207 + {0.3826834323650900, 0.9238795325112866}, // k=208 + {0.4052413140049900, 0.9142097557035306}, // k=209 + {0.4275550934302821, 0.9039892931234433}, // k=210 + {0.4496113296546066, 0.8932243011955153}, // k=211 + {0.4713967368259976, 0.8819212643483550}, // k=212 + {0.4928981922297839, 0.8700869911087115}, // k=213 + {0.5141027441932216, 0.8577286100002722}, // k=214 + {0.5349976198870969, 0.8448535652497072}, // k=215 + {0.5555702330196018, 0.8314696123025455}, // k=216 + {0.5758081914178449, 0.8175848131515840}, // k=217 + {0.5956993044924329, 0.8032075314806453}, // k=218 + {0.6152315905806270, 0.7883464276266061}, // k=219 + {0.6343932841636456, 0.7730104533627369}, // k=220 + {0.6531728429537768, 0.7572088465064846}, // k=221 + {0.6715589548470183, 0.7409511253549591}, // k=222 + {0.6895405447370668, 0.7242470829514670}, // k=223 + {0.7071067811865474, 0.7071067811865477}, // k=224 + {0.7242470829514667, 0.6895405447370672}, // k=225 + {0.7409511253549589, 0.6715589548470187}, // k=226 + {0.7572088465064842, 0.6531728429537771}, // k=227 + {0.7730104533627367, 0.6343932841636459}, // k=228 + {0.7883464276266059, 0.6152315905806274}, // k=229 + {0.8032075314806451, 0.5956993044924332}, // k=230 + {0.8175848131515837, 0.5758081914178452}, // k=231 + {0.8314696123025452, 0.5555702330196022}, // k=232 + {0.8448535652497070, 0.5349976198870973}, // k=233 + {0.8577286100002720, 0.5141027441932219}, // k=234 + {0.8700869911087113, 0.4928981922297843}, // k=235 + {0.8819212643483548, 0.4713967368259979}, // k=236 + {0.8932243011955151, 0.4496113296546070}, // k=237 + {0.9039892931234431, 0.4275550934302825}, // k=238 + {0.9142097557035305, 0.4052413140049904}, // k=239 + {0.9238795325112865, 0.3826834323650904}, // k=240 + {0.9329927988347390, 0.3598950365349880}, // k=241 + {0.9415440651830208, 0.3368898533922200}, // k=242 + {0.9495281805930367, 0.3136817403988915}, // k=243 + {0.9569403357322088, 0.2902846772544625}, // k=244 + {0.9637760657954398, 0.2667127574748986}, // k=245 + {0.9700312531945440, 0.2429801799032642}, // k=246 + {0.9757021300385285, 0.2191012401568702}, // k=247 + {0.9807852804032303, 0.1950903220161287}, // k=248 + {0.9852776423889411, 0.1709618887603018}, // k=249 + {0.9891765099647809, 0.1467304744553624}, // k=250 + {0.9924795345987100, 0.1224106751992160}, // k=251 + {0.9951847266721969, 0.0980171403295605}, // k=252 + {0.9972904566786902, 0.0735645635996674}, // k=253 + {0.9987954562051724, 0.0490676743274181}, // k=254 + {0.9996988186962042, 0.0245412285229124}, // k=255 +}; + +__constant__ double2 c_twiddle_512[512] = { + {1.0000000000000000, -0.0000000000000000}, // k=0 + {0.9999247018391445, -0.0122715382857199}, // k=1 + {0.9996988186962042, -0.0245412285229123}, // k=2 + {0.9993223845883495, -0.0368072229413588}, // k=3 + {0.9987954562051724, -0.0490676743274180}, // k=4 + {0.9981181129001492, -0.0613207363022086}, // k=5 + {0.9972904566786902, -0.0735645635996674}, // k=6 + {0.9963126121827780, -0.0857973123444399}, // k=7 + {0.9951847266721969, -0.0980171403295606}, // k=8 + {0.9939069700023561, -0.1102222072938831}, // k=9 + {0.9924795345987100, -0.1224106751992162}, // k=10 + {0.9909026354277800, -0.1345807085071262}, // k=11 + {0.9891765099647810, -0.1467304744553617}, // k=12 + {0.9873014181578584, -0.1588581433338614}, // k=13 + {0.9852776423889412, -0.1709618887603012}, // k=14 + {0.9831054874312163, -0.1830398879551410}, // k=15 + {0.9807852804032304, -0.1950903220161282}, // k=16 + {0.9783173707196277, -0.2071113761922186}, // k=17 + {0.9757021300385286, -0.2191012401568698}, // k=18 + {0.9729399522055602, -0.2310581082806711}, // k=19 + {0.9700312531945440, -0.2429801799032639}, // k=20 + {0.9669764710448521, -0.2548656596045146}, // k=21 + {0.9637760657954398, -0.2667127574748984}, // k=22 + {0.9604305194155658, -0.2785196893850531}, // k=23 + {0.9569403357322088, -0.2902846772544623}, // k=24 + {0.9533060403541939, -0.3020059493192281}, // k=25 + {0.9495281805930367, -0.3136817403988915}, // k=26 + {0.9456073253805213, -0.3253102921622629}, // k=27 + {0.9415440651830208, -0.3368898533922201}, // k=28 + {0.9373390119125750, -0.3484186802494346}, // k=29 + {0.9329927988347390, -0.3598950365349881}, // k=30 + {0.9285060804732156, -0.3713171939518375}, // k=31 + {0.9238795325112867, -0.3826834323650898}, // k=32 + {0.9191138516900578, -0.3939920400610481}, // k=33 + {0.9142097557035307, -0.4052413140049899}, // k=34 + {0.9091679830905224, -0.4164295600976372}, // k=35 + {0.9039892931234433, -0.4275550934302821}, // k=36 + {0.8986744656939538, -0.4386162385385277}, // k=37 + {0.8932243011955153, -0.4496113296546065}, // k=38 + {0.8876396204028539, -0.4605387109582400}, // k=39 + {0.8819212643483550, -0.4713967368259976}, // k=40 + {0.8760700941954066, -0.4821837720791227}, // k=41 + {0.8700869911087115, -0.4928981922297840}, // k=42 + {0.8639728561215868, -0.5035383837257176}, // k=43 + {0.8577286100002721, -0.5141027441932217}, // k=44 + {0.8513551931052652, -0.5245896826784689}, // k=45 + {0.8448535652497071, -0.5349976198870972}, // k=46 + {0.8382247055548381, -0.5453249884220465}, // k=47 + {0.8314696123025452, -0.5555702330196022}, // k=48 + {0.8245893027850253, -0.5657318107836131}, // k=49 + {0.8175848131515837, -0.5758081914178453}, // k=50 + {0.8104571982525948, -0.5857978574564389}, // k=51 + {0.8032075314806449, -0.5956993044924334}, // k=52 + {0.7958369046088836, -0.6055110414043255}, // k=53 + {0.7883464276266063, -0.6152315905806268}, // k=54 + {0.7807372285720945, -0.6248594881423863}, // k=55 + {0.7730104533627370, -0.6343932841636455}, // k=56 + {0.7651672656224590, -0.6438315428897914}, // k=57 + {0.7572088465064846, -0.6531728429537768}, // k=58 + {0.7491363945234594, -0.6624157775901718}, // k=59 + {0.7409511253549591, -0.6715589548470183}, // k=60 + {0.7326542716724128, -0.6806009977954530}, // k=61 + {0.7242470829514670, -0.6895405447370668}, // k=62 + {0.7157308252838186, -0.6983762494089729}, // k=63 + {0.7071067811865476, -0.7071067811865475}, // k=64 + {0.6983762494089729, -0.7157308252838186}, // k=65 + {0.6895405447370669, -0.7242470829514669}, // k=66 + {0.6806009977954531, -0.7326542716724128}, // k=67 + {0.6715589548470183, -0.7409511253549591}, // k=68 + {0.6624157775901718, -0.7491363945234593}, // k=69 + {0.6531728429537768, -0.7572088465064845}, // k=70 + {0.6438315428897915, -0.7651672656224590}, // k=71 + {0.6343932841636455, -0.7730104533627370}, // k=72 + {0.6248594881423865, -0.7807372285720944}, // k=73 + {0.6152315905806268, -0.7883464276266062}, // k=74 + {0.6055110414043255, -0.7958369046088835}, // k=75 + {0.5956993044924335, -0.8032075314806448}, // k=76 + {0.5857978574564389, -0.8104571982525948}, // k=77 + {0.5758081914178453, -0.8175848131515837}, // k=78 + {0.5657318107836132, -0.8245893027850253}, // k=79 + {0.5555702330196023, -0.8314696123025452}, // k=80 + {0.5453249884220465, -0.8382247055548380}, // k=81 + {0.5349976198870973, -0.8448535652497070}, // k=82 + {0.5245896826784688, -0.8513551931052652}, // k=83 + {0.5141027441932217, -0.8577286100002721}, // k=84 + {0.5035383837257176, -0.8639728561215867}, // k=85 + {0.4928981922297841, -0.8700869911087113}, // k=86 + {0.4821837720791228, -0.8760700941954066}, // k=87 + {0.4713967368259978, -0.8819212643483549}, // k=88 + {0.4605387109582400, -0.8876396204028539}, // k=89 + {0.4496113296546066, -0.8932243011955153}, // k=90 + {0.4386162385385277, -0.8986744656939538}, // k=91 + {0.4275550934302822, -0.9039892931234433}, // k=92 + {0.4164295600976373, -0.9091679830905223}, // k=93 + {0.4052413140049899, -0.9142097557035307}, // k=94 + {0.3939920400610481, -0.9191138516900578}, // k=95 + {0.3826834323650898, -0.9238795325112867}, // k=96 + {0.3713171939518376, -0.9285060804732155}, // k=97 + {0.3598950365349883, -0.9329927988347388}, // k=98 + {0.3484186802494345, -0.9373390119125750}, // k=99 + {0.3368898533922201, -0.9415440651830208}, // k=100 + {0.3253102921622630, -0.9456073253805213}, // k=101 + {0.3136817403988916, -0.9495281805930367}, // k=102 + {0.3020059493192282, -0.9533060403541938}, // k=103 + {0.2902846772544623, -0.9569403357322089}, // k=104 + {0.2785196893850531, -0.9604305194155658}, // k=105 + {0.2667127574748984, -0.9637760657954398}, // k=106 + {0.2548656596045146, -0.9669764710448521}, // k=107 + {0.2429801799032640, -0.9700312531945440}, // k=108 + {0.2310581082806713, -0.9729399522055601}, // k=109 + {0.2191012401568698, -0.9757021300385286}, // k=110 + {0.2071113761922186, -0.9783173707196277}, // k=111 + {0.1950903220161283, -0.9807852804032304}, // k=112 + {0.1830398879551411, -0.9831054874312163}, // k=113 + {0.1709618887603014, -0.9852776423889412}, // k=114 + {0.1588581433338614, -0.9873014181578584}, // k=115 + {0.1467304744553617, -0.9891765099647810}, // k=116 + {0.1345807085071262, -0.9909026354277800}, // k=117 + {0.1224106751992163, -0.9924795345987100}, // k=118 + {0.1102222072938832, -0.9939069700023561}, // k=119 + {0.0980171403295608, -0.9951847266721968}, // k=120 + {0.0857973123444399, -0.9963126121827780}, // k=121 + {0.0735645635996675, -0.9972904566786902}, // k=122 + {0.0613207363022086, -0.9981181129001492}, // k=123 + {0.0490676743274181, -0.9987954562051724}, // k=124 + {0.0368072229413590, -0.9993223845883495}, // k=125 + {0.0245412285229123, -0.9996988186962042}, // k=126 + {0.0122715382857199, -0.9999247018391445}, // k=127 + {0.0000000000000001, -1.0000000000000000}, // k=128 + {-0.0122715382857198, -0.9999247018391445}, // k=129 + {-0.0245412285229121, -0.9996988186962042}, // k=130 + {-0.0368072229413589, -0.9993223845883495}, // k=131 + {-0.0490676743274180, -0.9987954562051724}, // k=132 + {-0.0613207363022085, -0.9981181129001492}, // k=133 + {-0.0735645635996673, -0.9972904566786902}, // k=134 + {-0.0857973123444398, -0.9963126121827780}, // k=135 + {-0.0980171403295606, -0.9951847266721969}, // k=136 + {-0.1102222072938831, -0.9939069700023561}, // k=137 + {-0.1224106751992162, -0.9924795345987100}, // k=138 + {-0.1345807085071261, -0.9909026354277800}, // k=139 + {-0.1467304744553616, -0.9891765099647810}, // k=140 + {-0.1588581433338613, -0.9873014181578584}, // k=141 + {-0.1709618887603012, -0.9852776423889412}, // k=142 + {-0.1830398879551409, -0.9831054874312163}, // k=143 + {-0.1950903220161282, -0.9807852804032304}, // k=144 + {-0.2071113761922184, -0.9783173707196277}, // k=145 + {-0.2191012401568697, -0.9757021300385286}, // k=146 + {-0.2310581082806711, -0.9729399522055602}, // k=147 + {-0.2429801799032639, -0.9700312531945440}, // k=148 + {-0.2548656596045145, -0.9669764710448521}, // k=149 + {-0.2667127574748983, -0.9637760657954398}, // k=150 + {-0.2785196893850529, -0.9604305194155659}, // k=151 + {-0.2902846772544622, -0.9569403357322089}, // k=152 + {-0.3020059493192281, -0.9533060403541939}, // k=153 + {-0.3136817403988914, -0.9495281805930367}, // k=154 + {-0.3253102921622629, -0.9456073253805214}, // k=155 + {-0.3368898533922199, -0.9415440651830208}, // k=156 + {-0.3484186802494344, -0.9373390119125750}, // k=157 + {-0.3598950365349882, -0.9329927988347388}, // k=158 + {-0.3713171939518375, -0.9285060804732156}, // k=159 + {-0.3826834323650897, -0.9238795325112867}, // k=160 + {-0.3939920400610480, -0.9191138516900578}, // k=161 + {-0.4052413140049897, -0.9142097557035307}, // k=162 + {-0.4164295600976370, -0.9091679830905225}, // k=163 + {-0.4275550934302819, -0.9039892931234434}, // k=164 + {-0.4386162385385274, -0.8986744656939539}, // k=165 + {-0.4496113296546067, -0.8932243011955152}, // k=166 + {-0.4605387109582401, -0.8876396204028539}, // k=167 + {-0.4713967368259977, -0.8819212643483550}, // k=168 + {-0.4821837720791227, -0.8760700941954066}, // k=169 + {-0.4928981922297840, -0.8700869911087115}, // k=170 + {-0.5035383837257175, -0.8639728561215868}, // k=171 + {-0.5141027441932217, -0.8577286100002721}, // k=172 + {-0.5245896826784687, -0.8513551931052652}, // k=173 + {-0.5349976198870970, -0.8448535652497072}, // k=174 + {-0.5453249884220462, -0.8382247055548382}, // k=175 + {-0.5555702330196020, -0.8314696123025455}, // k=176 + {-0.5657318107836132, -0.8245893027850252}, // k=177 + {-0.5758081914178453, -0.8175848131515837}, // k=178 + {-0.5857978574564389, -0.8104571982525948}, // k=179 + {-0.5956993044924334, -0.8032075314806449}, // k=180 + {-0.6055110414043254, -0.7958369046088836}, // k=181 + {-0.6152315905806267, -0.7883464276266063}, // k=182 + {-0.6248594881423862, -0.7807372285720946}, // k=183 + {-0.6343932841636454, -0.7730104533627371}, // k=184 + {-0.6438315428897913, -0.7651672656224591}, // k=185 + {-0.6531728429537765, -0.7572088465064847}, // k=186 + {-0.6624157775901719, -0.7491363945234593}, // k=187 + {-0.6715589548470184, -0.7409511253549590}, // k=188 + {-0.6806009977954530, -0.7326542716724128}, // k=189 + {-0.6895405447370669, -0.7242470829514669}, // k=190 + {-0.6983762494089728, -0.7157308252838187}, // k=191 + {-0.7071067811865475, -0.7071067811865476}, // k=192 + {-0.7157308252838186, -0.6983762494089729}, // k=193 + {-0.7242470829514668, -0.6895405447370671}, // k=194 + {-0.7326542716724127, -0.6806009977954532}, // k=195 + {-0.7409511253549589, -0.6715589548470186}, // k=196 + {-0.7491363945234591, -0.6624157775901720}, // k=197 + {-0.7572088465064846, -0.6531728429537766}, // k=198 + {-0.7651672656224590, -0.6438315428897914}, // k=199 + {-0.7730104533627370, -0.6343932841636455}, // k=200 + {-0.7807372285720945, -0.6248594881423863}, // k=201 + {-0.7883464276266062, -0.6152315905806269}, // k=202 + {-0.7958369046088835, -0.6055110414043257}, // k=203 + {-0.8032075314806448, -0.5956993044924335}, // k=204 + {-0.8104571982525947, -0.5857978574564390}, // k=205 + {-0.8175848131515836, -0.5758081914178454}, // k=206 + {-0.8245893027850251, -0.5657318107836135}, // k=207 + {-0.8314696123025453, -0.5555702330196022}, // k=208 + {-0.8382247055548381, -0.5453249884220464}, // k=209 + {-0.8448535652497071, -0.5349976198870972}, // k=210 + {-0.8513551931052652, -0.5245896826784689}, // k=211 + {-0.8577286100002720, -0.5141027441932218}, // k=212 + {-0.8639728561215867, -0.5035383837257177}, // k=213 + {-0.8700869911087113, -0.4928981922297841}, // k=214 + {-0.8760700941954065, -0.4821837720791229}, // k=215 + {-0.8819212643483549, -0.4713967368259979}, // k=216 + {-0.8876396204028538, -0.4605387109582402}, // k=217 + {-0.8932243011955152, -0.4496113296546069}, // k=218 + {-0.8986744656939539, -0.4386162385385275}, // k=219 + {-0.9039892931234433, -0.4275550934302820}, // k=220 + {-0.9091679830905224, -0.4164295600976372}, // k=221 + {-0.9142097557035307, -0.4052413140049899}, // k=222 + {-0.9191138516900578, -0.3939920400610482}, // k=223 + {-0.9238795325112867, -0.3826834323650899}, // k=224 + {-0.9285060804732155, -0.3713171939518377}, // k=225 + {-0.9329927988347388, -0.3598950365349883}, // k=226 + {-0.9373390119125748, -0.3484186802494348}, // k=227 + {-0.9415440651830207, -0.3368898533922203}, // k=228 + {-0.9456073253805212, -0.3253102921622633}, // k=229 + {-0.9495281805930367, -0.3136817403988914}, // k=230 + {-0.9533060403541939, -0.3020059493192280}, // k=231 + {-0.9569403357322088, -0.2902846772544624}, // k=232 + {-0.9604305194155658, -0.2785196893850532}, // k=233 + {-0.9637760657954398, -0.2667127574748985}, // k=234 + {-0.9669764710448521, -0.2548656596045147}, // k=235 + {-0.9700312531945440, -0.2429801799032641}, // k=236 + {-0.9729399522055601, -0.2310581082806713}, // k=237 + {-0.9757021300385285, -0.2191012401568700}, // k=238 + {-0.9783173707196275, -0.2071113761922188}, // k=239 + {-0.9807852804032304, -0.1950903220161286}, // k=240 + {-0.9831054874312163, -0.1830398879551409}, // k=241 + {-0.9852776423889412, -0.1709618887603012}, // k=242 + {-0.9873014181578584, -0.1588581433338615}, // k=243 + {-0.9891765099647810, -0.1467304744553618}, // k=244 + {-0.9909026354277800, -0.1345807085071263}, // k=245 + {-0.9924795345987100, -0.1224106751992163}, // k=246 + {-0.9939069700023561, -0.1102222072938832}, // k=247 + {-0.9951847266721968, -0.0980171403295608}, // k=248 + {-0.9963126121827780, -0.0857973123444402}, // k=249 + {-0.9972904566786902, -0.0735645635996677}, // k=250 + {-0.9981181129001492, -0.0613207363022085}, // k=251 + {-0.9987954562051724, -0.0490676743274180}, // k=252 + {-0.9993223845883495, -0.0368072229413588}, // k=253 + {-0.9996988186962042, -0.0245412285229123}, // k=254 + {-0.9999247018391445, -0.0122715382857200}, // k=255 + {-1.0000000000000000, -0.0000000000000001}, // k=256 + {-0.9999247018391445, 0.0122715382857198}, // k=257 + {-0.9996988186962042, 0.0245412285229121}, // k=258 + {-0.9993223845883495, 0.0368072229413586}, // k=259 + {-0.9987954562051724, 0.0490676743274177}, // k=260 + {-0.9981181129001492, 0.0613207363022082}, // k=261 + {-0.9972904566786902, 0.0735645635996675}, // k=262 + {-0.9963126121827780, 0.0857973123444399}, // k=263 + {-0.9951847266721969, 0.0980171403295606}, // k=264 + {-0.9939069700023561, 0.1102222072938830}, // k=265 + {-0.9924795345987100, 0.1224106751992161}, // k=266 + {-0.9909026354277800, 0.1345807085071261}, // k=267 + {-0.9891765099647810, 0.1467304744553616}, // k=268 + {-0.9873014181578584, 0.1588581433338612}, // k=269 + {-0.9852776423889413, 0.1709618887603010}, // k=270 + {-0.9831054874312164, 0.1830398879551406}, // k=271 + {-0.9807852804032304, 0.1950903220161284}, // k=272 + {-0.9783173707196277, 0.2071113761922186}, // k=273 + {-0.9757021300385286, 0.2191012401568698}, // k=274 + {-0.9729399522055602, 0.2310581082806711}, // k=275 + {-0.9700312531945440, 0.2429801799032638}, // k=276 + {-0.9669764710448522, 0.2548656596045145}, // k=277 + {-0.9637760657954400, 0.2667127574748983}, // k=278 + {-0.9604305194155659, 0.2785196893850529}, // k=279 + {-0.9569403357322089, 0.2902846772544621}, // k=280 + {-0.9533060403541940, 0.3020059493192278}, // k=281 + {-0.9495281805930368, 0.3136817403988912}, // k=282 + {-0.9456073253805213, 0.3253102921622630}, // k=283 + {-0.9415440651830208, 0.3368898533922201}, // k=284 + {-0.9373390119125750, 0.3484186802494346}, // k=285 + {-0.9329927988347390, 0.3598950365349881}, // k=286 + {-0.9285060804732156, 0.3713171939518374}, // k=287 + {-0.9238795325112868, 0.3826834323650897}, // k=288 + {-0.9191138516900578, 0.3939920400610479}, // k=289 + {-0.9142097557035307, 0.4052413140049897}, // k=290 + {-0.9091679830905225, 0.4164295600976369}, // k=291 + {-0.9039892931234434, 0.4275550934302818}, // k=292 + {-0.8986744656939540, 0.4386162385385273}, // k=293 + {-0.8932243011955153, 0.4496113296546067}, // k=294 + {-0.8876396204028539, 0.4605387109582401}, // k=295 + {-0.8819212643483550, 0.4713967368259976}, // k=296 + {-0.8760700941954066, 0.4821837720791227}, // k=297 + {-0.8700869911087115, 0.4928981922297839}, // k=298 + {-0.8639728561215868, 0.5035383837257175}, // k=299 + {-0.8577286100002721, 0.5141027441932216}, // k=300 + {-0.8513551931052653, 0.5245896826784687}, // k=301 + {-0.8448535652497072, 0.5349976198870969}, // k=302 + {-0.8382247055548382, 0.5453249884220461}, // k=303 + {-0.8314696123025455, 0.5555702330196020}, // k=304 + {-0.8245893027850253, 0.5657318107836132}, // k=305 + {-0.8175848131515837, 0.5758081914178453}, // k=306 + {-0.8104571982525948, 0.5857978574564389}, // k=307 + {-0.8032075314806449, 0.5956993044924332}, // k=308 + {-0.7958369046088836, 0.6055110414043254}, // k=309 + {-0.7883464276266063, 0.6152315905806267}, // k=310 + {-0.7807372285720946, 0.6248594881423862}, // k=311 + {-0.7730104533627371, 0.6343932841636453}, // k=312 + {-0.7651672656224591, 0.6438315428897913}, // k=313 + {-0.7572088465064848, 0.6531728429537765}, // k=314 + {-0.7491363945234593, 0.6624157775901718}, // k=315 + {-0.7409511253549591, 0.6715589548470184}, // k=316 + {-0.7326542716724128, 0.6806009977954530}, // k=317 + {-0.7242470829514670, 0.6895405447370668}, // k=318 + {-0.7157308252838187, 0.6983762494089728}, // k=319 + {-0.7071067811865477, 0.7071067811865475}, // k=320 + {-0.6983762494089730, 0.7157308252838185}, // k=321 + {-0.6895405447370671, 0.7242470829514668}, // k=322 + {-0.6806009977954532, 0.7326542716724126}, // k=323 + {-0.6715589548470187, 0.7409511253549589}, // k=324 + {-0.6624157775901720, 0.7491363945234590}, // k=325 + {-0.6531728429537771, 0.7572088465064842}, // k=326 + {-0.6438315428897915, 0.7651672656224590}, // k=327 + {-0.6343932841636459, 0.7730104533627367}, // k=328 + {-0.6248594881423865, 0.7807372285720944}, // k=329 + {-0.6152315905806273, 0.7883464276266059}, // k=330 + {-0.6055110414043257, 0.7958369046088835}, // k=331 + {-0.5956993044924331, 0.8032075314806451}, // k=332 + {-0.5857978574564391, 0.8104571982525947}, // k=333 + {-0.5758081914178452, 0.8175848131515838}, // k=334 + {-0.5657318107836135, 0.8245893027850251}, // k=335 + {-0.5555702330196022, 0.8314696123025452}, // k=336 + {-0.5453249884220468, 0.8382247055548379}, // k=337 + {-0.5349976198870973, 0.8448535652497070}, // k=338 + {-0.5245896826784694, 0.8513551931052649}, // k=339 + {-0.5141027441932218, 0.8577286100002720}, // k=340 + {-0.5035383837257180, 0.8639728561215865}, // k=341 + {-0.4928981922297842, 0.8700869911087113}, // k=342 + {-0.4821837720791226, 0.8760700941954067}, // k=343 + {-0.4713967368259979, 0.8819212643483549}, // k=344 + {-0.4605387109582399, 0.8876396204028540}, // k=345 + {-0.4496113296546069, 0.8932243011955152}, // k=346 + {-0.4386162385385276, 0.8986744656939538}, // k=347 + {-0.4275550934302825, 0.9039892931234431}, // k=348 + {-0.4164295600976372, 0.9091679830905224}, // k=349 + {-0.4052413140049904, 0.9142097557035305}, // k=350 + {-0.3939920400610482, 0.9191138516900577}, // k=351 + {-0.3826834323650903, 0.9238795325112865}, // k=352 + {-0.3713171939518378, 0.9285060804732155}, // k=353 + {-0.3598950365349879, 0.9329927988347390}, // k=354 + {-0.3484186802494348, 0.9373390119125748}, // k=355 + {-0.3368898533922199, 0.9415440651830208}, // k=356 + {-0.3253102921622633, 0.9456073253805212}, // k=357 + {-0.3136817403988915, 0.9495281805930367}, // k=358 + {-0.3020059493192285, 0.9533060403541938}, // k=359 + {-0.2902846772544624, 0.9569403357322088}, // k=360 + {-0.2785196893850536, 0.9604305194155657}, // k=361 + {-0.2667127574748985, 0.9637760657954398}, // k=362 + {-0.2548656596045143, 0.9669764710448522}, // k=363 + {-0.2429801799032641, 0.9700312531945440}, // k=364 + {-0.2310581082806709, 0.9729399522055602}, // k=365 + {-0.2191012401568701, 0.9757021300385285}, // k=366 + {-0.2071113761922185, 0.9783173707196277}, // k=367 + {-0.1950903220161287, 0.9807852804032303}, // k=368 + {-0.1830398879551410, 0.9831054874312163}, // k=369 + {-0.1709618887603017, 0.9852776423889411}, // k=370 + {-0.1588581433338615, 0.9873014181578583}, // k=371 + {-0.1467304744553623, 0.9891765099647809}, // k=372 + {-0.1345807085071264, 0.9909026354277800}, // k=373 + {-0.1224106751992160, 0.9924795345987101}, // k=374 + {-0.1102222072938833, 0.9939069700023561}, // k=375 + {-0.0980171403295605, 0.9951847266721969}, // k=376 + {-0.0857973123444402, 0.9963126121827780}, // k=377 + {-0.0735645635996674, 0.9972904566786902}, // k=378 + {-0.0613207363022090, 0.9981181129001492}, // k=379 + {-0.0490676743274180, 0.9987954562051724}, // k=380 + {-0.0368072229413593, 0.9993223845883494}, // k=381 + {-0.0245412285229124, 0.9996988186962042}, // k=382 + {-0.0122715382857205, 0.9999247018391445}, // k=383 + {-0.0000000000000002, 1.0000000000000000}, // k=384 + {0.0122715382857201, 0.9999247018391445}, // k=385 + {0.0245412285229120, 0.9996988186962042}, // k=386 + {0.0368072229413590, 0.9993223845883495}, // k=387 + {0.0490676743274177, 0.9987954562051724}, // k=388 + {0.0613207363022086, 0.9981181129001492}, // k=389 + {0.0735645635996670, 0.9972904566786902}, // k=390 + {0.0857973123444399, 0.9963126121827780}, // k=391 + {0.0980171403295601, 0.9951847266721969}, // k=392 + {0.1102222072938829, 0.9939069700023561}, // k=393 + {0.1224106751992156, 0.9924795345987101}, // k=394 + {0.1345807085071260, 0.9909026354277800}, // k=395 + {0.1467304744553619, 0.9891765099647809}, // k=396 + {0.1588581433338612, 0.9873014181578584}, // k=397 + {0.1709618887603013, 0.9852776423889412}, // k=398 + {0.1830398879551406, 0.9831054874312164}, // k=399 + {0.1950903220161283, 0.9807852804032304}, // k=400 + {0.2071113761922181, 0.9783173707196278}, // k=401 + {0.2191012401568697, 0.9757021300385286}, // k=402 + {0.2310581082806706, 0.9729399522055603}, // k=403 + {0.2429801799032638, 0.9700312531945440}, // k=404 + {0.2548656596045140, 0.9669764710448523}, // k=405 + {0.2667127574748982, 0.9637760657954400}, // k=406 + {0.2785196893850533, 0.9604305194155658}, // k=407 + {0.2902846772544621, 0.9569403357322089}, // k=408 + {0.3020059493192281, 0.9533060403541939}, // k=409 + {0.3136817403988911, 0.9495281805930368}, // k=410 + {0.3253102921622629, 0.9456073253805213}, // k=411 + {0.3368898533922196, 0.9415440651830209}, // k=412 + {0.3484186802494345, 0.9373390119125750}, // k=413 + {0.3598950365349876, 0.9329927988347391}, // k=414 + {0.3713171939518374, 0.9285060804732156}, // k=415 + {0.3826834323650900, 0.9238795325112866}, // k=416 + {0.3939920400610479, 0.9191138516900579}, // k=417 + {0.4052413140049900, 0.9142097557035306}, // k=418 + {0.4164295600976369, 0.9091679830905225}, // k=419 + {0.4275550934302821, 0.9039892931234433}, // k=420 + {0.4386162385385273, 0.8986744656939540}, // k=421 + {0.4496113296546066, 0.8932243011955153}, // k=422 + {0.4605387109582396, 0.8876396204028542}, // k=423 + {0.4713967368259976, 0.8819212643483550}, // k=424 + {0.4821837720791222, 0.8760700941954069}, // k=425 + {0.4928981922297839, 0.8700869911087115}, // k=426 + {0.5035383837257178, 0.8639728561215866}, // k=427 + {0.5141027441932216, 0.8577286100002722}, // k=428 + {0.5245896826784691, 0.8513551931052651}, // k=429 + {0.5349976198870969, 0.8448535652497072}, // k=430 + {0.5453249884220465, 0.8382247055548380}, // k=431 + {0.5555702330196018, 0.8314696123025455}, // k=432 + {0.5657318107836131, 0.8245893027850253}, // k=433 + {0.5758081914178449, 0.8175848131515840}, // k=434 + {0.5857978574564388, 0.8104571982525949}, // k=435 + {0.5956993044924329, 0.8032075314806453}, // k=436 + {0.6055110414043253, 0.7958369046088837}, // k=437 + {0.6152315905806270, 0.7883464276266061}, // k=438 + {0.6248594881423861, 0.7807372285720946}, // k=439 + {0.6343932841636456, 0.7730104533627369}, // k=440 + {0.6438315428897912, 0.7651672656224592}, // k=441 + {0.6531728429537768, 0.7572088465064846}, // k=442 + {0.6624157775901715, 0.7491363945234596}, // k=443 + {0.6715589548470183, 0.7409511253549591}, // k=444 + {0.6806009977954527, 0.7326542716724131}, // k=445 + {0.6895405447370668, 0.7242470829514670}, // k=446 + {0.6983762494089724, 0.7157308252838190}, // k=447 + {0.7071067811865474, 0.7071067811865477}, // k=448 + {0.7157308252838188, 0.6983762494089727}, // k=449 + {0.7242470829514667, 0.6895405447370672}, // k=450 + {0.7326542716724129, 0.6806009977954530}, // k=451 + {0.7409511253549589, 0.6715589548470187}, // k=452 + {0.7491363945234594, 0.6624157775901718}, // k=453 + {0.7572088465064842, 0.6531728429537771}, // k=454 + {0.7651672656224588, 0.6438315428897915}, // k=455 + {0.7730104533627367, 0.6343932841636459}, // k=456 + {0.7807372285720944, 0.6248594881423865}, // k=457 + {0.7883464276266059, 0.6152315905806274}, // k=458 + {0.7958369046088833, 0.6055110414043257}, // k=459 + {0.8032075314806451, 0.5956993044924332}, // k=460 + {0.8104571982525947, 0.5857978574564391}, // k=461 + {0.8175848131515837, 0.5758081914178452}, // k=462 + {0.8245893027850251, 0.5657318107836136}, // k=463 + {0.8314696123025452, 0.5555702330196022}, // k=464 + {0.8382247055548377, 0.5453249884220468}, // k=465 + {0.8448535652497070, 0.5349976198870973}, // k=466 + {0.8513551931052649, 0.5245896826784694}, // k=467 + {0.8577286100002720, 0.5141027441932219}, // k=468 + {0.8639728561215864, 0.5035383837257181}, // k=469 + {0.8700869911087113, 0.4928981922297843}, // k=470 + {0.8760700941954067, 0.4821837720791226}, // k=471 + {0.8819212643483548, 0.4713967368259979}, // k=472 + {0.8876396204028539, 0.4605387109582399}, // k=473 + {0.8932243011955151, 0.4496113296546070}, // k=474 + {0.8986744656939538, 0.4386162385385277}, // k=475 + {0.9039892931234431, 0.4275550934302825}, // k=476 + {0.9091679830905224, 0.4164295600976373}, // k=477 + {0.9142097557035305, 0.4052413140049904}, // k=478 + {0.9191138516900577, 0.3939920400610483}, // k=479 + {0.9238795325112865, 0.3826834323650904}, // k=480 + {0.9285060804732155, 0.3713171939518378}, // k=481 + {0.9329927988347390, 0.3598950365349880}, // k=482 + {0.9373390119125748, 0.3484186802494349}, // k=483 + {0.9415440651830208, 0.3368898533922200}, // k=484 + {0.9456073253805212, 0.3253102921622634}, // k=485 + {0.9495281805930367, 0.3136817403988915}, // k=486 + {0.9533060403541936, 0.3020059493192286}, // k=487 + {0.9569403357322088, 0.2902846772544625}, // k=488 + {0.9604305194155657, 0.2785196893850537}, // k=489 + {0.9637760657954398, 0.2667127574748986}, // k=490 + {0.9669764710448522, 0.2548656596045144}, // k=491 + {0.9700312531945440, 0.2429801799032642}, // k=492 + {0.9729399522055602, 0.2310581082806710}, // k=493 + {0.9757021300385285, 0.2191012401568702}, // k=494 + {0.9783173707196277, 0.2071113761922185}, // k=495 + {0.9807852804032303, 0.1950903220161287}, // k=496 + {0.9831054874312163, 0.1830398879551410}, // k=497 + {0.9852776423889411, 0.1709618887603018}, // k=498 + {0.9873014181578583, 0.1588581433338616}, // k=499 + {0.9891765099647809, 0.1467304744553624}, // k=500 + {0.9909026354277800, 0.1345807085071264}, // k=501 + {0.9924795345987100, 0.1224106751992160}, // k=502 + {0.9939069700023561, 0.1102222072938834}, // k=503 + {0.9951847266721969, 0.0980171403295605}, // k=504 + {0.9963126121827780, 0.0857973123444403}, // k=505 + {0.9972904566786902, 0.0735645635996674}, // k=506 + {0.9981181129001492, 0.0613207363022091}, // k=507 + {0.9987954562051724, 0.0490676743274181}, // k=508 + {0.9993223845883494, 0.0368072229413594}, // k=509 + {0.9996988186962042, 0.0245412285229124}, // k=510 + {0.9999247018391445, 0.0122715382857206}, // k=511 +}; diff --git a/include/bout/utils.hxx b/include/bout/utils.hxx index e2ac814e53..0679324723 100644 --- a/include/bout/utils.hxx +++ b/include/bout/utils.hxx @@ -5,10 +5,10 @@ * simple but common calculations * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors + * + * Contact: Ben Dudson, dudson2@llnl.gov * - * Contact: Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -29,13 +29,11 @@ #ifndef BOUT_UTILS_H #define BOUT_UTILS_H -#include "bout/build_config.hxx" - #include "bout/array.hxx" #include "bout/assert.hxx" #include "bout/bout_types.hxx" #include "bout/boutexception.hxx" -#include "bout/msg_stack.hxx" +#include "bout/build_config.hxx" #include "bout/region.hxx" #include "bout/unused.hxx" @@ -47,6 +45,11 @@ #include #include #include +#include +#include +#include + +class Field; #ifdef _MSC_VER // finite is not actually standard C++, it's a BSD extention for C @@ -187,6 +190,7 @@ typename std::vector::size_type erase_if(std::vector& c, Pre return r; } #else +using std::erase; using std::erase_if; #endif } // namespace utils @@ -231,6 +235,14 @@ public: data.reallocate(new_size_1 * new_size_2); } + /*! + * Change shape of the container. + * Invalidates contents. + */ + void reshape(std::tuple new_shape) { + reallocate(std::get<0>(new_shape), std::get<1>(new_shape)); + } + Matrix& operator=(const Matrix& other) { n1 = other.n1; n2 = other.n2; @@ -305,9 +317,9 @@ public: Tensor(Tensor&&) noexcept = default; Tensor& operator=(Tensor&&) noexcept = default; Tensor(size_type n1, size_type n2, size_type n3) : n1(n1), n2(n2), n3(n3) { - ASSERT2(n1 >= 0); - ASSERT2(n2 >= 0); - ASSERT2(n3 >= 0); + ASSERT0(n1 >= 0); + ASSERT0(n2 >= 0); + ASSERT0(n3 >= 0); data.reallocate(n1 * n2 * n3); } Tensor(const Tensor& other) @@ -321,9 +333,9 @@ public: /// /// Note that this invalidates the existing data! void reallocate(size_type new_size_1, size_type new_size_2, size_type new_size_3) { - ASSERT2(new_size_1 >= 0); - ASSERT2(new_size_2 >= 0); - ASSERT2(new_size_3 >= 0); + ASSERT0(new_size_1 >= 0); + ASSERT0(new_size_2 >= 0); + ASSERT0(new_size_3 >= 0); n1 = new_size_1; n2 = new_size_2; @@ -331,6 +343,14 @@ public: data.reallocate(new_size_1 * new_size_2 * new_size_3); } + /*! + * Change shape of the container. + * Invalidates contents. + */ + void reshape(std::tuple new_shape) { + reallocate(std::get<0>(new_shape), std::get<1>(new_shape), std::get<2>(new_shape)); + } + Tensor& operator=(const Tensor& other) { n1 = other.n1; n2 = other.n2; @@ -361,7 +381,6 @@ public: ASSERT2(0 <= i.ind && i.ind < n1 * n2 * n3); return data[i.ind]; } - T& operator[](Ind3D i) { // ny and nz are private :-( // ASSERT2(i.nz == n3); @@ -421,15 +440,13 @@ inline BoutReal randomu() { * Calculate the square of a variable \p t * i.e. t * t */ -template -inline T SQ(const T& t) { +template >>> +inline auto SQ(const T& t) { return t * t; } -template <> -BOUT_HOST_DEVICE inline BoutReal SQ(const BoutReal& t) { - return t * t; -} +BOUT_HOST_DEVICE inline BoutReal SQ(const BoutReal& t) { return t * t; } /*! * Round \p x to the nearest integer @@ -469,7 +486,7 @@ inline bool is_pow2(int x) { return x && !((x - 1) & x); } /*! * Return the sign of a number \p a - * by testing if a > 0 + * by testing if a > 0 */ template T SIGN(T a) { // Return +1 or -1 (0 -> +1) @@ -496,7 +513,7 @@ inline void checkData(BoutReal f) { } #else /// Ignored with disabled CHECK; Throw an exception if \p f is not finite -inline void checkData(BoutReal UNUSED(f)){}; +inline void checkData(BoutReal UNUSED(f)) {}; #endif /*! @@ -518,18 +535,18 @@ std::string toString(const T& val) { /// where the type may be std::string. inline std::string toString(const std::string& val) { return val; } -template <> -inline std::string toString<>(const Array& UNUSED(val)) { +template +inline std::string toString(const Array& UNUSED(val)) { return ""; } -template <> -inline std::string toString<>(const Matrix& UNUSED(val)) { +template +inline std::string toString(const Matrix& UNUSED(val)) { return ""; } -template <> -inline std::string toString<>(const Tensor& UNUSED(val)) { +template +inline std::string toString(const Tensor& UNUSED(val)) { return ""; } @@ -572,7 +589,7 @@ BoutReal stringToReal(const std::string& s); /*! * Convert a string to an int - * + * * Throws BoutException if can't be done */ int stringToInt(const std::string& s); @@ -589,7 +606,7 @@ std::list& strsplit(const std::string& s, char delim, /*! * Split a string on a given delimiter - * + * * @param[in] s The string to split (not modified by call) * @param[in] delim The delimiter to split on (single char) */ @@ -597,7 +614,7 @@ std::list strsplit(const std::string& s, char delim); /*! * Strips leading and trailing spaces from a string - * + * * @param[in] s The string to trim (not modified) * @param[in] c Collection of characters to remove */ @@ -605,7 +622,7 @@ std::string trim(const std::string& s, const std::string& c = " \t\r"); /*! * Strips leading spaces from a string - * + * * @param[in] s The string to trim (not modified) * @param[in] c Collection of characters to remove */ @@ -613,7 +630,7 @@ std::string trimLeft(const std::string& s, const std::string& c = " \t"); /*! * Strips leading spaces from a string - * + * * @param[in] s The string to trim (not modified) * @param[in] c Collection of characters to remove */ @@ -621,7 +638,7 @@ std::string trimRight(const std::string& s, const std::string& c = " \t\r"); /*! * Strips the comments from a string - * + * * @param[in] s The string to trim (not modified) * @param[in] c Collection of characters to remove */ diff --git a/include/bout/vector2d.hxx b/include/bout/vector2d.hxx index bdc375e698..1e19241a8e 100644 --- a/include/bout/vector2d.hxx +++ b/include/bout/vector2d.hxx @@ -13,7 +13,7 @@ * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -142,7 +142,7 @@ public: CELL_LOC getLocation() const override; // FieldData virtual functions - bool is3D() const override { return false; } + FieldType field_type() const override { return FieldType::field2d; } int elementSize() const override { return 3; } /// Apply boundary condition to all fields diff --git a/include/bout/vector3d.hxx b/include/bout/vector3d.hxx index 0c71dcffa5..73d3912838 100644 --- a/include/bout/vector3d.hxx +++ b/include/bout/vector3d.hxx @@ -3,13 +3,11 @@ * * \brief Class for 3D vectors. Built on the Field3D class. * - * \author B. Dudson, October 2007 - * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2026 BOUT++ contributors + * + * Contact: Ben Dudson, dudson2@llnl.gov * - * Contact: Ben Dudson, bd512@york.ac.uk - * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -45,10 +43,10 @@ class Vector2D; * ------- * * Vector3D f; - * + * * a.x; // Error! a.x not allocated * - * + * */ class Vector3D : public FieldData { public: @@ -70,7 +68,7 @@ public: ~Vector3D() override; /*! - * The components of the vector. These can be + * The components of the vector. These can be * either co- or contra-variant, depending on * the boolean flag "covariant" */ @@ -92,8 +90,8 @@ public: bool covariant{true}; /*! - * In-place conversion to covariant form. - * + * In-place conversion to covariant form. + * * If already covariant (covariant = true) then does nothing * If contravariant, multiplies by metric tensor g_{ij} */ @@ -104,7 +102,7 @@ public: * * If already contravariant (covariant = false) then does nothing * If covariant, multiplies by metric tensor g^{ij} - * + * */ void toContravariant(); @@ -114,14 +112,14 @@ public: * The first time this is called, a new Vector3D object is created. * Subsequent calls return a pointer to this same object * - * For convenience, a standalone function "ddt" exists, so that + * For convenience, a standalone function "ddt" exists, so that * * ddt(v) is equivalent to *(v.timeDeriv()) - * + * * This does some book-keeping to ensure that the time derivative * of the components is the same as the components of the time derivative * - * ddt(v).x == ddt(v.x) + * ddt(v).x == ddt(v.x) */ Vector3D* timeDeriv(); @@ -172,7 +170,7 @@ public: CELL_LOC getLocation() const override; // FieldData virtual functions - bool is3D() const override { return true; } + FieldType field_type() const override { return FieldType::field3d; } int elementSize() const override { return 3; } void applyBoundary(bool init = false) override; @@ -203,7 +201,7 @@ const Vector3D cross(const Vector3D& lhs, const Vector2D& rhs); /*! * Absolute magnitude (modulus) of a vector |v| - * + * * sqrt( v.x^2 + v.y^2 + v.z^2 ) */ const Field3D abs(const Vector3D& v, const std::string& region = "RGN_ALL"); diff --git a/include/bout/vectormetric.hxx b/include/bout/vectormetric.hxx index 76a745d120..8fd994afed 100644 --- a/include/bout/vectormetric.hxx +++ b/include/bout/vectormetric.hxx @@ -1,3 +1,7 @@ +/// \file +/// Header to simplify using `Vector2D`/`Vector3D` when switching +/// between 2D and 3D metrics in user code + #pragma once #include "bout/build_defines.hxx" diff --git a/include/bout/yboundary_regions.hxx b/include/bout/yboundary_regions.hxx new file mode 100644 index 0000000000..91dcd529e0 --- /dev/null +++ b/include/bout/yboundary_regions.hxx @@ -0,0 +1,86 @@ +#pragma once + +#include "bout/boundary_region.hxx" +#include "bout/boundary_region_iter.hxx" +#include "bout/boutexception.hxx" +#include "bout/field_data.hxx" +#include "bout/mask.hxx" +#include "bout/region.hxx" + +#include +#include +#include + +class Options; + +namespace bout { +namespace boundary { +/// This class allows to simplify iterating over y-boundaries. +/// +/// It makes it easier to write code for FieldAligned boundaries, but if a bit +/// care is taken the code also works with FluxCoordinateIndependent code. +/// +/// An example how to replace old code is given here: +/// ../../manual/sphinx/user_docs/boundary_options.rst +class YBoundary { +public: + YBoundary(YBndryType type, Options* options_ptr, const Mesh& mesh); + + /// Iterate over the boundary. + /// This function takes a lamda / templated function, that applies the boundary on the given point. + /// The function must take a `const BoundaryIterator auto& point` as its only argument. + /// See also the documentation at ../../manual/sphinx/user_docs/boundary_options.rst + template + requires std::regular_invocable + || std::regular_invocable + void iter(F func) const { + for (const auto& region : boundary_regions) { + for (const auto& point : *region) { + func(point); + } + } + for (const auto& region : boundary_regions_par) { + for (const auto& point : *region) { + func(point); + } + } + } + + /// Return true if this boundary in the lower direction contains point \p ind + bool contains_low(const Ind3D& ind) const { return _contains_low[ind]; } + /// Return true if this boundary in the upper direction contains point \p ind + bool contains_high(const Ind3D& ind) const { return _contains_high[ind]; } + + /// Return true if this boundary in direction \p dir contains point \p ind + template + bool contains(const Ind3D& ind) const { + static_assert(dir == 1 || dir == -1); + if constexpr (dir == 1) { + return _contains_high[ind]; + } + if constexpr (dir == -1) { + return _contains_low[ind]; + } + } + + /// Return true if this boundary in direction \p dir contains point \p ind + bool contains(int dir, const Ind3D& ind) const { + if (dir == 1) { + return contains<+1>(ind); + } + if (dir == -1) { + return contains<-1>(ind); + } + throw BoutException("only dir == 1 and dir == -1 are implemented, not {}", dir); + } + +private: + std::vector> boundary_regions_par; + std::vector> boundary_regions; + + BoutMask _contains_low; + BoutMask _contains_high; +}; + +} // namespace boundary +} // namespace bout diff --git a/include/bout_types.hxx b/include/bout_types.hxx deleted file mode 100644 index e6048eb885..0000000000 --- a/include/bout_types.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "bout_types.hxx" has moved to "bout/bout_types.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/bout_types.hxx" diff --git a/include/boutcomm.hxx b/include/boutcomm.hxx deleted file mode 100644 index 256df49c4f..0000000000 --- a/include/boutcomm.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boutcomm.hxx" has moved to "bout/boutcomm.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boutcomm.hxx" diff --git a/include/boutexception.hxx b/include/boutexception.hxx deleted file mode 100644 index 9189babfb3..0000000000 --- a/include/boutexception.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boutexception.hxx" has moved to "bout/boutexception.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boutexception.hxx" diff --git a/include/cyclic_reduction.hxx b/include/cyclic_reduction.hxx deleted file mode 100644 index 3ff098b062..0000000000 --- a/include/cyclic_reduction.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "cyclic_reduction.hxx" has moved to "bout/cyclic_reduction.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/cyclic_reduction.hxx" diff --git a/include/dcomplex.hxx b/include/dcomplex.hxx deleted file mode 100644 index a91c5485bf..0000000000 --- a/include/dcomplex.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "dcomplex.hxx" has moved to "bout/dcomplex.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/dcomplex.hxx" diff --git a/include/derivs.hxx b/include/derivs.hxx deleted file mode 100644 index d0a6eb5831..0000000000 --- a/include/derivs.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "derivs.hxx" has moved to "bout/derivs.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/derivs.hxx" diff --git a/include/difops.hxx b/include/difops.hxx deleted file mode 100644 index a61d9712a9..0000000000 --- a/include/difops.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "difops.hxx" has moved to "bout/difops.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/difops.hxx" diff --git a/include/fft.hxx b/include/fft.hxx deleted file mode 100644 index d67b257388..0000000000 --- a/include/fft.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "fft.hxx" has moved to "bout/fft.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/fft.hxx" diff --git a/include/field.hxx b/include/field.hxx deleted file mode 100644 index a2fcb2464e..0000000000 --- a/include/field.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field.hxx" has moved to "bout/field.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field.hxx" diff --git a/include/field2d.hxx b/include/field2d.hxx deleted file mode 100644 index 3b148b3a50..0000000000 --- a/include/field2d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field2d.hxx" has moved to "bout/field2d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field2d.hxx" diff --git a/include/field3d.hxx b/include/field3d.hxx deleted file mode 100644 index 300cec057b..0000000000 --- a/include/field3d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field3d.hxx" has moved to "bout/field3d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field3d.hxx" diff --git a/include/field_data.hxx b/include/field_data.hxx deleted file mode 100644 index 90f5c96c40..0000000000 --- a/include/field_data.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field_data.hxx" has moved to "bout/field_data.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field_data.hxx" diff --git a/include/field_factory.hxx b/include/field_factory.hxx deleted file mode 100644 index c6302ee298..0000000000 --- a/include/field_factory.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field_factory.hxx" has moved to "bout/field_factory.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field_factory.hxx" diff --git a/include/fieldperp.hxx b/include/fieldperp.hxx deleted file mode 100644 index 1994e53060..0000000000 --- a/include/fieldperp.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "fieldperp.hxx" has moved to "bout/fieldperp.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/fieldperp.hxx" diff --git a/include/globals.hxx b/include/globals.hxx deleted file mode 100644 index f07488c10c..0000000000 --- a/include/globals.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "globals.hxx" has moved to "bout/globals.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/globals.hxx" diff --git a/include/gyro_average.hxx b/include/gyro_average.hxx deleted file mode 100644 index c0d454eb50..0000000000 --- a/include/gyro_average.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "gyro_average.hxx" has moved to "bout/gyro_average.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/gyro_average.hxx" diff --git a/include/initialprofiles.hxx b/include/initialprofiles.hxx deleted file mode 100644 index 7bc1595261..0000000000 --- a/include/initialprofiles.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "initialprofiles.hxx" has moved to "bout/initialprofiles.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/initialprofiles.hxx" diff --git a/include/interpolation.hxx b/include/interpolation.hxx deleted file mode 100644 index 80ad60b4e4..0000000000 --- a/include/interpolation.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "interpolation.hxx" has moved to "bout/interpolation.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/interpolation.hxx" diff --git a/include/interpolation_xz.hxx b/include/interpolation_xz.hxx deleted file mode 100644 index 8845e34b80..0000000000 --- a/include/interpolation_xz.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "interpolation_xz.hxx" has moved to "bout/interpolation_xz.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/interpolation_xz.hxx" diff --git a/include/interpolation_z.hxx b/include/interpolation_z.hxx deleted file mode 100644 index a88b486026..0000000000 --- a/include/interpolation_z.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "interpolation_z.hxx" has moved to "bout/interpolation_z.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/interpolation_z.hxx" diff --git a/include/invert_laplace.hxx b/include/invert_laplace.hxx deleted file mode 100644 index fbb04acaf1..0000000000 --- a/include/invert_laplace.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "invert_laplace.hxx" has moved to "bout/invert_laplace.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/invert_laplace.hxx" diff --git a/include/invert_parderiv.hxx b/include/invert_parderiv.hxx deleted file mode 100644 index 81a8ca4f49..0000000000 --- a/include/invert_parderiv.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "invert_parderiv.hxx" has moved to "bout/invert_parderiv.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/invert_parderiv.hxx" diff --git a/include/lapack_routines.hxx b/include/lapack_routines.hxx deleted file mode 100644 index 97fa2c6be9..0000000000 --- a/include/lapack_routines.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "lapack_routines.hxx" has moved to "bout/lapack_routines.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/lapack_routines.hxx" diff --git a/include/mask.hxx b/include/mask.hxx deleted file mode 100644 index cbeab65d85..0000000000 --- a/include/mask.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "mask.hxx" has moved to "bout/mask.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/mask.hxx" diff --git a/include/msg_stack.hxx b/include/msg_stack.hxx deleted file mode 100644 index 2503961748..0000000000 --- a/include/msg_stack.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "msg_stack.hxx" has moved to "bout/msg_stack.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/msg_stack.hxx" diff --git a/include/multiostream.hxx b/include/multiostream.hxx deleted file mode 100644 index 7e7101aad0..0000000000 --- a/include/multiostream.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "multiostream.hxx" has moved to "bout/multiostream.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/multiostream.hxx" diff --git a/include/options.hxx b/include/options.hxx deleted file mode 100644 index 4693422c13..0000000000 --- a/include/options.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "options.hxx" has moved to "bout/options.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/options.hxx" diff --git a/include/optionsreader.hxx b/include/optionsreader.hxx deleted file mode 100644 index 2c0f8344bf..0000000000 --- a/include/optionsreader.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "optionsreader.hxx" has moved to "bout/optionsreader.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/optionsreader.hxx" diff --git a/include/output.hxx b/include/output.hxx deleted file mode 100644 index 7eebcad478..0000000000 --- a/include/output.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "output.hxx" has moved to "bout/output.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/output.hxx" diff --git a/include/parallel_boundary_op.hxx b/include/parallel_boundary_op.hxx deleted file mode 100644 index e82a88d98f..0000000000 --- a/include/parallel_boundary_op.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "parallel_boundary_op.hxx" has moved to "bout/parallel_boundary_op.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/parallel_boundary_op.hxx" diff --git a/include/parallel_boundary_region.hxx b/include/parallel_boundary_region.hxx deleted file mode 100644 index dee2277007..0000000000 --- a/include/parallel_boundary_region.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "parallel_boundary_region.hxx" has moved to "bout/parallel_boundary_region.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/parallel_boundary_region.hxx" diff --git a/include/smoothing.hxx b/include/smoothing.hxx deleted file mode 100644 index b1a36adfb2..0000000000 --- a/include/smoothing.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "smoothing.hxx" has moved to "bout/smoothing.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/smoothing.hxx" diff --git a/include/sourcex.hxx b/include/sourcex.hxx deleted file mode 100644 index e09f3e89e4..0000000000 --- a/include/sourcex.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "sourcex.hxx" has moved to "bout/sourcex.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/sourcex.hxx" diff --git a/include/stencils.hxx b/include/stencils.hxx deleted file mode 100644 index fc877f3e1c..0000000000 --- a/include/stencils.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "stencils.hxx" has moved to "bout/stencils.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/stencils.hxx" diff --git a/include/unused.hxx b/include/unused.hxx deleted file mode 100644 index fa5ea7b6d1..0000000000 --- a/include/unused.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "unused.hxx" has moved to "bout/unused.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/unused.hxx" diff --git a/include/utils.hxx b/include/utils.hxx deleted file mode 100644 index d1a095e491..0000000000 --- a/include/utils.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "utils.hxx" has moved to "bout/utils.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/utils.hxx" diff --git a/include/vecops.hxx b/include/vecops.hxx deleted file mode 100644 index 1773418077..0000000000 --- a/include/vecops.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "vecops.hxx" has moved to "bout/vecops.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/vecops.hxx" diff --git a/include/vector2d.hxx b/include/vector2d.hxx deleted file mode 100644 index 6746d3f163..0000000000 --- a/include/vector2d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "vector2d.hxx" has moved to "bout/vector2d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/vector2d.hxx" diff --git a/include/vector3d.hxx b/include/vector3d.hxx deleted file mode 100644 index 747b6a75dd..0000000000 --- a/include/vector3d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "vector3d.hxx" has moved to "bout/vector3d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/vector3d.hxx" diff --git a/include/where.hxx b/include/where.hxx deleted file mode 100644 index e5b2bd9d30..0000000000 --- a/include/where.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "where.hxx" has moved to "bout/where.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/where.hxx" diff --git a/locale/de/libbout.po b/locale/de/libbout.po index 0e0773b5db..38d9f62a3e 100644 --- a/locale/de/libbout.po +++ b/locale/de/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2019-02-06 17:32+0000\n" "Last-Translator: David \n" "Language-Team: German\n" @@ -18,132 +18,134 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.2.1\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:182 +#, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -"\t -> `Core` Region iyseps2_1-iyseps1_1 ({:d}-{:d} = {:d}) muss ein " -"Vielfaches von MYSUB ({:d}) sein\n" +"\t -> `Core` Region iyseps2_1-iyseps1_1 ({:d}-{:d} = {:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -"\t -> `Core` Region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) muss ein " -"Vielfaches von MYSUB ({:d}) sein\n" +"\t -> `Core` Region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:190 +#, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -"\t -> `Core` Region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) muss ein " -"Vielfaches von MYSUB ({:d}) sein\n" +"\t -> `Core` Region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" -msgstr "\t -> Wert OK\n" +msgstr "" +"\t -> Wert OK\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:171 +#, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -"\t -> `Leg` Region jyseps1_1+1 ({:d}) muss ein Vielfaches von MYSUB ({:d}) " -"sein\n" +"\t -> `Leg` Region jyseps1_1+1 ({:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:206 +#, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -"\t -> `Leg` Region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) muss ein " -"Vielfaches von MYSUB ({:d}) sein\n" +"\t -> `Leg` Region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:223 +#, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -"\t -> `Leg` Region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) muss ein Vielfaches " -"von MYSUB ({:d}) sein\n" +"\t -> `Leg` Region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -"\t -> `Leg` Region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) muss ein " -"Vielfaches von MYSUB ({:d}) sein\n" +"\t -> `Leg` Region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) muss ein Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:166 +#, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" -msgstr "\t -> ny/NYPE ({:d}/{:d} = {:d}) muss >= MYG ({:d}) sein\n" +msgstr "" +"\t -> ny/NYPE ({:d}/{:d} = {:d}) muss >= MYG ({:d}) sein\n" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" +"\tUnterstützung für ADIOS2 {}\n" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" +"\tBacktrace in Ausnahmen {}\n" #. Loop over all possibilities #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:288 +#, c++-format msgid "\tCandidate value: {:d}\n" -msgstr "\tzu überprüfender Wert: {:d}\n" +msgstr "" +"\tzu überprüfender Wert: {:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" +"\tFarben in Protokollen {}\n" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "\tKommandozeilenoptionen für diese Ausführung: " #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 -#, fuzzy, c++-format +#: ../src/bout++.cxx:595 +#, c++-format msgid "\tCompiled with flags : {:s}\n" -msgstr "\tWurde kompiliert mit den Optionen : {:s}\n" +msgstr "" +"\tWurde kompiliert mit den Optionen : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:315 +#, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" -"\tDas Gebiet wird in NXPE={:d} mal NYPE={:d} Gebiete der Größe localNx={:d} " -"mal localNy={:d} aufgeteilt\n" +"\tDas Gebiet wird in NXPE={:d} mal NYPE={:d} Gebiete der Größe localNx={:d} mal localNy={:d} aufgeteilt\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:357 +#, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -"\tFEHLER: {:d} Punkte in der Y-Richtung können nicht gleichmässig zwischen " -"{:d} Prozessen verteilt werden\n" +"\tFEHLER: {:d} Punkte in der Y-Richtung können nicht gleichmässig zwischen {:d} Prozessen verteilt werden\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:365 +#, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" -"\tFEHLER: {:d} Punkte in der Y-Richtung können nicht gleichmässig zwischen " -"{:d} Prozessen verteilt werden\n" +"\tFEHLER: {:d} Punkte in der Y-Richtung können nicht gleichmässig zwischen {:d} Prozessen verteilt werden\n" #: ../src/sys/options/options_ini.cxx:200 -#, fuzzy, c++-format +#, c++-format msgid "" "\tEmpty key\n" "\tLine: {:s}" @@ -152,41 +154,45 @@ msgstr "" "\tZeile: {:s}" #: ../src/sys/optionsreader.cxx:127 -#, fuzzy, c++-format +#, c++-format msgid "\tEmpty key or value in command line '{:s}'\n" -msgstr "\tSchlüssel (Key) oder Wert nicht gesetzt in der Befehlszeile '{:s}'\n" +msgstr "" +"\tSchlüssel (Key) oder Wert nicht gesetzt in der Befehlszeile '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" +"\tZusätzliche Debug-Ausgabe {}\n" -#: ../src/bout++.cxx:561 -#, fuzzy, c++-format +#: ../src/bout++.cxx:568 +#, c++-format msgid "\tFFT support {}\n" -msgstr "\tNetCDF Unterstützung ist aktiviert\n" +msgstr "" +"\tUnterstützung für FFT {}\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" +"\tVerfolgung von Feldnamen {}\n" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" +"\tGleitkomma-Ausnahmen {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "\tGittergröße: " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 -#, fuzzy +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " -msgstr "\tGuardzellen (x,y): " +msgstr "\tGuard-Zellen (x,y,z): " #: ../src/sys/options/options_ini.cxx:204 -#, fuzzy, c++-format +#, c++-format msgid "" "\tKey must not contain ':' character\n" "\tLine: {:s}" @@ -194,139 +200,156 @@ msgstr "" "\tDer Schlüssel darf nicht ':' enthalten\n" "\tZeile: {:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" +"\tUnterstützung für LAPACK {}\n" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" +"\tNachrichten-Stack {}\n" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" +"\tMetrikmodus ist {}\n" #: ../src/sys/optionsreader.cxx:111 -#, fuzzy, c++-format +#, c++-format msgid "\tMultiple '=' in command-line argument '{:s}'\n" -msgstr "\t'=' darf nicht mehrfach vorkommen: '{:s}'\n" +msgstr "" +"\t'=' darf nicht mehrfach vorkommen: '{:s}'\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" +"\tUnterstützung für natürliche Sprache {}\n" -#: ../src/bout++.cxx:567 -#, fuzzy, c++-format +#: ../src/bout++.cxx:574 +#, c++-format msgid "\tNetCDF support {}{}\n" -msgstr "\tNetCDF Unterstützung ist aktiviert\n" +msgstr "" +"\tUnterstützung für NetCDF {}{}\n" -#: ../src/bout++.cxx:577 -#, fuzzy, c++-format -msgid "\tOpenMP parallelisation {}" -msgstr "\tOpenMP Parallelisierung ist deaktiviert\n" +#: ../src/bout++.cxx:585 +#, c++-format +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "" +"\tOpenMP-Parallelisierung {}, mit {} Threads\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\tOption " -#: ../src/sys/options.cxx:447 -#, fuzzy, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "\tOption '{:s}': Boolscherwert erwartet, '{:s}' gefunden\n" +#: ../src/sys/options.cxx:369 +#, c++-format +msgid "\tOption {} = {}" +msgstr "\tOption {} = {}" #: ../src/sys/options/options_ini.cxx:70 -#, fuzzy, c++-format +#, c++-format msgid "\tOptions file '{:s}' not found\n" -msgstr "\tDie Optionendatei '{:s}' konnte nicht gefunden werden\n" +msgstr "" +"\tDie Optionendatei '{:s}' konnte nicht gefunden werden\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" +"\tUnterstützung für PETSc {}\n" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" +"\tUnterstützung für PVODE {}\n" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" -msgstr "\tParallele-NetCDF Unterstützung ist deaktiviert\n" +msgstr "" +"\tParallele-NetCDF Unterstützung ist deaktiviert\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" -msgstr "\tParllele-NetCDF Unterstützung ist aktiviert\n" +msgstr "" +"\tParllele-NetCDF Unterstützung ist aktiviert\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" +"\tUnterstützung für schönere Funktionsnamen {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" -msgstr "\tnz wird von der Griddatei gelesen\n" +msgstr "" +"\tnz wird von der Griddatei gelesen\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "\tKontravariantevektoren werden gelesen " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "\tKovariantevektoren werden gelesen " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" -msgstr "" +msgstr "\tPrüfung auf Laufzeitfehler {}" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" +"\tUnterstützung für SLEPc {}\n" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" +"\tUnterstützung für SUNDIALS {}\n" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" +"\tUnterstützung für Score-P {}\n" -#: ../src/bout++.cxx:584 -#, fuzzy, c++-format +#: ../src/bout++.cxx:589 +#, c++-format msgid "\tSignal handling support {}\n" -msgstr "\tSignalverarbeitung ist deaktiviert\n" +msgstr "" +"\tUnterstützung für Signalbehandlung {}\n" #: ../src/solver/impls/split-rk/split-rk.cxx:76 #, c++-format msgid "\tUsing a timestep {:e}\n" msgstr "" +"\tVerwende einen Zeitschritt von {:e}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" -msgstr "\tfertig\n" +msgstr "" +"\tfertig\n" #: ../src/solver/impls/split-rk/split-rk.cxx:41 msgid "" "\n" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" +"\n" +"\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" -#: ../src/bout++.cxx:371 -#, fuzzy +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -339,22 +362,24 @@ msgstr "" "\n" " -d \tEin- und Ausgabedateien sind im \n" " -f \tOptinen werden aus der gelesen\n" -" -o \tGenutzte Optionen werden in der " -" gespeichert\n" +" -o \tGenutzte Optionen werden in der gespeichert\n" " -l, --log \tSchreibe das Log in die \n" " -v, --verbose\t\tWortreicherer Ausgabe\n" " -q, --quiet\t\tNur wichtigere Ausgaben anzeigen\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" " {1: ^{2}}{0}\n" " Did you mean '{0}'?" msgstr "" +"\n" +" {1: ^{2}}{0}\n" +" Meinten Sie '{0}'?" -#: ../src/solver/solver.cxx:580 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:586 +#, c++-format msgid "" "\n" "Run finished at : {:s}\n" @@ -362,8 +387,8 @@ msgstr "" "\n" "Simulation beendet um {:s}\n" -#: ../src/solver/solver.cxx:532 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:540 +#, c++-format msgid "" "\n" "Run started at : {:s}\n" @@ -374,7 +399,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -401,8 +426,32 @@ msgid "" "\n" "{}" msgstr "" +"\n" +"There were unused input options:\n" +"-----\n" +"{:i}\n" +"-----\n" +"It's possible you've mistyped some options. BOUT++ input arguments are\n" +"now case-sensitive, and some have changed name. You can try running\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"to automatically fix the most common issues. If these options above\n" +"are sometimes used depending on other options, you can call\n" +"`Options::setConditionallyUsed()`, for example:\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"to mark a section or value as depending on other values, and so ignore\n" +"it in this check. Alternatively, if you're sure the above inputs are\n" +"not a mistake, you can set 'input:error_on_unused_options=false' to\n" +"turn off this check for unused options. You can always set\n" +"'input:validate=true' to check inputs without running the full\n" +"simulation.\n" +"\n" +"{}" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -434,62 +483,84 @@ msgid "" "For all possible input parameters, see the user manual and/or the physics " "model source (e.g. {:s}.cxx)\n" msgstr "" +" --print-config\t\tPrint the compile-time configuration\n" +" --list-solvers\t\tList the available time solvers\n" +" --help-solver \tPrint help for the given time solver\n" +" --list-laplacians\t\tList the available Laplacian inversion solvers\n" +" --help-laplacian \tPrint help for the given Laplacian inversion solver\n" +" --list-laplacexz\t\tList the available LaplaceXZ inversion solvers\n" +" --help-laplacexz \tPrint help for the given LaplaceXZ inversion solver\n" +" --list-invertpars\t\tList the available InvertPar solvers\n" +" --help-invertpar \tPrint help for the given InvertPar solver\n" +" --list-rkschemes\t\tList the available Runge-Kutta schemes\n" +" --help-rkscheme \tPrint help for the given Runge-Kutta scheme\n" +" --list-meshes\t\t\tList the available Meshes\n" +" --help-mesh \t\tPrint help for the given Mesh\n" +" --list-xzinterpolations\tList the available XZInterpolations\n" +" --help-xzinterpolation \tPrint help for the given XZInterpolation\n" +" --list-zinterpolations\tList the available ZInterpolations\n" +" --help-zinterpolation \tPrint help for the given ZInterpolation\n" +" -h, --help\t\t\tThis message\n" +" restart [append]\t\tRestart the simulation. If append is specified, append to the existing output files, otherwise overwrite them\n" +" VAR=VALUE\t\t\tSpecify a VALUE for input parameter VAR\n" +"\n" +"For all possible input parameters, see the user manual and/or the physics model source (e.g. {:s}.cxx)\n" -#: ../src/bout++.cxx:379 -#, fuzzy +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" -msgstr " -c, --color\t\tFarbliche Ausgabe mit bout-log-color\n" +msgstr "" +" -c, --color\t\tFarbliche Ausgabe mit bout-log-color\n" -#: ../include/bout/options.hxx:823 -#, fuzzy +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" -msgstr ") überschrieben mit {:s}" +msgstr ") überschrieben mit:" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" -msgstr "" - -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" +msgstr ", level {}" #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" -msgstr "" +msgstr "4 of 8" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" -msgstr "Alle genutzten Optionen\n" +msgstr "" +"Alle genutzten Optionen\n" -#: ../src/bout++.cxx:528 -#, fuzzy, c++-format +#: ../src/bout++.cxx:535 +#, c++-format msgid "BOUT++ version {:s}\n" -msgstr "BOUT++ Version {:s}\n" +msgstr "" +"BOUT++ Version {:s}\n" -#: ../src/bout++.cxx:143 -#, fuzzy +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" -msgstr "\t'=' darf nicht mehrfach vorkommen: '{:s}'\n" +msgstr "" +"Bad command line arguments:\n" + +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "Boolean operator argument {:e} is not a bool" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "Randgebiete auf diesem Prozessor: " -#: ../src/mesh/impls/bout/boutmesh.cxx:355 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:348 +#, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -"{:d} Punkte in der X-Richtung können nicht gleichmässig zwischen {:d} " -"Prozessen verteilt werden\n" +"{:d} Punkte in der X-Richtung können nicht gleichmässig zwischen {:d} Prozessen verteilt werden\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." -msgstr "" +msgstr "Check if a file exists, and exit if it does." -#: ../src/bout++.cxx:533 -#, fuzzy, c++-format +#: ../src/bout++.cxx:540 +#, c++-format msgid "" "Code compiled on {:s} at {:s}\n" "\n" @@ -501,62 +572,59 @@ msgstr "" msgid "Command line" msgstr "Befehlszeile" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" -msgstr "Kompiliert mit:\n" +msgstr "" +"Kompiliert mit:\n" #: ../tests/unit/src/test_bout++.cxx:362 -#, fuzzy msgid "Compiled with flags" -msgstr "\tWurde kompiliert mit den Optionen : {:s}\n" +msgstr "Compiled with flags" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "Standardregionen werden erstellt" -#: ../src/bout++.cxx:520 -#, fuzzy, c++-format +#: ../src/bout++.cxx:527 +#, c++-format msgid "Could not create PID file {:s}" -msgstr "Die Ausgabedatei '{:s}' konnte nicht geöffnet werden\n" +msgstr "PID-Datei {:s} konnte nicht erstellt werden" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." -msgstr "" -"Es konnte keine gültige Anzahl an Prozessoren in X Richtung gefunden werden " -"(NXPE). Versuche es mit einer anderen Zahl an Prozessoren." +msgstr "Es konnte keine gültige Anzahl an Prozessoren in X Richtung gefunden werden (NXPE). Versuche es mit einer anderen Zahl an Prozessoren." #: ../src/sys/options/options_ini.cxx:160 -#, fuzzy, c++-format +#, c++-format msgid "Could not open output file '{:s}'\n" -msgstr "Die Ausgabedatei '{:s}' konnte nicht geöffnet werden\n" +msgstr "" +"Die Ausgabedatei '{:s}' konnte nicht geöffnet werden\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" -msgstr "" +msgstr "Konnte {:s}/{:s}.{:d} nicht zum Schreiben öffnen" #. Error reading -#: ../src/mesh/mesh.cxx:532 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:543 +#, c++-format msgid "Could not read integer array '{:s}'\n" -msgstr "Der Ganzzahlen-Array '{:s}' konnte nicht gelesen werden\n" +msgstr "" +"Der Ganzzahlen-Array '{:s}' konnte nicht gelesen werden\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -"Der Befehl 'bout-log-color' konnte nicht ausgeführt werden. Stellen Sie " -"sicher, dass er sich in $PATH befindet.\n" +"Der Befehl 'bout-log-color' konnte nicht ausgeführt werden. Stellen Sie sicher, dass er sich in $PATH befindet.\n" -#: ../src/solver/solver.cxx:765 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:772 +#, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" -msgstr "" -"'Monitor' konnte nicht hinzugefügt werden: {:g} ist nicht ein Vielfaches von " -"{:g}!" +msgstr "'Monitor' konnte nicht hinzugefügt werden: {:g} ist nicht ein Vielfaches von {:g}!" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -564,179 +632,182 @@ msgid "" "may need to change your input file.\n" "{}" msgstr "" +"Generator '{}' konnte nicht gefunden werden. BOUT++-Ausdrücke unterscheiden nun zwischen Groß- und Kleinschreibung, daher\n" +"müssen Sie möglicherweise Ihre Eingabedatei ändern.\n" +"{}" -#: ../src/mesh/mesh.cxx:568 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:587 +#, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "Die Region '{:s}' ist nicht in regionMap2D" -#: ../src/mesh/mesh.cxx:560 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 +#, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "Die Region '{:s}' ist nicht in regionMap3D" -#: ../src/mesh/mesh.cxx:576 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:595 +#, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "Die Region '{:s}' ist nicht in regionMapPerp" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:361 +#, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" -msgstr "" -"Die Option {:s} = '{:s}' konnte nicht als ganze Zahl interpretiert werden." +msgstr "{} konnte nicht aus der Option {:s} = '{:s}' gelesen werden: {}" -#: ../src/bout++.cxx:508 -#, fuzzy, c++-format +#: ../src/bout++.cxx:515 +#, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" -msgstr "Der Datenordner \"{:s}\" existiert nicht oder ist nicht lesbar\n" +msgstr "" +"Der Datenordner \"{:s}\" existiert nicht oder ist nicht lesbar\n" -#: ../src/bout++.cxx:505 -#, fuzzy, c++-format +#: ../src/bout++.cxx:512 +#, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "" "\"{:s}\" soll als Datenordner verwendet werden, ist jedoch kein Ordner\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" -msgstr "FEHLER: Der Integrator ist bereits initialisiert.\n" +msgstr "" +"FEHLER: Der Integrator ist bereits initialisiert.\n" -#: ../src/bout++.cxx:209 -#, fuzzy, c++-format +#: ../src/bout++.cxx:216 +#, c++-format msgid "Error encountered during initialisation: {:s}\n" -msgstr "Es wurde ein Fehler während der Initialisierung gefunden: {:s}\n" +msgstr "" +"Es wurde ein Fehler während der Initialisierung gefunden: {:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "Es wurde ein Fehler beim Schreiben der Einstellungsdatei gefunden" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:323 +#, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "Fehler: nx muss größer als 2 mal MXG sein (2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" -"Der Integrator konnte nicht initialisiert werden. Der Prozess wird " -"abgebrochen\n" +"Der Integrator konnte nicht initialisiert werden. Der Prozess wird abgebrochen\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:281 +#, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" -msgstr "Suche NXPE Wert (optimal = {:f})\n" +msgstr "" +"Suche NXPE Wert (optimal = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" -msgstr "initialisiere den Integrator\n" +msgstr "" +"initialisiere den Integrator\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" msgstr "" -"Optionendatei (Eingabe) und Einstellungsdatei (Ausgabe) müssen verschieden " -"sein.\n" +"Optionendatei (Eingabe) und Einstellungsdatei (Ausgabe) müssen verschieden sein.\n" "Verwende -o .\n" #: ../src/sys/optionsreader.cxx:76 msgid "Invalid command line option '-' found - maybe check whitespace?" -msgstr "" +msgstr "Invalid command line option '-' found - maybe check whitespace?" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "Lade das Gitter" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "Das Gitter muss nx enthalten" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "Das Gitter muss ny enthalten" #. Not found -#: ../src/mesh/mesh.cxx:536 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:547 +#, c++-format msgid "Missing integer array {:s}\n" -msgstr "Ganzzahlen-Array '{:s}' nicht gesetzt\n" +msgstr "" +"Ganzzahlen-Array '{:s}' nicht gesetzt\n" -#: ../src/solver/solver.cxx:905 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:911 +#, c++-format msgid "Monitor signalled to quit (exception {})\n" -msgstr "Beendigung durch Monitor\n" +msgstr "" +"Monitor signalisierte Beenden (Ausnahme {})\n" -#: ../src/solver/solver.cxx:883 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:889 +#, c++-format msgid "Monitor signalled to quit (return code {})" -msgstr "Der Monitor signaliserte die Beendigung" +msgstr "Monitor signalisierte Beenden (Rückgabecode {})" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" -msgstr "" +msgstr "Name of file whose existence triggers a stop" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "Keine Randregionen auf diesem Prozessor" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 -#, fuzzy +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" -msgstr "Keine Randregionen auf diesem Prozessor" +msgstr "" +"Keine Randregionen; Domäne ist periodisch\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:245 +#, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -"Anzahl an Prozessoren ({:d}) nicht teilbar durch Anzahl in x Richtung " -"({:d})\n" +"Anzahl an Prozessoren ({:d}) nicht teilbar durch Anzahl in x Richtung ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:258 +#, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" -"Anzahl an Prozessoren ({:d}) nicht teilbar durch Anzahl in x Richtung " -"({:d})\n" +"Anzahl an Prozessoren ({:d}) nicht teilbar durch Anzahl in x Richtung ({:d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 -#, fuzzy, c++-format +#: ../src/bout++.cxx:908 +#, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" -msgstr "Nur noch {:e} Sekunden verfügbar. Abbruch\n" +msgstr "" +"Nur noch {:e} Sekunden ({:.2f} Schritte) übrig. Beende\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 +#, c++-format msgid "Option {:s} has no value" msgstr "Der Option '{:s}' wurde kein Wert zugewiesen" #. Doesn't exist -#: ../src/sys/options.cxx:159 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:172 +#, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "Die Option {:s}:{:s} exisitiert nicht" -#: ../include/bout/options.hxx:828 -#, fuzzy, c++-format +#: ../include/bout/options.hxx:904 +#, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." -msgstr "" -"Optionen: Der Wert {2:s} wird mit dem Wert {1:s} gleichen Ursprungs ({0:s}) " -"überschrieben." +msgstr "Optionen: Setze einen Wert aus derselben Quelle ({:s}) auf den neuen Wert '{:s}' - der alte Wert war '{:s}'." -#: ../src/mesh/impls/bout/boutmesh.cxx:552 -#, fuzzy +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "Keine Randregionen auf diesem Prozessor" -#: ../src/bout++.cxx:538 -#, fuzzy, c++-format +#: ../src/bout++.cxx:545 +#, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" @@ -744,32 +815,33 @@ msgstr "" "Prozessorennummer: {:d} von {:d}\n" "\n" -#: ../src/mesh/mesh.cxx:609 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:642 +#, c++-format msgid "Registered region 2D {:s}" msgstr "2D Region '{:s}' hinzugefügt" -#: ../src/mesh/mesh.cxx:599 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:632 +#, c++-format msgid "Registered region 3D {:s}" msgstr "3D Region '{:s}' hinzugefügt" -#: ../src/mesh/mesh.cxx:619 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:652 +#, c++-format msgid "Registered region Perp {:s}" msgstr "Perp Region '{:s}' hinzugefügt" -#: ../src/bout++.cxx:529 -#, fuzzy, c++-format +#: ../src/bout++.cxx:536 +#, c++-format msgid "Revision: {:s}\n" -msgstr "Revision: {:s}\n" +msgstr "" +"Revision: {:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "Dauer: " #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -779,77 +851,73 @@ msgstr "" #: ../tests/unit/src/test_bout++.cxx:359 msgid "Signal" -msgstr "" +msgstr "Signal" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -"Simu Zeit | RHS Berech. | Echtdauer | Rechnen Inver Komm I/O " -"Integrator\n" +"Simu Zeit | RHS Berech. | Echtdauer | Rechnen Inver Komm I/O Integrator\n" "\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -"Simu Zeit | #expl RHS | #impl RHS | Echtdauer | Rechnen Inv " -"Komm I/O Integrator\n" +"Simu Zeit | #expl RHS | #impl RHS | Echtdauer | Rechnen Inv Komm I/O Integrator\n" "\n" -#: ../src/solver/solver.cxx:506 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:514 +#, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -"Integriere mit einem `Monitor`-Zeitschritt von {1:e} für {0:d} Aufrufe.\n" +"Solver läuft für {:d} Ausgaben mit einem Monitor-Zeitschritt von {:e}\n" -#: ../src/solver/solver.cxx:502 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:510 +#, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" -msgstr "Integriere {:d} Zeitschritte von je {:e}\n" +msgstr "" +"Integriere {:d} Zeitschritte von je {:e}\n" -#: ../src/solver/solver.cxx:781 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:788 +#, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" -msgstr "" -"Der Integrator kann den Zeitschritt nicht von {:g} auf {:g} reduzieren, " -"nachdem er initialisiert wurde!" +msgstr "Der Integrator kann den Zeitschritt nicht von {:g} auf {:g} reduzieren, nachdem er initialisiert wurde!" -#: ../src/solver/solver.cxx:1281 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:1289 +#, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -"Die zeitliche Ableitung ist an der falschen Stelle. Das Feld '{2:s}' ist an " -"Position {0:s}, während die Ableitung an Position {1:s} ist.\n" +"Zeitliche Ableitung an falscher Stelle - Feld ist bei {:s}, Ableitung ist bei {:s} für Feld '{:s}'\n" -#: ../src/solver/solver.cxx:1480 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:1494 +#, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "Zeitliche Ableitung für Variable '{:s}' nicht gesetzt" -#: ../src/mesh/mesh.cxx:605 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:638 +#, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "Die Region '{:s}' ist bereits vorhanden in der regionMap2D" -#: ../src/mesh/mesh.cxx:595 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:614 +#, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "Die Region '{:s}' ist bereits vorhanden in der regionMap3D" -#: ../src/mesh/mesh.cxx:616 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:649 +#, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "Die Region '{:s}' ist bereits vorhanden in der regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -857,8 +925,10 @@ msgid "" "This is likely the result of clashing input options, and you may have to " "rename one of them.\n" msgstr "" +"Es wird versucht, Option '{0}' mit '{1}' zu indizieren, aber '{0}' ist ein Wert und kein Abschnitt.\n" +"Dies ist wahrscheinlich das Ergebnis kollidierender Eingabeoptionen, und Sie müssen möglicherweise eine davon umbenennen.\n" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -866,155 +936,177 @@ msgstr "" "Unbekannte Paralleltransformation\n" "Gültige Optionen sind 'identity', 'shifted', 'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" -msgstr "Ungenutzte Optionen:\n" +msgstr "" +"Ungenutzte Optionen:\n" -#: ../src/bout++.cxx:439 -#, fuzzy, c++-format +#: ../src/bout++.cxx:446 +#, c++-format msgid "Usage is {:s} -d \n" -msgstr "Benutzung: {:s} -d \n" +msgstr "" +"Benutzung: {:s} -d \n" -#: ../src/bout++.cxx:448 -#, fuzzy, c++-format +#: ../src/bout++.cxx:455 +#, c++-format msgid "Usage is {:s} -f \n" -msgstr "Benutzung: {:s} -f \n" +msgstr "" +"Benutzung: {:s} -f \n" -#: ../src/bout++.cxx:466 -#, fuzzy, c++-format +#: ../src/bout++.cxx:473 +#, c++-format msgid "Usage is {:s} -l \n" -msgstr "Benutzung: {:s} -f \n" +msgstr "" +"Benutzung: {:s} -f \n" -#: ../src/bout++.cxx:457 -#, fuzzy, c++-format +#: ../src/bout++.cxx:464 +#, c++-format msgid "Usage is {:s} -o \n" -msgstr "Benutzung: {:s} -f \n" +msgstr "" +"Benutzung: {:s} -f \n" -#: ../src/bout++.cxx:353 -#, fuzzy, c++-format +#: ../src/bout++.cxx:360 +#, c++-format msgid "Usage is {} {} \n" -msgstr "Benutzung: {:s} -f \n" +msgstr "" +"Verwendung: {} {} \n" #: ../tests/unit/src/test_bout++.cxx:32 ../tests/unit/src/test_bout++.cxx:46 msgid "Usage:" -msgstr "" +msgstr "Usage:" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 -#, fuzzy, c++-format +#: ../src/bout++.cxx:374 +#, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " "[VAR=VALUE]\n" msgstr "" -"Benutzung: {:s} [-d ] [-f ] [restart [append]] " -"[VAR=WERT]\n" +"Benutzung: {:s} [-d ] [-f ] [restart [append]] [VAR=WERT]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 -#, fuzzy +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" -msgstr "Beendigung durch Monitor\n" +msgstr "" +"Beendigung durch Monitor\n" -#: ../src/sys/options.cxx:373 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" + +#: ../src/sys/options.cxx:426 +#, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" -msgstr "" +msgstr "Wert für Option {:s} kann nicht in ein BoutReal umgewandelt werden" -#: ../src/sys/options.cxx:581 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:623 +#, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} kann nicht in ein Field2D umgewandelt werden" -#: ../src/sys/options.cxx:529 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:571 +#, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} kann nicht in ein Field3D umgewandelt werden" -#: ../src/sys/options.cxx:663 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:705 +#, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} kann nicht in ein FieldPerp umgewandelt werden" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" -msgstr "" +msgstr "Wert für Option {:s} kann nicht in ein bool umgewandelt werden" -#: ../src/sys/options.cxx:709 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:751 +#, c++-format msgid "Value for option {:s} cannot be converted to an Array" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} kann nicht in ein Array umgewandelt werden" -#: ../src/sys/options.cxx:736 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:773 +#, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} kann nicht in eine Matrix umgewandelt werden" -#: ../src/sys/options.cxx:763 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:795 +#, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} kann nicht in einen Tensor umgewandelt werden" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:418 +#, c++-format msgid "Value for option {:s} is not an integer" -msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" +msgstr "Wert für Option {:s} ist keine Ganzzahl" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 +#, c++-format msgid "Variable '{:s}' not initialised" msgstr "Variable '{:s}' ist nicht initialisiert" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:467 +#, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -"WARNUNG: Anzahl der toroidalen Punkte sollte 2^n für effiziente FFTs sein. " -"Ändere MZ falls FFTs verwendet werden\n" +"WARNUNG: Die Anzahl toroidaler Punkte sollte für effiziente FFT-Leistung 2^n sein -- ziehen Sie eine Änderung von MZ ({:d}) in Betracht, wenn Sie FFTs verwenden\n" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" +"WARNING: extrapolating input mesh quantities into x-boundary cells\n" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" +"WARNING: extrapolating input mesh quantities into x-boundary cells. Set option extrapolate_x=false to disable this.\n" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" +"WARNING: extrapolating input mesh quantities into y-boundary cells\n" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" +"WARNING: extrapolating input mesh quantities into y-boundary cells. Set option extrapolate_y=false to disable this.\n" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" -msgstr "" +msgstr "Wall time limit in hours. By default (< 0), no limit" #: ../src/sys/optionsreader.cxx:42 -#, fuzzy, c++-format +#, c++-format msgid "Writing options to file {:s}\n" -msgstr "Optionen werden in {:s} gespeichert\n" +msgstr "" +"Optionen werden in {:s} gespeichert\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "Vorgabe" +#, fuzzy, c++-format +#~ msgid "\tOpenMP parallelisation {}" +#~ msgstr "\tOpenMP Parallelisierung ist deaktiviert\n" + +#, fuzzy, c++-format +#~ msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +#~ msgstr "\tOption '{:s}': Boolscherwert erwartet, '{:s}' gefunden\n" + #~ msgid "\tChecking disabled\n" #~ msgstr "\tChecks sind deaktiviert\n" @@ -1022,10 +1114,6 @@ msgstr "Vorgabe" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\tChecks der Stufe {:d} sind aktiviert\n" -#, fuzzy -#~ msgid "\tOpenMP parallelisation enabled, using {:d} threads\n" -#~ msgstr "\tOpenMP Parallelisierung mit {:d} Threads ist aktiviert\n" - #~ msgid "\tSignal handling enabled\n" #~ msgstr "\tSignalverarbeitung ist aktiviert\n" @@ -1051,8 +1139,8 @@ msgstr "Vorgabe" #~ "überschrieben. Benötigt `restart`\n" #~ " VAR=WERT \t\tSetzt den Wert WERT für die Variable VAR\n" #~ "\n" -#~ "Weitere Eingabeparameter sind in dem Manual und dem Quellcode (z.B. {:s}." -#~ "cxx) des Physikmoduls definiert.\n" +#~ "Weitere Eingabeparameter sind in dem Manual und dem Quellcode (z.B. " +#~ "{:s}.cxx) des Physikmoduls definiert.\n" #, fuzzy #~ msgid "Couldn't get BoutReal from option {:s} = '{:s}'" diff --git a/locale/es/libbout.po b/locale/es/libbout.po index 8a3b22be61..3346bd882e 100644 --- a/locale/es/libbout.po +++ b/locale/es/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2019-02-11 12:46+0900\n" "Last-Translator: Marta \n" "Language-Team: Spanish\n" @@ -16,132 +16,134 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:182 +#, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -"\t -> La región `Core` jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) debe ser un " -"múltiplo de MYSUB ({:d})\n" +"\t -> La región `Core` jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -"\t -> La región `Core` jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) debe ser un " -"múltiplo de MYSUB ({:d})\n" +"\t -> La región `Core` jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:190 +#, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -"\t -> La región `Core` jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) debe ser un " -"múltiplo de MYSUB ({:d})\n" +"\t -> La región `Core` jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" -msgstr "\t -> El valor es bueno\n" +msgstr "" +"\t -> El valor es bueno\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:171 +#, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -"\t -> La región `Leg` jyseps1_1+1 ({:d}) debe ser un múltiplo de MYSUB " -"({:d})\n" +"\t -> La región `Leg` jyseps1_1+1 ({:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:206 +#, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -"\t -> La región `Leg` jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) debe ser un " -"múltiplo de MYSUB ({:d})\n" +"\t -> La región `Leg` jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:223 +#, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -"\t -> La región `Leg` ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) debe ser un " -"múltiplo de MYSUB ({:d})\n" +"\t -> La región `Leg` ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -"\t -> La región `Leg` ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) debe ser un " -"múltiplo de MYSUB ({:d})\n" +"\t -> La región `Leg` ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) debe ser un múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:166 +#, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" -msgstr "\t -> ny/NYPE ({:d}/{:d} = {:d}) debe ser >= MYG ({:d})\n" +msgstr "" +"\t -> ny/NYPE ({:d}/{:d} = {:d}) debe ser >= MYG ({:d})\n" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" +"\tCompatibilidad con ADIOS2 {}\n" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" +"\tTraza inversa en excepciones {}\n" #. Loop over all possibilities #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:288 +#, c++-format msgid "\tCandidate value: {:d}\n" -msgstr "\tValor candidato: {:d}\n" +msgstr "" +"\tValor candidato: {:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" +"\tColor en los registros {}\n" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "\tParámetros de línea de comandos para esta ejecución :" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 -#, fuzzy, c++-format +#: ../src/bout++.cxx:595 +#, c++-format msgid "\tCompiled with flags : {:s}\n" -msgstr "\tCompilado con las opciones `flags` : {:s}\n" +msgstr "" +"\tCompilado con las opciones `flags` : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:315 +#, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" -"\tDominio separado (NXPE={:d}, NYPE={:d}) en los dominios (localNx={:d}, " -"localNy={:d})\n" +"\tDominio separado (NXPE={:d}, NYPE={:d}) en los dominios (localNx={:d}, localNy={:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:357 +#, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -"\tERROR: No se pueden separar {:d} Y puntos entre {:d} procesadores por " -"igual\n" +"\tERROR: No se pueden separar {:d} Y puntos entre {:d} procesadores por igual\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:365 +#, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" -"\tERROR: No se pueden separar {:d} Y puntos entre {:d} procesadores por " -"igual\n" +"\tERROR: No se pueden separar {:d} Y puntos entre {:d} procesadores por igual\n" #: ../src/sys/options/options_ini.cxx:200 -#, fuzzy, c++-format +#, c++-format msgid "" "\tEmpty key\n" "\tLine: {:s}" @@ -150,41 +152,45 @@ msgstr "" "\tLínea: {:s}" #: ../src/sys/optionsreader.cxx:127 -#, fuzzy, c++-format +#, c++-format msgid "\tEmpty key or value in command line '{:s}'\n" -msgstr "\tEntrada o valor vacío en la línea de comandos '{:s}'\n" +msgstr "" +"\tEntrada o valor vacío en la línea de comandos '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" +"\tSalida adicional de depuración {}\n" -#: ../src/bout++.cxx:561 -#, fuzzy, c++-format +#: ../src/bout++.cxx:568 +#, c++-format msgid "\tFFT support {}\n" -msgstr "\tSoporte netCDF activado\n" +msgstr "" +"\tCompatibilidad con FFT {}\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" +"\tSeguimiento del nombre de campo {}\n" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" +"\tExcepciones de punto flotante {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "\tTamaño de la malla (`grid`): " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 -#, fuzzy +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " -msgstr "\tProteger celdas (x,y): " +msgstr "\tCeldas de guarda (x,y,z): " #: ../src/sys/options/options_ini.cxx:204 -#, fuzzy, c++-format +#, c++-format msgid "" "\tKey must not contain ':' character\n" "\tLine: {:s}" @@ -192,139 +198,156 @@ msgstr "" "\tLa entrada no debe contener el carácter ':'\n" "\tLínea: {:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" +"\tCompatibilidad con LAPACK {}\n" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" +"\tPila de mensajes {}\n" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" +"\tEl modo de métricas es {}\n" #: ../src/sys/optionsreader.cxx:111 -#, fuzzy, c++-format +#, c++-format msgid "\tMultiple '=' in command-line argument '{:s}'\n" -msgstr "\tMutilples '=' en el argumento de la línea de comandos '{:s}'\n" +msgstr "" +"\tMutilples '=' en el argumento de la línea de comandos '{:s}'\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" +"\tCompatibilidad con lenguaje natural {}\n" -#: ../src/bout++.cxx:567 -#, fuzzy, c++-format +#: ../src/bout++.cxx:574 +#, c++-format msgid "\tNetCDF support {}{}\n" -msgstr "\tSoporte netCDF activado\n" +msgstr "" +"\tCompatibilidad con NetCDF {}{}\n" -#: ../src/bout++.cxx:577 -#, fuzzy, c++-format -msgid "\tOpenMP parallelisation {}" -msgstr "\tParalelización en OpenMP desactivada\n" +#: ../src/bout++.cxx:585 +#, c++-format +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "" +"\tParalelización con OpenMP {}, usando {} hilos\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\tOpción " -#: ../src/sys/options.cxx:447 -#, fuzzy, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "\tOpción '{:s}': valor Booleano esperado. Se obtuvo '{:s}'\n" +#: ../src/sys/options.cxx:369 +#, c++-format +msgid "\tOption {} = {}" +msgstr "\tOpción {} = {}" #: ../src/sys/options/options_ini.cxx:70 -#, fuzzy, c++-format +#, c++-format msgid "\tOptions file '{:s}' not found\n" -msgstr "\tOpciones de archivo '{:s}' no encontrados\n" +msgstr "" +"\tOpciones de archivo '{:s}' no encontrados\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" +"\tCompatibilidad con PETSc {}\n" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" +"\tCompatibilidad con PVODE {}\n" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" -msgstr "\tSoporte para NetCDF paralelo desactivado\n" +msgstr "" +"\tSoporte para NetCDF paralelo desactivado\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" -msgstr "\tSoporte para NetCDF paralelo activado\n" +msgstr "" +"\tSoporte para NetCDF paralelo activado\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" +"\tCompatibilidad con nombres de función detallados {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" -msgstr "\tLeer nz del archivo input de la malla `grid`\n" +msgstr "" +"\tLeer nz del archivo input de la malla `grid`\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "\tLeyendo vector contravariante " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "\tLeyendo vector covariante " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" -msgstr "" +msgstr "\tComprobación de errores en tiempo de ejecución {}" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" +"\tCompatibilidad con SLEPc {}\n" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" +"\tCompatibilidad con SUNDIALS {}\n" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" +"\tCompatibilidad con Score-P {}\n" -#: ../src/bout++.cxx:584 -#, fuzzy, c++-format +#: ../src/bout++.cxx:589 +#, c++-format msgid "\tSignal handling support {}\n" -msgstr "\tGestión de señal desactivada\n" +msgstr "" +"\tCompatibilidad con manejo de señales {}\n" #: ../src/solver/impls/split-rk/split-rk.cxx:76 #, c++-format msgid "\tUsing a timestep {:e}\n" msgstr "" +"\tUsando un paso de tiempo {:e}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" -msgstr "\tlisto\n" +msgstr "" +"\tlisto\n" #: ../src/solver/impls/split-rk/split-rk.cxx:41 msgid "" "\n" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" +"\n" +"\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" -#: ../src/bout++.cxx:371 -#, fuzzy +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -337,22 +360,24 @@ msgstr "" "\n" " -d \tBuscar en los archivos input/output\n" " -f \tUsar OPCIONES descritas en \n" -" -o \tGuardar OPCIONES usadas descritas en \n" +" -o \tGuardar OPCIONES usadas descritas en \n" " -l, --log \tImprimir registro `log` en \n" " -v, --verbose\t\tAumentar verbosidad\n" " -q, --quiet\t\tDisminuir verbosidad\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" " {1: ^{2}}{0}\n" " Did you mean '{0}'?" msgstr "" +"\n" +" {1: ^{2}}{0}\n" +" ¿Quiso decir '{0}'?" -#: ../src/solver/solver.cxx:580 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:586 +#, c++-format msgid "" "\n" "Run finished at : {:s}\n" @@ -360,8 +385,8 @@ msgstr "" "\n" "Ejecución finalizada en : {:s}\n" -#: ../src/solver/solver.cxx:532 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:540 +#, c++-format msgid "" "\n" "Run started at : {:s}\n" @@ -372,7 +397,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -399,8 +424,32 @@ msgid "" "\n" "{}" msgstr "" +"\n" +"There were unused input options:\n" +"-----\n" +"{:i}\n" +"-----\n" +"It's possible you've mistyped some options. BOUT++ input arguments are\n" +"now case-sensitive, and some have changed name. You can try running\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"to automatically fix the most common issues. If these options above\n" +"are sometimes used depending on other options, you can call\n" +"`Options::setConditionallyUsed()`, for example:\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"to mark a section or value as depending on other values, and so ignore\n" +"it in this check. Alternatively, if you're sure the above inputs are\n" +"not a mistake, you can set 'input:error_on_unused_options=false' to\n" +"turn off this check for unused options. You can always set\n" +"'input:validate=true' to check inputs without running the full\n" +"simulation.\n" +"\n" +"{}" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -432,59 +481,84 @@ msgid "" "For all possible input parameters, see the user manual and/or the physics " "model source (e.g. {:s}.cxx)\n" msgstr "" +" --print-config\t\tPrint the compile-time configuration\n" +" --list-solvers\t\tList the available time solvers\n" +" --help-solver \tPrint help for the given time solver\n" +" --list-laplacians\t\tList the available Laplacian inversion solvers\n" +" --help-laplacian \tPrint help for the given Laplacian inversion solver\n" +" --list-laplacexz\t\tList the available LaplaceXZ inversion solvers\n" +" --help-laplacexz \tPrint help for the given LaplaceXZ inversion solver\n" +" --list-invertpars\t\tList the available InvertPar solvers\n" +" --help-invertpar \tPrint help for the given InvertPar solver\n" +" --list-rkschemes\t\tList the available Runge-Kutta schemes\n" +" --help-rkscheme \tPrint help for the given Runge-Kutta scheme\n" +" --list-meshes\t\t\tList the available Meshes\n" +" --help-mesh \t\tPrint help for the given Mesh\n" +" --list-xzinterpolations\tList the available XZInterpolations\n" +" --help-xzinterpolation \tPrint help for the given XZInterpolation\n" +" --list-zinterpolations\tList the available ZInterpolations\n" +" --help-zinterpolation \tPrint help for the given ZInterpolation\n" +" -h, --help\t\t\tThis message\n" +" restart [append]\t\tRestart the simulation. If append is specified, append to the existing output files, otherwise overwrite them\n" +" VAR=VALUE\t\t\tSpecify a VALUE for input parameter VAR\n" +"\n" +"For all possible input parameters, see the user manual and/or the physics model source (e.g. {:s}.cxx)\n" -#: ../src/bout++.cxx:379 -#, fuzzy +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" -msgstr " -c, --color\t\tSalida de color usando bout-log-color\n" +msgstr "" +" -c, --color\t\tSalida de color usando bout-log-color\n" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" -msgstr "" +msgstr ") sobrescrito con:" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" -msgstr "" - -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" +msgstr ", level {}" #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" -msgstr "" +msgstr "4 of 8" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" -msgstr "Usando todas las opciones\n" +msgstr "" +"Usando todas las opciones\n" -#: ../src/bout++.cxx:528 -#, fuzzy, c++-format +#: ../src/bout++.cxx:535 +#, c++-format msgid "BOUT++ version {:s}\n" -msgstr "Versión de BOUT++ {:s}\n" +msgstr "" +"Versión de BOUT++ {:s}\n" -#: ../src/bout++.cxx:143 -#, fuzzy +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" -msgstr "\tMutilples '=' en el argumento de la línea de comandos '{:s}'\n" +msgstr "" +"Bad command line arguments:\n" + +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "Boolean operator argument {:e} is not a bool" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "Regiones frontera en este procesador: " -#: ../src/mesh/impls/bout/boutmesh.cxx:355 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:348 +#, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" -msgstr "No se pueden dividir {:d} X points entre {:d} procesadores por igual\n" +msgstr "" +"No se pueden dividir {:d} X points entre {:d} procesadores por igual\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." -msgstr "" +msgstr "Check if a file exists, and exit if it does." -#: ../src/bout++.cxx:533 -#, fuzzy, c++-format +#: ../src/bout++.cxx:540 +#, c++-format msgid "" "Code compiled on {:s} at {:s}\n" "\n" @@ -496,60 +570,59 @@ msgstr "" msgid "Command line" msgstr "Línea de comandos" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" -msgstr "Opciones de tiempo de compilación:\n" +msgstr "" +"Opciones de tiempo de compilación:\n" #: ../tests/unit/src/test_bout++.cxx:362 -#, fuzzy msgid "Compiled with flags" -msgstr "\tCompilado con las opciones `flags` : {:s}\n" +msgstr "Compiled with flags" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "Construyendo regiones por defecto" -#: ../src/bout++.cxx:520 -#, fuzzy, c++-format +#: ../src/bout++.cxx:527 +#, c++-format msgid "Could not create PID file {:s}" -msgstr "No se pudo abrir el archivo de salida `output` '{:s}'\n" +msgstr "No se pudo crear el archivo PID {:s}" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." -msgstr "" -"No se pudo encontrar un valor válido para NXPE. Intente usar un número " -"diferente de procesadores." +msgstr "No se pudo encontrar un valor válido para NXPE. Intente usar un número diferente de procesadores." #: ../src/sys/options/options_ini.cxx:160 -#, fuzzy, c++-format +#, c++-format msgid "Could not open output file '{:s}'\n" -msgstr "No se pudo abrir el archivo de salida `output` '{:s}'\n" +msgstr "" +"No se pudo abrir el archivo de salida `output` '{:s}'\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" -msgstr "" +msgstr "No se pudo abrir {:s}/{:s}.{:d} para escritura" #. Error reading -#: ../src/mesh/mesh.cxx:532 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:543 +#, c++-format msgid "Could not read integer array '{:s}'\n" -msgstr "No se pudo leer la matriz de enteros '{:s}'\n" +msgstr "" +"No se pudo leer la matriz de enteros '{:s}'\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -"No se pudo ejecutar bout-log-color. Asegúrese de que se encuentre en su " -"PATH\n" +"No se pudo ejecutar bout-log-color. Asegúrese de que se encuentre en su PATH\n" -#: ../src/solver/solver.cxx:765 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:772 +#, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "No se pudo añadir el Monitor: {:g} no és multiplo de {:g}!" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -557,175 +630,182 @@ msgid "" "may need to change your input file.\n" "{}" msgstr "" +"No se pudo encontrar el generador '{}'. Las expresiones de BOUT++ ahora distinguen entre mayúsculas y minúsculas, por lo que\n" +"puede que tenga que cambiar su archivo de entrada.\n" +"{}" -#: ../src/mesh/mesh.cxx:568 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:587 +#, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "No se pudo encontrar la región {:s} en regionMap2D" -#: ../src/mesh/mesh.cxx:560 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 +#, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "No se pudo encontrar la región {:s} en regionMap2D" -#: ../src/mesh/mesh.cxx:576 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:595 +#, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "No se pudo encontrar la región {:s} en regionMapPerp" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:361 +#, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" -msgstr "No se pudo recuperar el entero de la opción {:s} = '{:s}'" +msgstr "No se pudo obtener {} de la opción {:s} = '{:s}': {}" -#: ../src/bout++.cxx:508 -#, fuzzy, c++-format +#: ../src/bout++.cxx:515 +#, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" -msgstr "DataDir \"{:s}\" no existe o no es accessible\n" +msgstr "" +"DataDir \"{:s}\" no existe o no es accessible\n" -#: ../src/bout++.cxx:505 -#, fuzzy, c++-format +#: ../src/bout++.cxx:512 +#, c++-format msgid "DataDir \"{:s}\" is not a directory\n" -msgstr "DataDir \"{:s}\" no es un directorio\n" +msgstr "" +"DataDir \"{:s}\" no es un directorio\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" -msgstr "ERROR: el Solver ya se encuentra inicializado\n" +msgstr "" +"ERROR: el Solver ya se encuentra inicializado\n" -#: ../src/bout++.cxx:209 -#, fuzzy, c++-format +#: ../src/bout++.cxx:216 +#, c++-format msgid "Error encountered during initialisation: {:s}\n" -msgstr "Error encontrado durante la inicialización:{:s}\n" +msgstr "" +"Error encontrado durante la inicialización:{:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "Error durante el paso de opciones" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:323 +#, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "Error: nx debe ser mayor que 2 veces MXG (2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" -msgstr "Fallo en inicializar el solver-> Abortando\n" +msgstr "" +"Fallo en inicializar el solver-> Abortando\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:281 +#, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" -msgstr "Encontrando valor para NXPE (ideal = {:f})\n" +msgstr "" +"Encontrando valor para NXPE (ideal = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" -msgstr "Initializando el solver\n" +msgstr "" +"Initializando el solver\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" msgstr "" -"Archivos de entrada y salida (`input/output`) para las opciones deben ser " -"diferentes.\n" +"Archivos de entrada y salida (`input/output`) para las opciones deben ser diferentes.\n" "Añada -o para evitar este problema.\n" #: ../src/sys/optionsreader.cxx:76 msgid "Invalid command line option '-' found - maybe check whitespace?" -msgstr "" +msgstr "Invalid command line option '-' found - maybe check whitespace?" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "Cargando malla `mesh`" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "La malla `mesh` debe contener nx" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "La malla `mesh` debe contener ny" #. Not found -#: ../src/mesh/mesh.cxx:536 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:547 +#, c++-format msgid "Missing integer array {:s}\n" -msgstr "Fala la matriz entera {:s}\n" +msgstr "" +"Fala la matriz entera {:s}\n" -#: ../src/solver/solver.cxx:905 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:911 +#, c++-format msgid "Monitor signalled to quit (exception {})\n" -msgstr "Monitor indicó salir\n" +msgstr "" +"El monitor indicó salir (excepción {})\n" -#: ../src/solver/solver.cxx:883 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:889 +#, c++-format msgid "Monitor signalled to quit (return code {})" -msgstr "Monitor indicó salir" +msgstr "El monitor indicó salir (código de retorno {})" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" -msgstr "" +msgstr "Name of file whose existence triggers a stop" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "Sin regiones de frontera en este procesador" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 -#, fuzzy +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" -msgstr "Sin regiones de frontera en este procesador" +msgstr "" +"No hay regiones de frontera; el dominio es periódico\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:245 +#, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -"Número de procesadores ({:d}) no divisible para NPs en la dirección x " -"({:d})\n" +"Número de procesadores ({:d}) no divisible para NPs en la dirección x ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:258 +#, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" -"Número de procesadores ({:d}) no divisible para NPs en la dirección x " -"({:d})\n" +"Número de procesadores ({:d}) no divisible para NPs en la dirección x ({:d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 -#, fuzzy, c++-format +#: ../src/bout++.cxx:908 +#, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" -msgstr "Solo faltan {:e} segundos. Saliendo\n" +msgstr "" +"Solo quedan {:e} segundos ({:.2f} pasos). Saliendo\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 +#, c++-format msgid "Option {:s} has no value" msgstr "Opción {:s} sin valor" #. Doesn't exist -#: ../src/sys/options.cxx:159 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:172 +#, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "Opción {:s}:{:s} no existe" -#: ../include/bout/options.hxx:828 -#, fuzzy, c++-format +#: ../include/bout/options.hxx:904 +#, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." -msgstr "" -"Opciones: Cambiando valor de la misma fuente ({:s}) al valor nuevo '{:s}' - " -"valor anterior era '{:s}'." +msgstr "Opciones: estableciendo un valor desde la misma fuente ({:s}) al nuevo valor '{:s}' - el valor anterior era '{:s}'." -#: ../src/mesh/impls/bout/boutmesh.cxx:552 -#, fuzzy +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "Sin regiones de frontera en este procesador" -#: ../src/bout++.cxx:538 -#, fuzzy, c++-format +#: ../src/bout++.cxx:545 +#, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" @@ -733,32 +813,33 @@ msgstr "" "Procesador número: {:d} de {:d}\n" "\n" -#: ../src/mesh/mesh.cxx:609 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:642 +#, c++-format msgid "Registered region 2D {:s}" msgstr "Región 2D registrada {:s}" -#: ../src/mesh/mesh.cxx:599 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:632 +#, c++-format msgid "Registered region 3D {:s}" msgstr "Región 3D registrada {:s}" -#: ../src/mesh/mesh.cxx:619 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:652 +#, c++-format msgid "Registered region Perp {:s}" msgstr "Región Perp registrada {:s}" -#: ../src/bout++.cxx:529 -#, fuzzy, c++-format +#: ../src/bout++.cxx:536 +#, c++-format msgid "Revision: {:s}\n" -msgstr "Revisión: {:s}\n" +msgstr "" +"Revisión: {:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "Tiempo de ejecución : " #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -768,80 +849,73 @@ msgstr "" #: ../tests/unit/src/test_bout++.cxx:359 msgid "Signal" -msgstr "" +msgstr "Signal" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -"Tiempo Sim | RHS eval. | Tiempo Wall | Calc Inv Com I/O " -"SOLVER\n" +"Tiempo Sim | RHS eval. | Tiempo Wall | Calc Inv Com I/O SOLVER\n" "\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -"Tiempo Sim | RHS_e eval. | RHS_I eval. | Tiempo Wall | Calc Inv " -"Com I/O SOLVER\n" +"Tiempo Sim | RHS_e eval. | RHS_I eval. | Tiempo Wall | Calc Inv Com I/O SOLVER\n" "\n" -#: ../src/solver/solver.cxx:506 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:514 +#, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -"Solver corriendo para {:d} outputs con intervalos de tiempo de monitor de " -"{:e}\n" +"El solucionador se ejecuta para {:d} salidas con un paso de tiempo de monitor de {:e}\n" -#: ../src/solver/solver.cxx:502 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:510 +#, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -"Solver corriendo para {:d} outputs con intervalos de tiempo de output de " -"{:e}\n" +"Solver corriendo para {:d} outputs con intervalos de tiempo de output de {:e}\n" -#: ../src/solver/solver.cxx:781 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:788 +#, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" -msgstr "" -"Solver::addMonitor: No se puedo reducir el intervalo de tiempo (de {:g} a " -"{:g}) después de que init fuera llamado!" +msgstr "Solver::addMonitor: No se puedo reducir el intervalo de tiempo (de {:g} a {:g}) después de que init fuera llamado!" -#: ../src/solver/solver.cxx:1281 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:1289 +#, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -"Derivada del tiempo en lugar erróneo - El field se encuentra en {:s}, la " -"derivada se encuentra en {:s} para el field '{:s}'\n" +"Derivada temporal en ubicación incorrecta: el campo está en {:s}, la derivada está en {:s} para el campo '{:s}'\n" -#: ../src/solver/solver.cxx:1480 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:1494 +#, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "Derivada del tiempo para la variable '{:s}' no fijada" -#: ../src/mesh/mesh.cxx:605 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:638 +#, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "Intentando añadir una región ya existente {:s} a regionMap2D" -#: ../src/mesh/mesh.cxx:595 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:614 +#, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "Intentando añadir una región ya existente {:s} a regionMap3D" -#: ../src/mesh/mesh.cxx:616 -#, fuzzy, c++-format +#: ../src/mesh/mesh.cxx:649 +#, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "Intentando añadir una región ya existente {:s} a regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -849,8 +923,10 @@ msgid "" "This is likely the result of clashing input options, and you may have to " "rename one of them.\n" msgstr "" +"Se está intentando indexar la opción '{0}' con '{1}', pero '{0}' es un valor, no una sección.\n" +"Es probable que esto sea el resultado de opciones de entrada en conflicto, y puede que tenga que cambiar el nombre de una de ellas.\n" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -858,155 +934,177 @@ msgstr "" "Opción paralleltransform desconocida.\n" "Opciones válidas son 'identity', 'shifted', 'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" -msgstr "Opciones sin usar:\n" +msgstr "" +"Opciones sin usar:\n" -#: ../src/bout++.cxx:439 -#, fuzzy, c++-format +#: ../src/bout++.cxx:446 +#, c++-format msgid "Usage is {:s} -d \n" -msgstr "Correcto uso es {:s} -d \n" +msgstr "" +"Correcto uso es {:s} -d \n" -#: ../src/bout++.cxx:448 -#, fuzzy, c++-format +#: ../src/bout++.cxx:455 +#, c++-format msgid "Usage is {:s} -f \n" -msgstr "Correcto uso es {:s} -f \n" +msgstr "" +"Correcto uso es {:s} -f \n" -#: ../src/bout++.cxx:466 -#, fuzzy, c++-format +#: ../src/bout++.cxx:473 +#, c++-format msgid "Usage is {:s} -l \n" -msgstr "Correcto uso es {:s} -l \n" +msgstr "" +"Correcto uso es {:s} -l \n" -#: ../src/bout++.cxx:457 -#, fuzzy, c++-format +#: ../src/bout++.cxx:464 +#, c++-format msgid "Usage is {:s} -o \n" -msgstr "Correcto uso es {:s} -o \n" +msgstr "" +"Correcto uso es {:s} -o \n" -#: ../src/bout++.cxx:353 -#, fuzzy, c++-format +#: ../src/bout++.cxx:360 +#, c++-format msgid "Usage is {} {} \n" -msgstr "Correcto uso es {:s} -l \n" +msgstr "" +"Uso: {} {} \n" #: ../tests/unit/src/test_bout++.cxx:32 ../tests/unit/src/test_bout++.cxx:46 msgid "Usage:" -msgstr "" +msgstr "Usage:" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 -#, fuzzy, c++-format +#: ../src/bout++.cxx:374 +#, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " "[VAR=VALUE]\n" msgstr "" -"Uso: {:s} [-d ] [-f ] [restart [append]] " -"[VAR=VALUE]\n" +"Uso: {:s} [-d ] [-f ] [restart [append]] [VAR=VALUE]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 -#, fuzzy +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" -msgstr "Monitor indicó salir\n" +msgstr "" +"Monitor indicó salir\n" -#: ../src/sys/options.cxx:373 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "Valor para la opción {:s} = {:e} no es un entero" + +#: ../src/sys/options.cxx:426 +#, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" -msgstr "" +msgstr "El valor de la opción {:s} no se puede convertir a un BoutReal" -#: ../src/sys/options.cxx:581 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:623 +#, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no se puede convertir a un Field2D" -#: ../src/sys/options.cxx:529 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:571 +#, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no se puede convertir a un Field3D" -#: ../src/sys/options.cxx:663 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:705 +#, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no se puede convertir a un FieldPerp" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" -msgstr "" +msgstr "El valor de la opción {:s} no se puede convertir a un bool" -#: ../src/sys/options.cxx:709 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:751 +#, c++-format msgid "Value for option {:s} cannot be converted to an Array" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no se puede convertir a un Array" -#: ../src/sys/options.cxx:736 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:773 +#, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no se puede convertir a una Matrix" -#: ../src/sys/options.cxx:763 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:795 +#, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no se puede convertir a un Tensor" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:418 +#, c++-format msgid "Value for option {:s} is not an integer" -msgstr "Valor para la opción {:s} = {:e} no es un entero" +msgstr "El valor de la opción {:s} no es un entero" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 +#, c++-format msgid "Variable '{:s}' not initialised" msgstr "Variable '{:s}' sin inicializar" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:467 +#, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -"WARNING: el número de puntos toroidales debería ser 2^n para una FFT " -"eficiente -- considere cambiar MZ si se usan FFTs\n" +"ADVERTENCIA: el número de puntos toroidales debe ser 2^n para un rendimiento eficiente de FFT; considere cambiar MZ ({:d}) si usa FFT\n" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" +"WARNING: extrapolating input mesh quantities into x-boundary cells\n" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" +"WARNING: extrapolating input mesh quantities into x-boundary cells. Set option extrapolate_x=false to disable this.\n" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" +"WARNING: extrapolating input mesh quantities into y-boundary cells\n" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" +"WARNING: extrapolating input mesh quantities into y-boundary cells. Set option extrapolate_y=false to disable this.\n" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" -msgstr "" +msgstr "Wall time limit in hours. By default (< 0), no limit" #: ../src/sys/optionsreader.cxx:42 -#, fuzzy, c++-format +#, c++-format msgid "Writing options to file {:s}\n" -msgstr "Escribiendo opciones a archivo {:s}\n" +msgstr "" +"Escribiendo opciones a archivo {:s}\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "por defecto" +#, fuzzy, c++-format +#~ msgid "\tOpenMP parallelisation {}" +#~ msgstr "\tParalelización en OpenMP desactivada\n" + +#, fuzzy, c++-format +#~ msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +#~ msgstr "\tOpción '{:s}': valor Booleano esperado. Se obtuvo '{:s}'\n" + #~ msgid "\tChecking disabled\n" #~ msgstr "\tComprobación desactivada\n" @@ -1014,11 +1112,6 @@ msgstr "por defecto" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\tComprobación activada, nivel {:d}\n" -#, fuzzy -#~ msgid "\tOpenMP parallelisation enabled, using {:d} threads\n" -#~ msgstr "" -#~ "\tParalelización en OpenMP activada, usando {:d} procesos (`threads`)\n" - #~ msgid "\tSignal handling enabled\n" #~ msgstr "\tGestión de señal activada\n" diff --git a/locale/fr/libbout.po b/locale/fr/libbout.po index ae88b8953c..8b8ca69328 100644 --- a/locale/fr/libbout.po +++ b/locale/fr/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2018-10-21 22:46+0100\n" "Last-Translator: \n" "Language-Team: French\n" @@ -17,109 +17,131 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> région Core jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> région Core jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> région Core jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "" +"\t -> Valeur correcte\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" +"\t -> région Leg jyseps1_1+1 ({:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" +"\t -> région leg jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" +"\t -> région leg ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" +"\t -> région leg ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) doit être un multiple de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" +"\t -> ny/NYPE ({:d}/{:d} = {:d}) doit être >= MYG ({:d})\n" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" +"\tPrise en charge de ADIOS2 {}\n" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" +"\tTrace d'appel dans les exceptions {}\n" #. Loop over all possibilities #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, c++-format msgid "\tCandidate value: {:d}\n" msgstr "" +"\tValeur candidate : {:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" +"\tCouleur dans les journaux {}\n" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " -msgstr "" +msgstr "\tOptions de ligne de commande pour cette exécution : " #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "" +"\tCompilé avec les options : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" +"\tDomaine découpé (NXPE={:d}, NYPE={:d}) en sous-domaines (localNx={:d}, localNy={:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" +"\tERREUR : impossible de répartir {:d} points Y équitablement entre {:d} processeurs\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" +"\tERREUR : impossible de répartir {:d} points Z équitablement entre {:d} processeurs\n" #: ../src/sys/options/options_ini.cxx:200 #, c++-format @@ -127,39 +149,46 @@ msgid "" "\tEmpty key\n" "\tLine: {:s}" msgstr "" +"\tClé vide\n" +"\tLigne : {:s}" #: ../src/sys/optionsreader.cxx:127 #, c++-format msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "" +"\tClé ou valeur vide dans la ligne de commande '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" +"\tSortie de débogage supplémentaire {}\n" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" +"\tPrise en charge de FFT {}\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" +"\tSuivi des noms de champ {}\n" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" +"\tExceptions en virgule flottante {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " -msgstr "" +msgstr "\tTaille de la grille : " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " -msgstr "" +msgstr "\tCellules de garde (x,y,z) : " #: ../src/sys/options/options_ini.cxx:204 #, c++-format @@ -167,139 +196,159 @@ msgid "" "\tKey must not contain ':' character\n" "\tLine: {:s}" msgstr "" +"\tLa clé ne doit pas contenir le caractère ':'\n" +"\tLigne : {:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" +"\tPrise en charge de LAPACK {}\n" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" +"\tPile de messages {}\n" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" +"\tLe mode de métriques est {}\n" #: ../src/sys/optionsreader.cxx:111 #, c++-format msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" +"\tPlusieurs '=' dans l'argument de ligne de commande '{:s}'\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" +"\tPrise en charge des langues naturelles {}\n" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, c++-format msgid "\tNetCDF support {}{}\n" msgstr "" +"\tPrise en charge de NetCDF {}{}\n" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, c++-format -msgid "\tOpenMP parallelisation {}" +msgid "\tOpenMP parallelisation {}, using {} threads\n" msgstr "" +"\tParallélisation OpenMP {}, avec {} threads\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " -msgstr "" +msgstr "\tOption " -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "" +msgid "\tOption {} = {}" +msgstr "\tOption {} = {}" #: ../src/sys/options/options_ini.cxx:70 #, c++-format msgid "\tOptions file '{:s}' not found\n" msgstr "" +"\tFichier d'options '{:s}' introuvable\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" +"\tPrise en charge de PETSc {}\n" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" +"\tPrise en charge de PVODE {}\n" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "" +"\tPrise en charge de NetCDF parallèle désactivée\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" +"\tPrise en charge de NetCDF parallèle activée\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" +"\tPrise en charge des noms de fonctions détaillés {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" +"\tnz lu depuis le fichier de grille d'entrée\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " -msgstr "" +msgstr "\tLecture du vecteur contravariant " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " -msgstr "" +msgstr "\tLecture du vecteur covariant " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" -msgstr "" +msgstr "\tVérification des erreurs à l'exécution {}" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" +"\tPrise en charge de SLEPc {}\n" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" +"\tPrise en charge de SUNDIALS {}\n" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" +"\tPrise en charge de Score-P {}\n" -#: ../src/bout++.cxx:584 -#, fuzzy, c++-format +#: ../src/bout++.cxx:589 +#, c++-format msgid "\tSignal handling support {}\n" -msgstr "\tTraitement du signal désactivé\n" +msgstr "" +"\tPrise en charge de la gestion des signaux {}\n" #: ../src/solver/impls/split-rk/split-rk.cxx:76 #, c++-format msgid "\tUsing a timestep {:e}\n" msgstr "" +"\tUtilisation d'un pas de temps {:e}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "" +"\tterminé\n" #: ../src/solver/impls/split-rk/split-rk.cxx:41 msgid "" "\n" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" +"\n" +"\tSolveur fractionné Runge-Kutta-Legendre et SSP-RK3\n" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -309,37 +358,47 @@ msgid "" " -v, --verbose\t\t\tIncrease verbosity\n" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" +"\n" +" -d \t\tChercher les fichiers d'entrée/sortie dans \n" +" -f \t\tUtiliser les OPTIONS indiquées dans \n" +" -o \tEnregistrer les OPTIONS utilisées dans \n" +" -l, --log \tÉcrire le journal dans \n" +" -v, --verbose\t\t\tAugmenter la verbosité\n" +" -q, --quiet\t\t\tRéduire la verbosité\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" " {1: ^{2}}{0}\n" " Did you mean '{0}'?" msgstr "" +"\n" +" {1: ^{2}}{0}\n" +" Vouliez-vous dire '{0}' ?" -#: ../src/solver/solver.cxx:580 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:586 +#, c++-format msgid "" "\n" "Run finished at : {:s}\n" msgstr "" "\n" -"L'exécution se termine à {:s}\n" +"Exécution terminée à : {:s}\n" -#: ../src/solver/solver.cxx:532 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:540 +#, c++-format msgid "" "\n" "Run started at : {:s}\n" msgstr "" "\n" -"L'exécution se termine à {:s}\n" +"Exécution démarrée à : {:s}\n" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -366,8 +425,33 @@ msgid "" "\n" "{}" msgstr "" +"\n" +"Des options d'entrée inutilisées ont été trouvées :\n" +"-----\n" +"{:i}\n" +"-----\n" +"Il est possible que certaines options aient été mal saisies. Les arguments\n" +"d'entrée de BOUT++ distinguent désormais les majuscules et les minuscules,\n" +"et certains ont changé de nom. Vous pouvez essayer d'exécuter\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"afin de corriger automatiquement les problèmes les plus courants. Si les\n" +"options ci-dessus ne sont utilisées que dans certains cas selon d'autres\n" +"options, vous pouvez appeler `Options::setConditionallyUsed()`, par exemple :\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"afin de marquer une section ou une valeur comme dépendant d'autres valeurs\n" +"et de l'ignorer lors de cette vérification. Sinon, si vous êtes certain que\n" +"les entrées ci-dessus ne sont pas une erreur, vous pouvez définir\n" +"'input:error_on_unused_options=false' pour désactiver cette vérification des\n" +"options inutilisées. Vous pouvez également définir 'input:validate=true'\n" +"pour vérifier les entrées sans lancer la simulation complète.\n" +"\n" +"{}" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -399,117 +483,148 @@ msgid "" "For all possible input parameters, see the user manual and/or the physics " "model source (e.g. {:s}.cxx)\n" msgstr "" +" --print-config\t\tAfficher la configuration de compilation\n" +" --list-solvers\t\tLister les solveurs temporels disponibles\n" +" --help-solver \tAfficher l'aide du solveur temporel indiqué\n" +" --list-laplacians\t\tLister les solveurs d'inversion laplacienne disponibles\n" +" --help-laplacian \tAfficher l'aide du solveur d'inversion laplacienne indiqué\n" +" --list-laplacexz\t\tLister les solveurs d'inversion LaplaceXZ disponibles\n" +" --help-laplacexz \tAfficher l'aide du solveur d'inversion LaplaceXZ indiqué\n" +" --list-invertpars\t\tLister les solveurs InvertPar disponibles\n" +" --help-invertpar \tAfficher l'aide du solveur InvertPar indiqué\n" +" --list-rkschemes\t\tLister les schémas de Runge-Kutta disponibles\n" +" --help-rkscheme \tAfficher l'aide du schéma de Runge-Kutta indiqué\n" +" --list-meshes\t\t\tLister les maillages disponibles\n" +" --help-mesh \t\tAfficher l'aide du maillage indiqué\n" +" --list-xzinterpolations\tLister les interpolations XZ disponibles\n" +" --help-xzinterpolation \tAfficher l'aide de l'interpolation XZ indiquée\n" +" --list-zinterpolations\tLister les interpolations Z disponibles\n" +" --help-zinterpolation \tAfficher l'aide de l'interpolation Z indiquée\n" +" -h, --help\t\t\tCe message\n" +" restart [append]\t\tRedémarrer la simulation. Si append est indiqué, les données sont ajoutées aux fichiers de sortie existants ; sinon, ils sont écrasés\n" +" VAR=VALUE\t\t\tDéfinir VALUE pour le paramètre d'entrée VAR\n" +"\n" +"Pour la liste complète des paramètres d'entrée, consultez le manuel utilisateur et/ou la source du modèle physique (p. ex. {:s}.cxx)\n" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" +" -c, --color\t\t\tSortie colorée avec bout-log-color\n" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" -msgstr "" +msgstr ") écrasée par :" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" -msgstr "" - -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" +msgstr ", niveau {}" #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" -msgstr "" +msgstr "4 sur 8" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" +"Toutes les options ont été utilisées\n" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, c++-format msgid "BOUT++ version {:s}\n" msgstr "" +"Version de BOUT++ {:s}\n" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" +"Arguments de ligne de commande incorrects :\n" + +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "L'argument {:e} de l'opérateur booléen n'est pas un booléen" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " -msgstr "" +msgstr "Régions de bord dans ce processeur : " -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" +"Impossible de répartir {:d} points X équitablement entre {:d} processeurs\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." -msgstr "" +msgstr "Vérifier si un fichier existe, et quitter si c'est le cas." -#: ../src/bout++.cxx:533 -#, fuzzy, c++-format +#: ../src/bout++.cxx:540 +#, c++-format msgid "" "Code compiled on {:s} at {:s}\n" "\n" msgstr "" -"Code compilé le {:s} à {:s}\n" +"Code compilé sur {:s} à {:s}\n" "\n" #: ../src/sys/optionsreader.cxx:130 msgid "Command line" -msgstr "" +msgstr "Ligne de commande" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "" +"Options de compilation :\n" #: ../tests/unit/src/test_bout++.cxx:362 msgid "Compiled with flags" -msgstr "" +msgstr "Compilé avec les options" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" -msgstr "" +msgstr "Construction des régions par défaut" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, c++-format msgid "Could not create PID file {:s}" -msgstr "" +msgstr "Impossible de créer le fichier PID {:s}" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." -msgstr "" +msgstr "Impossible de trouver une valeur valide pour NXPE. Essayez un autre nombre de processeurs." #: ../src/sys/options/options_ini.cxx:160 #, c++-format msgid "Could not open output file '{:s}'\n" msgstr "" +"Impossible d'ouvrir le fichier de sortie '{:s}'\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" -msgstr "" +msgstr "Impossible d'ouvrir {:s}/{:s}.{:d} en écriture" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" +"Impossible de lire le tableau d'entiers '{:s}'\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" +"Impossible d'exécuter bout-log-color. Assurez-vous qu'il se trouve dans votre PATH\n" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" -msgstr "" +msgstr "Impossible d'ajouter le moniteur : {:g} n'est pas un multiple de {:g} !" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -517,196 +632,216 @@ msgid "" "may need to change your input file.\n" "{}" msgstr "" +"Impossible de trouver le générateur '{}'. Les expressions BOUT++ distinguent désormais les majuscules et les minuscules ;\n" +"vous devrez peut-être modifier votre fichier d'entrée.\n" +"{}" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" -msgstr "" +msgstr "Impossible de trouver la région {:s} dans regionMap2D" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" -msgstr "" +msgstr "Impossible de trouver la région {:s} dans regionMap3D" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" -msgstr "" +msgstr "Impossible de trouver la région {:s} dans regionMapPerp" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" -msgstr "" +msgstr "Impossible d'obtenir {} à partir de l'option {:s} = '{:s}' : {}" -#: ../src/bout++.cxx:508 -#, fuzzy, c++-format +#: ../src/bout++.cxx:515 +#, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "" "Le répertoire de données \"{:s}\" n'existe pas ou n'est pas accessible\n" -#: ../src/bout++.cxx:505 -#, fuzzy, c++-format +#: ../src/bout++.cxx:512 +#, c++-format msgid "DataDir \"{:s}\" is not a directory\n" -msgstr "\"{:s}\" n'est pas un répertoire\n" +msgstr "" +"Le répertoire de données \"{:s}\" n'est pas un répertoire\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" +"ERREUR : le solveur est déjà initialisé\n" -#: ../src/bout++.cxx:209 -#, fuzzy, c++-format +#: ../src/bout++.cxx:216 +#, c++-format msgid "Error encountered during initialisation: {:s}\n" -msgstr "Erreur rencontrée lors de l'initialisation : {:s}\n" +msgstr "" +"Erreur lors de l'initialisation : {:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" -msgstr "" +msgstr "Erreur lors de l'écriture des paramètres" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" -msgstr "" +msgstr "Erreur : nx doit être supérieur à 2 fois MXG (2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" -msgstr "Échec d'initialisation du solutionneur -> Abandonner\n" +msgstr "" +"Échec d'initialisation du solutionneur -> Abandonner\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" +"Recherche d'une valeur pour NXPE (idéal = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "" +"Initialisation du solveur\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" msgstr "" +"Les fichiers d'entrée et de sortie des paramètres doivent être différents.\n" +"Fournissez -o pour éviter ce problème.\n" #: ../src/sys/optionsreader.cxx:76 msgid "Invalid command line option '-' found - maybe check whitespace?" -msgstr "" +msgstr "Option de ligne de commande '-' invalide trouvée ; vérifiez peut-être les espaces" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" -msgstr "" +msgstr "Chargement de la grille" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" -msgstr "" +msgstr "La grille doit contenir nx" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" -msgstr "" +msgstr "La grille doit contenir ny" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" +"Tableau d'entiers manquant {:s}\n" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" +"Le moniteur a signalé l'arrêt (exception {})\n" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" -msgstr "" +msgstr "Le moniteur a signalé l'arrêt (code de retour {})" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" -msgstr "" +msgstr "Nom du fichier dont l'existence déclenche un arrêt" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" -msgstr "" +msgstr "Aucune région de bord dans ce processeur" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" +"Aucune région de bord ; le domaine est périodique\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" +"Le nombre de processeurs ({:d}) n'est pas divisible par les NP dans la direction x ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" +"Le nombre de processeurs ({:d}) n'est pas divisible par les NP dans la direction y ({:d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" +"Il ne reste que {:e} secondes ({:.2f} pas). Arrêt\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, c++-format msgid "Option {:s} has no value" -msgstr "" +msgstr "L'option {:s} n'a pas de valeur" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, c++-format msgid "Option {:s}:{:s} does not exist" -msgstr "" +msgstr "L'option {:s}:{:s} n'existe pas" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." -msgstr "" +msgstr "Options : définition d'une valeur depuis la même source ({:s}) vers la nouvelle valeur '{:s}' - l'ancienne valeur était '{:s}'." -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " -msgstr "" +msgstr "Les régions de bord possibles sont : " -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" +"Processeur numéro {:d} sur {:d}\n" +"\n" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" -msgstr "" +msgstr "Région 2D enregistrée {:s}" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" -msgstr "" +msgstr "Région 3D enregistrée {:s}" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" -msgstr "" +msgstr "Région Perp enregistrée {:s}" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, c++-format msgid "Revision: {:s}\n" msgstr "" +"Révision : {:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "Temps d'exécution : " #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -716,68 +851,73 @@ msgstr "" #: ../tests/unit/src/test_bout++.cxx:359 msgid "Signal" -msgstr "" +msgstr "Signal" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" +"Temps sim. | Eval. RHS | Temps mur | Calc Inv Comm E/S SOLVEUR\n" +"\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" +"Temps sim. | Eval. RHS_e | Eval. RHS_I | Temps mur | Calc Inv Comm E/S SOLVEUR\n" +"\n" -#: ../src/solver/solver.cxx:506 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:514 +#, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -"Le solveur fonctionne pour {:d} sorties avec un temps de moniteur de {:e}\n" +"Le solveur s'exécute pour {:d} sorties avec un pas de temps de moniteur de {:e}\n" -#: ../src/solver/solver.cxx:502 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:510 +#, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -"Le solveur fonctionne pour {:d} sorties avec un pas de sortie de {:e}\n" +"Le solveur s'exécute pour {:d} sorties avec un pas de temps de sortie de {:e}\n" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" -msgstr "" +msgstr "Solver::addMonitor : impossible de réduire le pas de temps (de {:g} à {:g}) après l'appel à init !" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" +"Dérivée temporelle au mauvais emplacement - le champ est à {:s}, la dérivée est à {:s} pour le champ '{:s}'\n" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" -msgstr "" +msgstr "La dérivée temporelle de la variable '{:s}' n'est pas définie" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" -msgstr "" +msgstr "Tentative d'ajout d'une région déjà existante {:s} à regionMap2D" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" -msgstr "" +msgstr "Tentative d'ajout d'une région déjà existante {:s} à regionMap3D" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" -msgstr "" +msgstr "Tentative d'ajout d'une région déjà existante {:s} à regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -785,156 +925,179 @@ msgid "" "This is likely the result of clashing input options, and you may have to " "rename one of them.\n" msgstr "" +"Tentative d'indexer l'option '{0}' avec '{1}', mais '{0}' est une valeur, pas une section.\n" +"Ceci est probablement dû à des options d'entrée en conflit, et vous devrez peut-être renommer l'une d'elles.\n" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" +"Option paralleltransform non reconnue.\n" +"Les choix valides sont 'identity', 'shifted', 'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" +"Options inutilisées :\n" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" +"Utilisation : {:s} -d \n" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" +"Utilisation : {:s} -f \n" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" +"Utilisation : {:s} -l \n" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" +"Utilisation : {:s} -o \n" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" +"Utilisation : {} {} \n" #: ../tests/unit/src/test_bout++.cxx:32 ../tests/unit/src/test_bout++.cxx:46 msgid "Usage:" -msgstr "" +msgstr "Utilisation :" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " "[VAR=VALUE]\n" msgstr "" +"Utilisation : {:s} [-d ] [-f ] [restart [append]] [VAR=VALUE]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" +"L'utilisateur a demandé l'arrêt. Retour\n" + +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "La valeur de l'option {:s} = {:e} n'est pas un booléen" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" -msgstr "" +msgstr "La valeur de l'option {:s} = {:e} n'est pas un entier" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en BoutReal" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en Field2D" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en Field3D" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en FieldPerp" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en bool" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en Array" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en Matrix" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" -msgstr "" +msgstr "La valeur de l'option {:s} ne peut pas être convertie en Tensor" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" -msgstr "" +msgstr "La valeur de l'option {:s} n'est pas un entier" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" -msgstr "" +msgstr "La variable '{:s}' n'est pas initialisée" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" +"AVERTISSEMENT : le nombre de points toroïdaux devrait être 2^n pour de bonnes performances FFT ; envisagez de modifier MZ ({:d}) si vous utilisez des FFT\n" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" +"AVERTISSEMENT : extrapolation des quantités de la grille d'entrée dans les cellules de bord x\n" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" +"AVERTISSEMENT : extrapolation des quantités de la grille d'entrée dans les cellules de bord x. Définissez l'option extrapolate_x=false pour désactiver cela.\n" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" +"AVERTISSEMENT : extrapolation des quantités de la grille d'entrée dans les cellules de bord y\n" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" +"AVERTISSEMENT : extrapolation des quantités de la grille d'entrée dans les cellules de bord y. Définissez l'option extrapolate_y=false pour désactiver cela.\n" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" -msgstr "" +msgstr "Limite de temps mur en heures. Par défaut (< 0), aucune limite" #: ../src/sys/optionsreader.cxx:42 #, c++-format msgid "Writing options to file {:s}\n" msgstr "" +"Écriture des options dans le fichier {:s}\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" -msgstr "" +msgstr "par défaut" #~ msgid "\tChecking disabled\n" #~ msgstr "\tVérification désactivée\n" @@ -946,10 +1109,6 @@ msgstr "" #~ msgid "\tSignal handling enabled\n" #~ msgstr "\tTraitement du signal activé\n" -#, fuzzy -#~ msgid "Option {:s} is not a section" -#~ msgstr "\"{:s}\" n'est pas un répertoire\n" - #, fuzzy #~ msgid "Error encountered during initialisation\n" #~ msgstr "Erreur rencontrée lors de l'initialisation\n" diff --git a/locale/ka/libbout.po b/locale/ka/libbout.po new file mode 100644 index 0000000000..70ed52aafb --- /dev/null +++ b/locale/ka/libbout.po @@ -0,0 +1,1084 @@ +# Georgian translation for libbout. +# Copyright (C) 2026 libbout's authors. +# This file is distributed under the same license as the libbout package. +# Ekaterine Papava , 2026. +# +msgid "" +msgstr "" +"Project-Id-Version: libbout\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" +"PO-Revision-Date: 2026-03-23 08:06+0100\n" +"Last-Translator: Ekaterine Papava \n" +"Language-Team: Georgian <(nothing)>\n" +"Language: ka\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.9\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:182 +#, c++-format +msgid "" +"\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " +"of MYSUB ({:d})\n" +msgstr "" +"\t -> რეგიონი Core jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) MYSUB-ის ({:d}) " +"ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#, c++-format +msgid "" +"\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " +"of MYSUB ({:d})\n" +msgstr "" +"\t -> რეგიონი Core jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) MYSUB-ის ({:d}) " +"ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:190 +#, c++-format +msgid "" +"\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " +"of MYSUB ({:d})\n" +msgstr "" +"\t -> რეგიონი Core jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) MYSUB-ის ({:d}) " +"ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:300 +msgid "\t -> Good value\n" +msgstr "\t -> კარგი მნიშვნელობა\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:171 +#, c++-format +msgid "" +"\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" +msgstr "\t -> რეგიონი Leg jyseps1_1+1 ({:d}) MYSUB-ის ({:d}) ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:206 +#, c++-format +msgid "" +"\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " +"multiple of MYSUB ({:d})\n" +msgstr "" +"\t -> რეგიონი leg jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) MYSUB-ის ({:d}) " +"ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:223 +#, c++-format +msgid "" +"\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " +"MYSUB ({:d})\n" +msgstr "" +"\t -> რეგიონი leg ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) MYSUB-ის ({:d}) " +"ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#, c++-format +msgid "" +"\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " +"multiple of MYSUB ({:d})\n" +msgstr "" +"\t -> რეგიონი leg ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) MYSUB-ის ({:d}) " +"ნამრავლი უნდა იყოს\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:166 +#, c++-format +msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" +msgstr "\t -> ny/NYPE ({:d}/{:d} = {:d}) უნდა იყოს >= MYG ({:d})\n" + +#: ../src/bout++.cxx:575 +#, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "\tADIOS2-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:583 +#, c++-format +msgid "\tBacktrace in exceptions {}\n" +msgstr "\tუკუტრეისი გამონაკლისებში {}\n" + +#. Loop over all possibilities +#. Processors divide equally +#. Mesh in X divides equally +#. Mesh in Y divides equally +#: ../src/mesh/impls/bout/boutmesh.cxx:288 +#, c++-format +msgid "\tCandidate value: {:d}\n" +msgstr "\tკანდიდატი მნიშვნელობა: {:d}\n" + +#: ../src/bout++.cxx:584 +#, c++-format +msgid "\tColour in logs {}\n" +msgstr "\tფერები ჟურნალში {}\n" + +#: ../src/bout++.cxx:599 +msgid "\tCommand line options for this run : " +msgstr "\tბრძანების სტრიქონის პარამეტრები ამ გაშვებისთვის : " + +#. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings +#. which could cause problems (e.g. terminate strings). +#: ../src/bout++.cxx:595 +#, c++-format +msgid "\tCompiled with flags : {:s}\n" +msgstr "\tდაკომპილებულია ალმებით : {:s}\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:315 +#, c++-format +msgid "" +"\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " +"localNy={:d})\n" +msgstr "" +"\tდომენი დაყოფილია (NXPE={:d}, NYPE={:d}) დომენებად (localNx={:d}, " +"localNy={:d})\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:357 +#, c++-format +msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" +msgstr "" +"\tშეცდომა: {:d} Y წერტილის თანაბრად განაწილება {:d} პროცესორს შორის " +"შეუძლებელია\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:365 +#, c++-format +msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" +msgstr "" +"\tშეცდომა: {:d} Z წერტილის თანაბრად განაწილება {:d} პროცესორს შორის " +"შეუძლებელია\n" + +#: ../src/sys/options/options_ini.cxx:200 +#, c++-format +msgid "" +"\tEmpty key\n" +"\tLine: {:s}" +msgstr "" +"\tცარიელი გასაღები\n" +"\tხაზი: {:s}" + +#: ../src/sys/optionsreader.cxx:127 +#, c++-format +msgid "\tEmpty key or value in command line '{:s}'\n" +msgstr "\tცარიელი გასაღები, ან მნიშვნელობა ბრძანების სტრიქონში '{:s}'\n" + +#: ../src/bout++.cxx:587 +#, c++-format +msgid "\tExtra debug output {}\n" +msgstr "\tგამართვის დამატებითი შეტყობინებები {}\n" + +#: ../src/bout++.cxx:568 +#, c++-format +msgid "\tFFT support {}\n" +msgstr "\tFFT-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:590 +#, c++-format +msgid "\tField name tracking {}\n" +msgstr "\tველის სახელის თვალყურის დევნება {}\n" + +#: ../src/bout++.cxx:588 +#, c++-format +msgid "\tFloating-point exceptions {}\n" +msgstr "\tმცურავმძიმიანი გამონაკლისები {}\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:476 +msgid "\tGrid size: " +msgstr "\tბადის ზომა: " + +#: ../src/mesh/impls/bout/boutmesh.cxx:499 +msgid "\tGuard cells (x,y,z): " +msgstr "\tუჯრედების დაცვა (x,y,z): " + +#: ../src/sys/options/options_ini.cxx:204 +#, c++-format +msgid "" +"\tKey must not contain ':' character\n" +"\tLine: {:s}" +msgstr "" +"\tგასაღები არ უნდა შეიცავდეს სიმბოლოს ':'\n" +"\tხაზი: {:s}" + +#: ../src/bout++.cxx:570 +#, c++-format +msgid "\tLAPACK support {}\n" +msgstr "\tLAPACK-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:591 +#, c++-format +msgid "\tMessage stack {}\n" +msgstr "\tშეტყობინებების სტეკი {}\n" + +#: ../src/bout++.cxx:567 +#, c++-format +msgid "\tMetrics mode is {}\n" +msgstr "\tმეტრიკების რეჟიმია {}\n" + +#: ../src/sys/optionsreader.cxx:111 +#, c++-format +msgid "\tMultiple '=' in command-line argument '{:s}'\n" +msgstr "\tერთზე მეტი '=' ბრძანების სტრიქონის არგუმენტში '{:s}'\n" + +#: ../src/bout++.cxx:569 +#, c++-format +msgid "\tNatural language support {}\n" +msgstr "\tნატურალური ენის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:574 +#, c++-format +msgid "\tNetCDF support {}{}\n" +msgstr "\tNetCDF-ის მხარდაჭერა {}{}\n" + +#: ../src/bout++.cxx:585 +#, c++-format +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "\tOpenMP-ის პარალელიზაცია {}. გამოიყენება {} ნაკადი\n" + +#. Mark the option as used +#. Option not found +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 +msgid "\tOption " +msgstr "\tპარამეტრი " + +#: ../src/sys/options.cxx:369 +#, c++-format +msgid "\tOption {} = {}" +msgstr "\tპარამეტრი {} = {}" + +#: ../src/sys/options/options_ini.cxx:70 +#, c++-format +msgid "\tOptions file '{:s}' not found\n" +msgstr "\tპარამეტრების ფაილი '{:s}' აღმოჩენილი არაა\n" + +#: ../src/bout++.cxx:576 +#, c++-format +msgid "\tPETSc support {}\n" +msgstr "\tPETSc-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:579 +#, c++-format +msgid "\tPVODE support {}\n" +msgstr "\tPVODE-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:564 +msgid "\tParallel NetCDF support disabled\n" +msgstr "\tპარალელური NetCDF-ის მხარდაჭერა გათიშულია\n" + +#: ../src/bout++.cxx:562 +msgid "\tParallel NetCDF support enabled\n" +msgstr "\tპარალელური NetCDF-ის მხარდაჭერა ჩართულია\n" + +#: ../src/bout++.cxx:577 +#, c++-format +msgid "\tPretty function name support {}\n" +msgstr "\tლამაზი ფუნქციის სახელის მხარდაჭერა {}\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:473 +msgid "\tRead nz from input grid file\n" +msgstr "\tnz წაკითხულია შეყვანილი ბადის ფაილიდან\n" + +#: ../src/mesh/mesh.cxx:249 +msgid "\tReading contravariant vector " +msgstr "\tკონტრავარიანტული ვექტორის წაკითხვა " + +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 +msgid "\tReading covariant vector " +msgstr "\tკოვარიანტული ვექტორის წაკითხვა " + +#: ../src/bout++.cxx:555 +#, c++-format +msgid "\tRuntime error checking {}" +msgstr "\tგაშვების დროის შემოწმება {}" + +#: ../src/bout++.cxx:581 +#, c++-format +msgid "\tSLEPc support {}\n" +msgstr "\tSLEPc-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:582 +#, c++-format +msgid "\tSUNDIALS support {}\n" +msgstr "\tSUNDIALS-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:580 +#, c++-format +msgid "\tScore-P support {}\n" +msgstr "\tScore-P-ის მხარდაჭერა {}\n" + +#: ../src/bout++.cxx:589 +#, c++-format +msgid "\tSignal handling support {}\n" +msgstr "\tსიგნალის დამუშავების მხარდაჭერა {}\n" + +#: ../src/solver/impls/split-rk/split-rk.cxx:76 +#, c++-format +msgid "\tUsing a timestep {:e}\n" +msgstr "\tგამოიყენება დროის შტამპი {:e}\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:613 +msgid "\tdone\n" +msgstr "\tმზადაა\n" + +#: ../src/solver/impls/split-rk/split-rk.cxx:41 +msgid "" +"\n" +"\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" +msgstr "" +"\n" +"\tგაყოფილი Runge-Kutta-Legendre და SSP-RK3 ამომხსნელი\n" + +#: ../src/bout++.cxx:378 +msgid "" +"\n" +" -d \t\tLook in for input/output files\n" +" -f \t\tUse OPTIONS given in \n" +" -o \tSave used OPTIONS given to \n" +" -l, --log \tPrint log to \n" +" -v, --verbose\t\t\tIncrease verbosity\n" +" -q, --quiet\t\t\tDecrease verbosity\n" +msgstr "" +"\n" +" -d <მონაცემთა_საქაღალდე>\t\tშეტანა/გამოტანის ფაილების ძებნა " +"<მონაცემთა_საქაღალდეში>\n" +" -f <პარამეტრების_ფაილის_სახელი>\t\t<პარამეტრების_ფაილში> მითითებული " +"პარამეტრების გამოყენება\n" +" -o <პარამეტრების_ფაილი>\tგადაცემული პარამეტრების შენახვა " +"<პარამეტრების_ფაილში>\n" +" -l, --log <ჟურნალის_ფაილის_სახელი>\tჟურნალის ჩაწერა " +"<ჟურნალის_ფაილის_სახელში>\n" +" -v, --verbose\t\t\tმეტი შეტყობინების გამოტანა\n" +" -q, --quiet\t\t\tნაკლები შეტყობინების გამოტანა\n" + +#: ../src/sys/expressionparser.cxx:341 +#, c++-format +msgid "" +"\n" +" {1: ^{2}}{0}\n" +" Did you mean '{0}'?" +msgstr "" +"\n" +" {1: ^{2}}{0}\n" +" გულისხმობდით '{0}'-ს?" + +#: ../src/solver/solver.cxx:586 +#, c++-format +msgid "" +"\n" +"Run finished at : {:s}\n" +msgstr "" +"\n" +"დასრულების დროა : {:s}\n" + +#: ../src/solver/solver.cxx:540 +#, c++-format +msgid "" +"\n" +"Run started at : {:s}\n" +msgstr "" +"\n" +"გაშვების დროა : {:s}\n" + +#. Raw string to help with the formatting of the message, and a +#. separate variable so clang-format doesn't barf on the +#. exception +#: ../src/sys/options.cxx:1158 +msgid "" +"\n" +"There were unused input options:\n" +"-----\n" +"{:i}\n" +"-----\n" +"It's possible you've mistyped some options. BOUT++ input arguments are\n" +"now case-sensitive, and some have changed name. You can try running\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"to automatically fix the most common issues. If these options above\n" +"are sometimes used depending on other options, you can call\n" +"`Options::setConditionallyUsed()`, for example:\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"to mark a section or value as depending on other values, and so ignore\n" +"it in this check. Alternatively, if you're sure the above inputs are\n" +"not a mistake, you can set 'input:error_on_unused_options=false' to\n" +"turn off this check for unused options. You can always set\n" +"'input:validate=true' to check inputs without running the full\n" +"simulation.\n" +"\n" +"{}" +msgstr "" +"\n" +"აღმოჩენილია გამოუყენებელი შეყვანის პარამეტრები:\n" +"-----\n" +"{:i}\n" +"-----\n" +"შესაძლებელია, ზოგიერთი პარამეტრი შეცდომით გაქვთ აკრეფილი. BOUT++-ის " +"შეყვანის არგუმენტები\n" +"ახლა დიდ და პატარა ასოებს არჩევს და ზოგიერთ მათგანს სახელიც შეეცვალა. " +"შეგიძლიათ გაუშვათ\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"რათა ყველაზე გავრცელებული პრობლემები ავტომატურად გასწორდეს. თუ ზემოთ მოცემული " +"პარამეტრები\n" +"ზოგჯერ სხვა პარამეტრებზეა დამოკიდებული, შეგიძლიათ გამოიძახოთ\n" +"`Options::setConditionallyUsed()`, მაგალითად:\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"რათა მონაკვეთი ან მნიშვნელობა სხვა მნიშვნელობებზე დამოკიდებულად მონიშნოთ და ამ " +"შემოწმებაში\n" +"მისი იგნორირება მოხდეს. თუ დარწმუნებული ხართ, რომ ზემოთ მითითებული შეყვანები\n" +"შეცდომა არაა, შეგიძლიათ დააყენოთ 'input:error_on_unused_options=false', რათა\n" +"გამოუყენებელი პარამეტრების ეს შემოწმება გამოირთოს. ასევე ყოველთვის შეგიძლიათ\n" +"'input:validate=true' დააყენოთ, რათა შეყვანები სრული სიმულაციის გაშვების " +"გარეშე გადაამოწმოთ.\n" +"\n" +"{}" + +#: ../src/bout++.cxx:389 +#, c++-format +msgid "" +" --print-config\t\tPrint the compile-time configuration\n" +" --list-solvers\t\tList the available time solvers\n" +" --help-solver \tPrint help for the given time solver\n" +" --list-laplacians\t\tList the available Laplacian inversion solvers\n" +" --help-laplacian \tPrint help for the given Laplacian inversion " +"solver\n" +" --list-laplacexz\t\tList the available LaplaceXZ inversion solvers\n" +" --help-laplacexz \tPrint help for the given LaplaceXZ inversion " +"solver\n" +" --list-invertpars\t\tList the available InvertPar solvers\n" +" --help-invertpar \tPrint help for the given InvertPar solver\n" +" --list-rkschemes\t\tList the available Runge-Kutta schemes\n" +" --help-rkscheme \tPrint help for the given Runge-Kutta scheme\n" +" --list-meshes\t\t\tList the available Meshes\n" +" --help-mesh \t\tPrint help for the given Mesh\n" +" --list-xzinterpolations\tList the available XZInterpolations\n" +" --help-xzinterpolation \tPrint help for the given " +"XZInterpolation\n" +" --list-zinterpolations\tList the available ZInterpolations\n" +" --help-zinterpolation \tPrint help for the given " +"ZInterpolation\n" +" -h, --help\t\t\tThis message\n" +" restart [append]\t\tRestart the simulation. If append is specified, append " +"to the existing output files, otherwise overwrite them\n" +" VAR=VALUE\t\t\tSpecify a VALUE for input parameter VAR\n" +"\n" +"For all possible input parameters, see the user manual and/or the physics " +"model source (e.g. {:s}.cxx)\n" +msgstr "" +" --print-config\t\tკომპილაციის დროის კონფიგურაციის გამოტანა\n" +" --list-solvers\t\tხელმისაწვდომი დროის ამომხსნელების სია\n" +" --help-solver \tდახმარების გამოტანა მოცემული დროის ამოხსნელისთვის\n" +" --list-laplacians\t\tხელმისაწვდომი ლაპლასის ინვერსიის ამომხსნელების სია\n" +" --help-laplacian \tდახმარების გამოტანა მოცემული ლაპლასის " +"ინვერსიის ამომხსნელისთვის\n" +" --list-laplacexz\t\tხელმისაწვდომი LaplaceXZ ინვერსიის ამომხსნელების სია\n" +" --help-laplacexz \tდახმარების გამოტანა მოცემული LaplaceXZ " +"ინვერსიის ამომხსნელისთვის\n" +" --list-invertpars\t\tხელმისაწვდომი InvertPar ამომხსნელების სია\n" +" --help-invertpar \tდახმარების გამოტანა მოცემული InvertPar " +"ამომხსნელისთვის\n" +" --list-rkschemes\t\tხელმისაწვდომი Runge-Kutta სქემების სიის გამოტანა\n" +" --help-rkscheme \tდახმარების გამოტანა მოცემული Runge-Kutta " +"სქემისთვის\n" +" --list-meshes\t\t\tხელმისაწვდომი ბადეების სია\n" +" --help-mesh \t\tდახმარების გამოტანა მოცემული ბადისთვის\n" +" --list-xzinterpolations\tხელმისაწვდომი XZInterpolation-ების სიის გამოტანა\n" +" --help-xzinterpolation \tდახმარების გამოტანა მოცემული " +"XZInterpolation-ისთვის\n" +" --list-zinterpolations\tხელმისაწვდომი ZInterpolation-ების სიის გამოტანა\n" +" --help-zinterpolation \tდახმარების გამოტანა მოცემული " +"ZInterpolation-ისთვის\n" +" -h, --help\t\t\tეს შეტყობინება\n" +" restart [append]\t\tსიმულაციის თავიდან გაშვება. თუ მითითებულია append, " +"გამოტანილი ინფორმაცია არსებულ გამოტანილ ფაილებს ბოლოში მიეწერება. წინააღმდეგ " +"შემთხვევაში კი მოხდება თავზე გადაწერა\n" +" VAR=VALUE\t\t\tმიუთითეთ VALUE შეყვანის პარამეტრისტვის VAR\n" +"\n" +"ყველა შესაძლო შეყვანის პარამეტრის სანახავად იხილეთ სახელმძღვანელო, ან/და " +"ფიზიკის მოდელის წყარო (მაგ: {:s}.cxx)\n" + +#: ../src/bout++.cxx:386 +msgid " -c, --color\t\t\tColor output using bout-log-color\n" +msgstr " -c, --color\t\t\tფერადი გამოტანა bout-log-color-ის გამოყენეებით\n" + +#: ../include/bout/options.hxx:899 +msgid ") overwritten with:" +msgstr ") თავსე გადაწერილია რით:" + +#: ../src/bout++.cxx:557 +#, c++-format +msgid ", level {}" +msgstr ", დონე {}" + +#: ../tests/unit/src/test_bout++.cxx:352 +msgid "4 of 8" +msgstr "4 8-დან" + +#: ../src/sys/options.cxx:895 +msgid "All options used\n" +msgstr "ყველა გამოყენებული პარამეტრი\n" + +#: ../src/bout++.cxx:535 +#, c++-format +msgid "BOUT++ version {:s}\n" +msgstr "BOUT++ ვერსია {:s}\n" + +#: ../src/bout++.cxx:147 +msgid "Bad command line arguments:\n" +msgstr "არასწორი ბრძანების სტრიქონის არგუმენტები:\n" + +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "ლოგიკური ოპერატორის არგუმენტი {:e} ლოგიკური არაა" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 +msgid "Boundary regions in this processor: " +msgstr "სასაზღვრო რეგიონები ამ პროცესორში: " + +#: ../src/mesh/impls/bout/boutmesh.cxx:348 +#, c++-format +msgid "Cannot split {:d} X points equally between {:d} processors\n" +msgstr "შეუძლებელია {:d} X წერტილის თანაბრად გაყოფა {:d} პროცესორს შორის\n" + +#: ../src/bout++.cxx:829 +msgid "Check if a file exists, and exit if it does." +msgstr "შემოწმება, არსებობს, თუ არა ფაილი და გასვლა, თუ კი." + +#: ../src/bout++.cxx:540 +#, c++-format +msgid "" +"Code compiled on {:s} at {:s}\n" +"\n" +msgstr "" +"კოდის კომპილაცია მოხდა მანქანაზე {:s} დრო: {:s}\n" +"\n" + +#: ../src/sys/optionsreader.cxx:130 +msgid "Command line" +msgstr "ბრძანების სტრიქონი" + +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 +msgid "Compile-time options:\n" +msgstr "კომპილაციის დროის პარამეტრები:\n" + +#: ../tests/unit/src/test_bout++.cxx:362 +msgid "Compiled with flags" +msgstr "კომპილაციის ალმები" + +#: ../src/mesh/impls/bout/boutmesh.cxx:604 +msgid "Constructing default regions" +msgstr "ნაგულისხმევი რეგიონების აგება" + +#: ../src/bout++.cxx:527 +#, c++-format +msgid "Could not create PID file {:s}" +msgstr "ვერ შევქმენი PID ფაილი {:s}" + +#: ../src/mesh/impls/bout/boutmesh.cxx:309 +msgid "" +"Could not find a valid value for NXPE. Try a different number of processors." +msgstr "" +"NXPE-ისთვის სწორი მნიშვნელობის პოვნა შეუძლებელია. სცადეთ პროცესორების სხვა " +"რაოდენობა." + +#: ../src/sys/options/options_ini.cxx:160 +#, c++-format +msgid "Could not open output file '{:s}'\n" +msgstr "გახსნის შეცდომა გამოტანის ფაილისთვის '{:s}'\n" + +#: ../src/bout++.cxx:657 +#, c++-format +msgid "Could not open {:s}/{:s}.{:d} for writing" +msgstr "{:s}/{:s}.{:d}-ის ჩასაწერად გახსნა შეუძლებელია" + +#. Error reading +#: ../src/mesh/mesh.cxx:543 +#, c++-format +msgid "Could not read integer array '{:s}'\n" +msgstr "წაკითხვის შეცდომა მთელი რიცხვების მასივისთვის '{:s}'\n" + +#. Failed . Probably not important enough to stop the simulation +#: ../src/bout++.cxx:637 +msgid "Could not run bout-log-color. Make sure it is in your PATH\n" +msgstr "bout-log-color-ის გაშვება შეუძლებელია. დარწმუნდით, რომ ის თქვენს PATH-შია\n" + +#: ../src/solver/solver.cxx:772 +#, c++-format +msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" +msgstr "მონიტორის დამატება შეუძლებელია: {:g} {:g}-ის ნამრავლი არაა!" + +#: ../src/sys/expressionparser.cxx:312 +#, c++-format +msgid "" +"Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " +"you\n" +"may need to change your input file.\n" +"{}" +msgstr "" +"გენერატორი '{}' აღმოჩენილი არაა. BOUT++-ის გამოსახულებები ახლა დიდ და პატარა " +"ასოებს ანსხვავებს, ასე რომ,\n" +"შეიძლება, თქვენი შეყვანის ფაილის შემოწმება დაგჭირდეთ.\n" +"{}" + +#: ../src/mesh/mesh.cxx:587 +#, c++-format +msgid "Couldn't find region {:s} in regionMap2D" +msgstr "regionMap2D-ში რეგიონი {:s} აღმოჩენილი არაა" + +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 +#, c++-format +msgid "Couldn't find region {:s} in regionMap3D" +msgstr "regionMap3D-ში რეგიონი {:s} აღმოჩენილი არაა" + +#: ../src/mesh/mesh.cxx:595 +#, c++-format +msgid "Couldn't find region {:s} in regionMapPerp" +msgstr "regionMapPerp-ში რეგიონი {:s} აღმოჩენილი არაა" + +#. Convert any exceptions to something a bit more useful +#: ../src/sys/options.cxx:361 +#, c++-format +msgid "Couldn't get {} from option {:s} = '{:s}': {}" +msgstr "{}-ის მიღება შეუძლებელია პარამეტრიდან {:s} = '{:s}': {}" + +#: ../src/bout++.cxx:515 +#, c++-format +msgid "DataDir \"{:s}\" does not exist or is not accessible\n" +msgstr "მონაცემთა საქაღალდე \"{:s}\" არ არსებობს, ან წვდომადი არაა\n" + +#: ../src/bout++.cxx:512 +#, c++-format +msgid "DataDir \"{:s}\" is not a directory\n" +msgstr "მონაცემთა საქაღალდე \"{:s}\" საქაღალდე არაა\n" + +#: ../src/solver/solver.cxx:671 +msgid "ERROR: Solver is already initialised\n" +msgstr "შეცდომა: ამომხსნელი უკვე ინიციალიზებულია\n" + +#: ../src/bout++.cxx:216 +#, c++-format +msgid "Error encountered during initialisation: {:s}\n" +msgstr "ინიციალიზაციისას აღმოჩენილია შეცდომა: {:s}\n" + +#: ../src/bout++.cxx:751 +msgid "Error whilst writing settings" +msgstr "შეცდომა პარამეტრების ჩაწერისას" + +#: ../src/mesh/impls/bout/boutmesh.cxx:323 +#, c++-format +msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" +msgstr "" +"შეცდომა: nx უფრო მეტი უნდა იყოს, ვიდრე ორზე გამრავლებული MXG (2 * {:d})" + +#: ../src/solver/solver.cxx:520 +msgid "Failed to initialise solver-> Aborting\n" +msgstr "ამომხსნელის ინიციალიზაცია ჩავარდა -> შესრულება შეწყდა\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:281 +#, c++-format +msgid "Finding value for NXPE (ideal = {:f})\n" +msgstr "ვეძებ მნიშვნელობას NXPE-ისთვის (იდეალურია = {:f})\n" + +#: ../src/solver/solver.cxx:674 +msgid "Initialising solver\n" +msgstr "ამომხსნელის ინიციალიზაცია\n" + +#: ../src/bout++.cxx:501 +msgid "" +"Input and output file for settings must be different.\n" +"Provide -o to avoid this issue.\n" +msgstr "" +"შეყვანის და გამოტანის ფაილი პარამეტრებისთვის უნდა განსხვავდებოდეს.\n" +"ამ პრობლემის თავიდან ასაცილებლად მიუთითეთ -o .\n" + +#: ../src/sys/optionsreader.cxx:76 +msgid "Invalid command line option '-' found - maybe check whitespace?" +msgstr "" +"აღმოჩენილია არასწორი ბრძანების სტრიქონის პარამეტრი '-' - შეამოწმეთ ზედმეტი " +"ჰარეები?" + +#: ../src/mesh/impls/bout/boutmesh.cxx:436 +msgid "Loading mesh" +msgstr "ბადის ჩატვირთვა" + +#: ../src/mesh/impls/bout/boutmesh.cxx:451 +msgid "Mesh must contain nx" +msgstr "ბადე უნდა შეიცავდეს nx-ს" + +#: ../src/mesh/impls/bout/boutmesh.cxx:455 +msgid "Mesh must contain ny" +msgstr "ბადე უნდა შეიცავდეს ny-ს" + +#. Not found +#: ../src/mesh/mesh.cxx:547 +#, c++-format +msgid "Missing integer array {:s}\n" +msgstr "აკლია მთელი რიცხვების მასივი {:s}\n" + +#: ../src/solver/solver.cxx:911 +#, c++-format +msgid "Monitor signalled to quit (exception {})\n" +msgstr "მონიტორმა გასვლის სიგნალი გამოაგზავნა (გამონაკლისი {})\n" + +#: ../src/solver/solver.cxx:889 +#, c++-format +msgid "Monitor signalled to quit (return code {})" +msgstr "მონიტორმა გასვლის სიგნალი გამოაგზავნა (დაბრუნების კოდი {})" + +#: ../src/bout++.cxx:834 +msgid "Name of file whose existence triggers a stop" +msgstr "ფაილის სახელი, რომლის არსებობაც გაჩერებას იწვევს" + +#: ../src/mesh/impls/bout/boutmesh.cxx:601 +msgid "No boundary regions in this processor" +msgstr "ამ პროცესორში სასაზღვრო რეგიონები არ არის" + +#: ../src/mesh/impls/bout/boutmesh.cxx:586 +msgid "No boundary regions; domain is periodic\n" +msgstr "სასაზღვრო რეგიონების გარეშე. დომენი პერიოდულია\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:245 +#, c++-format +msgid "" +"Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" +msgstr "" +"პროცესორების რაოდენობა ({:d}), რომლებიც არ იყოფა NP-ებზე x მიმართულებით " +"({:d})\n" + +#: ../src/mesh/impls/bout/boutmesh.cxx:258 +#, c++-format +msgid "" +"Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" +msgstr "" +"პროცესორების რაოდენობა ({:d}), რომლებიც არ იყოფა NP-ებზე y მიმართულებით " +"({:d})\n" + +#. Less than 2 time-steps left +#: ../src/bout++.cxx:908 +#, c++-format +msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" +msgstr "დარჩა მხოლოდ {:e} წამი ({:.2f} ნაბიჯი). გასვლა\n" + +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 +#, c++-format +msgid "Option {:s} has no value" +msgstr "პარამეტრს {:s} მნიშვნელობა არ აქვს" + +#. Doesn't exist +#: ../src/sys/options.cxx:172 +#, c++-format +msgid "Option {:s}:{:s} does not exist" +msgstr "პარამეტრი {:s}:{:s} არ არსებობს" + +#: ../include/bout/options.hxx:904 +#, c++-format +msgid "" +"Options: Setting a value from same source ({:s}) to new value '{:s}' - old " +"value was '{:s}'." +msgstr "" +"პარამეტრები: მნიშვნელობის დაყენება იგივე წყაროდან ({:s}) ახალ მნიშვნელობაზე " +"'{:s}' - ძველი მნიშვნელობა იყო '{:s}'." + +#: ../src/mesh/impls/bout/boutmesh.cxx:588 +msgid "Possible boundary regions are: " +msgstr "შესაძლო სასაზღვრო რეგიონებია: " + +#: ../src/bout++.cxx:545 +#, c++-format +msgid "" +"Processor number: {:d} of {:d}\n" +"\n" +msgstr "" +"პროცესორის ნომერი: {:d} {:d}-დან\n" +"\n" + +#: ../src/mesh/mesh.cxx:642 +#, c++-format +msgid "Registered region 2D {:s}" +msgstr "რეგისტრირებული რეგიონი 2D {:s}" + +#: ../src/mesh/mesh.cxx:632 +#, c++-format +msgid "Registered region 3D {:s}" +msgstr "რეგისტრირებული რეგიონი 3D {:s}" + +#: ../src/mesh/mesh.cxx:652 +#, c++-format +msgid "Registered region Perp {:s}" +msgstr "რეგისტრირებულია რეგიონი Perp {:s}" + +#: ../src/bout++.cxx:536 +#, c++-format +msgid "Revision: {:s}\n" +msgstr "რევიზია: {:s}\n" + +#: ../src/solver/solver.cxx:587 +msgid "Run time : " +msgstr "გაშვებულობის დრო : " + +#. / Run the solver +#: ../src/solver/solver.cxx:533 +msgid "" +"Running simulation\n" +"\n" +msgstr "" +"სიმულაციის გაშვება\n" +"\n" + +#: ../tests/unit/src/test_bout++.cxx:359 +msgid "Signal" +msgstr "სიგნალი" + +#: ../src/bout++.cxx:876 +msgid "" +"Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" +"\n" +msgstr "" +"სიმ. დრო | RHS გამოთვ. | კედლ. დრო | გამოთვ. ინვ. კავშ. I/O ამომხს.\n" +"\n" + +#: ../src/bout++.cxx:879 +msgid "" +"Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " +"Comm I/O SOLVER\n" +"\n" +msgstr "" +"სიმ. დრო | RHS_e გამოთვ. | RHS_I გამოთვ. | კედლ. დრო | გამოთვ. ინვ. კავშ. " +"I/O ამომხს.\n" +"\n" + +#: ../src/solver/solver.cxx:514 +#, c++-format +msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" +msgstr "" +"ამომხსნელი გაშვებულია {:d} გამოტანისთვის მონიტორინგის დროის ნაბიჯით {:e}\n" + +#: ../src/solver/solver.cxx:510 +#, c++-format +msgid "Solver running for {:d} outputs with output timestep of {:e}\n" +msgstr "" +"ამომხსნელი გაშვებულია {:d} გამოტანისთვის გამოტანის დროის ნაბიჯით {:e}\n" + +#: ../src/solver/solver.cxx:788 +#, c++-format +msgid "" +"Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " +"called!" +msgstr "" +"Solver::addMonitor: init-ის გამოძახების შემდეგ დროის ნაბიჯს ({:g}-და {:g}-" +"ზე) ვერ შეამცირებთ!" + +#: ../src/solver/solver.cxx:1289 +#, c++-format +msgid "" +"Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " +"for field '{:s}'\n" +msgstr "" +"დროითი წარმოებული არასწორ მდებარეობაზეა - ველი არის {:s}-ზე, წარმოებული კი " +"{:s}-ზე ველისთვის '{:s}'\n" + +#: ../src/solver/solver.cxx:1494 +#, c++-format +msgid "Time derivative for variable '{:s}' not set" +msgstr "ცვლადისთვის '{:s}' დროის წარმოებული დაყენებული არაა" + +#: ../src/mesh/mesh.cxx:638 +#, c++-format +msgid "Trying to add an already existing region {:s} to regionMap2D" +msgstr "მცდელობა, დაემატოს უკვე არსებული რეგიონი {:s} regionMap2D-ს" + +#: ../src/mesh/mesh.cxx:614 +#, c++-format +msgid "Trying to add an already existing region {:s} to regionMap3D" +msgstr "მცდელობა, დაემატოს უკვე არსებული რეგიონი {:s} regionMap3D-ს" + +#: ../src/mesh/mesh.cxx:649 +#, c++-format +msgid "Trying to add an already existing region {:s} to regionMapPerp" +msgstr "მცდელობა, დაემატოს უკვე არსებული რეგიონი {:s} regionMapPerp-ს" + +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 +#, c++-format +msgid "" +"Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " +"section.\n" +"This is likely the result of clashing input options, and you may have to " +"rename one of them.\n" +msgstr "" +"მიმდინარეობს პარამეტრის '{0}' ინდექსაცია '{1}'-ით, მაგრამ '{0}' მნიშვნელობაა " +"და არა სექცია.\n" +"ეს, სავარაუდოდ, კონფლიქტური შეყვანის პარამეტრების შედეგია და შეიძლება ერთ-" +"ერთის სახელის გადარქმევა დაგჭირდეთ.\n" + +#: ../src/mesh/coordinates.cxx:1464 +msgid "" +"Unrecognised paralleltransform option.\n" +"Valid choices are 'identity', 'shifted', 'fci'" +msgstr "" +"უცნობი პარამეტრია paralleltransform.\n" +"დასაშვები მნიშვნელობებია 'identity', 'shifted', 'fci'" + +#: ../src/sys/options.cxx:899 +msgid "Unused options:\n" +msgstr "გამოუყენებელი პარამეტრები:\n" + +#: ../src/bout++.cxx:446 +#, c++-format +msgid "Usage is {:s} -d \n" +msgstr "გამოყენება: {:s} -d <მონაცემების_სააღალდე>\n" + +#: ../src/bout++.cxx:455 +#, c++-format +msgid "Usage is {:s} -f \n" +msgstr "გამოყენება: {:s} -f <პარამეტრების_ფაილის_სახელი>\n" + +#: ../src/bout++.cxx:473 +#, c++-format +msgid "Usage is {:s} -l \n" +msgstr "გამოყენება: {:s} -l <ჟურნალის_ფაილის_სახელი>\n" + +#: ../src/bout++.cxx:464 +#, c++-format +msgid "Usage is {:s} -o \n" +msgstr "გამოყენება: {:s} -o <პარამეტრების_ფაილის_სახელი>\n" + +#: ../src/bout++.cxx:360 +#, c++-format +msgid "Usage is {} {} \n" +msgstr "გამოყენება: {} {} <სახელი>\n" + +#: ../tests/unit/src/test_bout++.cxx:32 ../tests/unit/src/test_bout++.cxx:46 +msgid "Usage:" +msgstr "გამოყენება:" + +#. Print help message -- note this will be displayed once per processor as we've not +#. started MPI yet. +#: ../src/bout++.cxx:374 +#, c++-format +msgid "" +"Usage: {:s} [-d ] [-f ] [restart [append]] " +"[VAR=VALUE]\n" +msgstr "" +"გამოყენება: {:s} [-d <მონაცემთა_საქაღალდე>] [-f " +"<პარამეტრების_ფაილის_სახელი>] [restart [append]] [VAR=VALUE]\n" + +#. restart file should be written by physics model +#: ../src/solver/solver.cxx:927 +msgid "User signalled to quit. Returning\n" +msgstr "მომხმარებელმა მიგვანიშნა, მუშაობა დაგვემთავრებინა\n" + +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} = {:e} ლოგიკური არაა" + +#: ../src/sys/options.cxx:426 +#, c++-format +msgid "Value for option {:s} = {:e} is not an integer" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} = {:e} მთელი რიცხვი არაა" + +#: ../src/sys/options.cxx:456 +#, c++-format +msgid "Value for option {:s} cannot be converted to a BoutReal" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} BoutReal-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:623 +#, c++-format +msgid "Value for option {:s} cannot be converted to a Field2D" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} Field2D-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:571 +#, c++-format +msgid "Value for option {:s} cannot be converted to a Field3D" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} Field3D-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:705 +#, c++-format +msgid "Value for option {:s} cannot be converted to a FieldPerp" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} FieldPerp-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:491 +#, c++-format +msgid "Value for option {:s} cannot be converted to a bool" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} bool-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:751 +#, c++-format +msgid "Value for option {:s} cannot be converted to an Array" +msgstr "" +"მნიშვნელობა პარამეტრისთვის {:s} Array-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:773 +#, c++-format +msgid "Value for option {:s} cannot be converted to an Matrix" +msgstr "" +"მნიშვნელობა პარამეტრისთვის {:s} Matrix-ში გადაყვანილი ვერ იქნება" + +#: ../src/sys/options.cxx:795 +#, c++-format +msgid "Value for option {:s} cannot be converted to an Tensor" +msgstr "" +"მნიშვნელობა პარამეტრისთვის {:s} Tensor-ში გადაყვანილი ვერ იქნება" + +#. Another type which can't be converted +#: ../src/sys/options.cxx:418 +#, c++-format +msgid "Value for option {:s} is not an integer" +msgstr "მნიშვნელობა პარამეტრისთვის {:s} მთელი რიცხვი არაა" + +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 +#, c++-format +msgid "Variable '{:s}' not initialised" +msgstr "ცვლადი '{:s}' ინიციალიზებული არაა" + +#: ../src/mesh/impls/bout/boutmesh.cxx:467 +#, c++-format +msgid "" +"WARNING: Number of toroidal points should be 2^n for efficient FFT " +"performance -- consider changing MZ ({:d}) if using FFTs\n" +msgstr "" +"გაფრთხილება: FFT-ის ეფექტური წარმადობისთვის ტოროიდული წერტილების რაოდენობა " +"უნდა იყოს 2^n -- თუ FFT-ებს იყენებთ, განიხილეთ MZ-ის ({:d}) შეცვლა\n" + +#: ../src/mesh/coordinates.cxx:635 +msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" +msgstr "გაფრთხილება: შეყვანილი ბადის სიდიდეები ექსტრაპოლირდება x-სასაზღვრო უჯრედებში\n" + +#: ../src/mesh/coordinates.cxx:412 +msgid "" +"WARNING: extrapolating input mesh quantities into x-boundary cells. Set " +"option extrapolate_x=false to disable this.\n" +msgstr "" +"გაფრთხილება: შეყვანილი ბადის სიდიდეები ექსტრაპოლირდება x-სასაზღვრო უჯრედებში. " +"ამის გასათიშად დააყენეთ პარამეტრი extrapolate_x=false.\n" + +#: ../src/mesh/coordinates.cxx:640 +msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" +msgstr "გაფრთხილება: შეყვანილი ბადის სიდიდეები ექსტრაპოლირდება y-სასაზღვრო უჯრედებში\n" + +#: ../src/mesh/coordinates.cxx:417 +msgid "" +"WARNING: extrapolating input mesh quantities into y-boundary cells. Set " +"option extrapolate_y=false to disable this.\n" +msgstr "" +"გაფრთხილება: შეყვანილი ბადის სიდიდეები ექსტრაპოლირდება y-სასაზღვრო უჯრედებში. " +"ამის გასათიშად დააყენეთ პარამეტრი extrapolate_y=false.\n" + +#: ../src/bout++.cxx:825 +msgid "Wall time limit in hours. By default (< 0), no limit" +msgstr "კედლის დროის ზღვარი საათებში. ნაგულისხმევად (< 0) ზღვარი არ არსებობს" + +#: ../src/sys/optionsreader.cxx:42 +#, c++-format +msgid "Writing options to file {:s}\n" +msgstr "პარამეტრების ჩაწერა ფაილში {:s}\n" + +#. / The source label given to default values +#: ../src/sys/options.cxx:34 +msgid "default" +msgstr "ნაგულისხმევი" diff --git a/locale/libbout.pot b/locale/libbout.pot index 3895001ba0..2ef0618dd0 100644 --- a/locale/libbout.pot +++ b/locale/libbout.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,65 +17,70 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -83,40 +88,40 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, c++-format msgid "\tCandidate value: {:d}\n" msgstr "" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -133,31 +138,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " msgstr "" @@ -168,17 +173,17 @@ msgid "" "\tLine: {:s}" msgstr "" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -188,35 +193,31 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, c++-format msgid "\tNetCDF support {}{}\n" msgstr "" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, c++-format -msgid "\tOpenMP parallelisation {}" +msgid "\tOpenMP parallelisation {}, using {} threads\n" msgstr "" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "" -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +msgid "\tOption {} = {}" msgstr "" #: ../src/sys/options/options_ini.cxx:70 @@ -224,62 +225,62 @@ msgstr "" msgid "\tOptions file '{:s}' not found\n" msgstr "" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "" -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "" -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, c++-format msgid "\tSignal handling support {}\n" msgstr "" @@ -289,7 +290,7 @@ msgstr "" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "" @@ -299,7 +300,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -310,7 +311,7 @@ msgid "" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -318,14 +319,14 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, c++-format msgid "" "\n" "Run finished at : {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, c++-format msgid "" "\n" @@ -335,7 +336,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -363,7 +364,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -396,55 +397,55 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" msgstr "" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, c++-format msgid "BOUT++ version {:s}\n" msgstr "" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -455,7 +456,7 @@ msgstr "" msgid "Command line" msgstr "" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "" @@ -463,16 +464,16 @@ msgstr "" msgid "Compiled with flags" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, c++-format msgid "Could not create PID file {:s}" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "" @@ -482,28 +483,28 @@ msgstr "" msgid "Could not open output file '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -512,69 +513,69 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "" -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -584,122 +585,122 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, c++-format msgid "Option {:s} has no value" msgstr "" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" msgstr "" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, c++-format msgid "Revision: {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "" #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -709,64 +710,64 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -775,37 +776,37 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" @@ -816,7 +817,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -824,94 +825,99 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "" + +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -921,6 +927,6 @@ msgid "Writing options to file {:s}\n" msgstr "" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "" diff --git a/locale/zh_CN/libbout.po b/locale/zh_CN/libbout.po index 2c53b5392c..f735dd1727 100644 --- a/locale/zh_CN/libbout.po +++ b/locale/zh_CN/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2018-10-22 22:56+0100\n" "Last-Translator: \n" "Language-Team: Chinese (simplified)\n" @@ -16,109 +16,131 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> Core 区域 jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> Core 区域 jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> Core 区域 jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "" +"\t -> 有效值\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" +"\t -> Leg 区域 jyseps1_1+1 ({:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" +"\t -> leg 区域 jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" +"\t -> leg 区域 ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" +"\t -> leg 区域 ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) 必须是 MYSUB ({:d}) 的整数倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" +"\t -> ny/NYPE ({:d}/{:d} = {:d}) 必须 >= MYG ({:d})\n" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" +"\tADIOS2 支持 {}\n" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" +"\t异常中的回溯 {}\n" #. Loop over all possibilities #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, c++-format msgid "\tCandidate value: {:d}\n" msgstr "" +"\t候选值:{:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" +"\t日志着色 {}\n" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " -msgstr "" +msgstr "\t本次运行的命令行选项:" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "" +"\t编译标志:{:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" +"\t域已拆分为 (NXPE={:d}, NYPE={:d}),局部域为 (localNx={:d}, localNy={:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" +"\t错误:无法将 {:d} 个 Y 点平均分给 {:d} 个处理器\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" +"\t错误:无法将 {:d} 个 Z 点平均分给 {:d} 个处理器\n" #: ../src/sys/options/options_ini.cxx:200 #, c++-format @@ -126,39 +148,46 @@ msgid "" "\tEmpty key\n" "\tLine: {:s}" msgstr "" +"\t空键\n" +"\t行:{:s}" #: ../src/sys/optionsreader.cxx:127 #, c++-format msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "" +"\t命令行中存在空键或空值 '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" +"\t额外调试输出 {}\n" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" +"\tFFT 支持 {}\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" +"\t字段名跟踪 {}\n" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" +"\t浮点异常 {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " -msgstr "" +msgstr "\t网格大小:" -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " -msgstr "" +msgstr "\t保护单元 (x,y,z):" #: ../src/sys/options/options_ini.cxx:204 #, c++-format @@ -166,139 +195,159 @@ msgid "" "\tKey must not contain ':' character\n" "\tLine: {:s}" msgstr "" +"\t键中不能包含字符 ':'\n" +"\t行:{:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" +"\tLAPACK 支持 {}\n" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" +"\t消息栈 {}\n" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" +"\t度量模式为 {}\n" #: ../src/sys/optionsreader.cxx:111 #, c++-format msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" +"\t命令行参数 '{:s}' 中包含多个 '='\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" +"\t自然语言支持 {}\n" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, c++-format msgid "\tNetCDF support {}{}\n" msgstr "" +"\tNetCDF 支持 {}{}\n" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, c++-format -msgid "\tOpenMP parallelisation {}" +msgid "\tOpenMP parallelisation {}, using {} threads\n" msgstr "" +"\tOpenMP 并行化 {},使用 {} 个线程\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\t选项 " -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "" +msgid "\tOption {} = {}" +msgstr "\t选项 {} = {}" #: ../src/sys/options/options_ini.cxx:70 #, c++-format msgid "\tOptions file '{:s}' not found\n" msgstr "" +"\t未找到选项文件 '{:s}'\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" +"\tPETSc 支持 {}\n" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" +"\tPVODE 支持 {}\n" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "" +"\t并行 NetCDF 支持已禁用\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" +"\t并行 NetCDF 支持已启用\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" +"\t详细函数名支持 {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" +"\t已从输入网格文件读取 nz\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " -msgstr "" +msgstr "\t正在读取逆变向量 " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " -msgstr "" +msgstr "\t正在读取协变向量 " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" -msgstr "" +msgstr "\t运行时错误检查 {}" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" +"\tSLEPc 支持 {}\n" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" +"\tSUNDIALS 支持 {}\n" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" +"\tScore-P 支持 {}\n" -#: ../src/bout++.cxx:584 -#, fuzzy, c++-format +#: ../src/bout++.cxx:589 +#, c++-format msgid "\tSignal handling support {}\n" -msgstr "\t测试关掉\n" +msgstr "" +"\t信号处理支持 {}\n" #: ../src/solver/impls/split-rk/split-rk.cxx:76 #, c++-format msgid "\tUsing a timestep {:e}\n" msgstr "" +"\t使用时间步长 {:e}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "" +"\t完成\n" #: ../src/solver/impls/split-rk/split-rk.cxx:41 msgid "" "\n" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" +"\n" +"\tSplit Runge-Kutta-Legendre 与 SSP-RK3 求解器\n" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -308,37 +357,47 @@ msgid "" " -v, --verbose\t\t\tIncrease verbosity\n" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" +"\n" +" -d <数据目录>\t\t在 <数据目录> 中查找输入/输出文件\n" +" -f <选项文件名>\t\t使用 <选项文件名> 中给出的 OPTIONS\n" +" -o <设置文件名>\t将已使用的 OPTIONS 保存到 <选项文件名>\n" +" -l, --log <日志文件名>\t将日志输出到 <日志文件名>\n" +" -v, --verbose\t\t\t提高详细程度\n" +" -q, --quiet\t\t\t降低详细程度\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" " {1: ^{2}}{0}\n" " Did you mean '{0}'?" msgstr "" +"\n" +" {1: ^{2}}{0}\n" +" 您是不是想写 '{0}'?" -#: ../src/solver/solver.cxx:580 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:586 +#, c++-format msgid "" "\n" "Run finished at : {:s}\n" msgstr "" "\n" -"计算结束于 {:s}\n" +"运行结束时间:{:s}\n" -#: ../src/solver/solver.cxx:532 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:540 +#, c++-format msgid "" "\n" "Run started at : {:s}\n" msgstr "" "\n" -"计算从 {:s} 开始\n" +"运行开始时间:{:s}\n" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -365,8 +424,30 @@ msgid "" "\n" "{}" msgstr "" +"\n" +"发现未使用的输入选项:\n" +"-----\n" +"{:i}\n" +"-----\n" +"有些选项可能被误拼写了。BOUT++ 的输入参数现在区分大小写,\n" +"并且其中一些名称已经改变。您可以尝试运行\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"以自动修复最常见的问题。如果上面的这些选项有时会根据其他\n" +"选项而被使用,您可以调用 `Options::setConditionallyUsed()`,例如:\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"将某个节或值标记为依赖于其他值,从而在这项检查中忽略它。或者,\n" +"如果您确信以上输入并非错误,可以设置\n" +"'input:error_on_unused_options=false' 来关闭这项未使用选项检查。\n" +"您也始终可以设置 'input:validate=true',在不运行完整模拟的情况下\n" +"检查输入。\n" +"\n" +"{}" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -398,117 +479,148 @@ msgid "" "For all possible input parameters, see the user manual and/or the physics " "model source (e.g. {:s}.cxx)\n" msgstr "" +" --print-config\t\t显示编译时配置\n" +" --list-solvers\t\t列出可用的时间求解器\n" +" --help-solver \t显示指定时间求解器的帮助\n" +" --list-laplacians\t\t列出可用的拉普拉斯反演求解器\n" +" --help-laplacian \t显示指定拉普拉斯反演求解器的帮助\n" +" --list-laplacexz\t\t列出可用的 LaplaceXZ 反演求解器\n" +" --help-laplacexz \t显示指定 LaplaceXZ 反演求解器的帮助\n" +" --list-invertpars\t\t列出可用的 InvertPar 求解器\n" +" --help-invertpar \t显示指定 InvertPar 求解器的帮助\n" +" --list-rkschemes\t\t列出可用的 Runge-Kutta 格式\n" +" --help-rkscheme \t显示指定 Runge-Kutta 格式的帮助\n" +" --list-meshes\t\t\t列出可用的 Mesh\n" +" --help-mesh \t\t显示指定 Mesh 的帮助\n" +" --list-xzinterpolations\t列出可用的 XZInterpolation\n" +" --help-xzinterpolation \t显示指定 XZInterpolation 的帮助\n" +" --list-zinterpolations\t列出可用的 ZInterpolation\n" +" --help-zinterpolation \t显示指定 ZInterpolation 的帮助\n" +" -h, --help\t\t\t此消息\n" +" restart [append]\t\t重新启动模拟。若指定 append,则追加到现有输出文件,否则覆盖它们\n" +" VAR=VALUE\t\t\t为输入参数 VAR 指定一个 VALUE\n" +"\n" +"有关所有可能的输入参数,请参阅用户手册和/或物理模型源码(例如 {:s}.cxx)\n" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" +" -c, --color\t\t\t使用 bout-log-color 输出彩色日志\n" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" -msgstr "" +msgstr ") 被覆盖为:" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" -msgstr "" - -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" +msgstr ", 级别 {}" #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" -msgstr "" +msgstr "4 / 8" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" +"所有选项均已使用\n" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, c++-format msgid "BOUT++ version {:s}\n" msgstr "" +"BOUT++ 版本 {:s}\n" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" +"错误的命令行参数:\n" + +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "布尔运算符参数 {:e} 不是布尔值" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " -msgstr "" +msgstr "该处理器中的边界区域:" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" +"无法将 {:d} 个 X 点平均分配给 {:d} 个处理器\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." -msgstr "" +msgstr "检查文件是否存在,若存在则退出。" -#: ../src/bout++.cxx:533 -#, fuzzy, c++-format +#: ../src/bout++.cxx:540 +#, c++-format msgid "" "Code compiled on {:s} at {:s}\n" "\n" msgstr "" -"代码于 {:s} {:s} 编译\n" +"代码编译于 {:s},时间 {:s}\n" "\n" #: ../src/sys/optionsreader.cxx:130 msgid "Command line" -msgstr "" +msgstr "命令行" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "" +"编译时选项:\n" #: ../tests/unit/src/test_bout++.cxx:362 msgid "Compiled with flags" -msgstr "" +msgstr "编译标志" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" -msgstr "" +msgstr "正在构建默认区域" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, c++-format msgid "Could not create PID file {:s}" -msgstr "" +msgstr "无法创建 PID 文件 {:s}" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." -msgstr "" +msgstr "无法为 NXPE 找到有效值。请尝试使用不同数量的处理器。" #: ../src/sys/options/options_ini.cxx:160 #, c++-format msgid "Could not open output file '{:s}'\n" msgstr "" +"无法打开输出文件 '{:s}'\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" -msgstr "" +msgstr "无法打开 {:s}/{:s}.{:d} 进行写入" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" +"无法读取整数数组 '{:s}'\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" +"无法运行 bout-log-color。请确认它在您的 PATH 中\n" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" -msgstr "" +msgstr "无法添加监视器:{:g} 不是 {:g} 的整数倍!" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -516,195 +628,216 @@ msgid "" "may need to change your input file.\n" "{}" msgstr "" +"无法找到生成器 '{}'。BOUT++ 表达式现在区分大小写,因此\n" +"您可能需要修改输入文件。\n" +"{}" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" -msgstr "" +msgstr "无法在 regionMap2D 中找到区域 {:s}" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" -msgstr "" +msgstr "无法在 regionMap3D 中找到区域 {:s}" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" -msgstr "" +msgstr "无法在 regionMapPerp 中找到区域 {:s}" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" -msgstr "" +msgstr "无法从选项 {1:s} = '{2:s}' 获取 {0}:{3}" -#: ../src/bout++.cxx:508 -#, fuzzy, c++-format +#: ../src/bout++.cxx:515 +#, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" -msgstr "\"{:s}\" 不存在或不可访问\n" +msgstr "" +"数据目录 \"{:s}\" 不存在或不可访问\n" -#: ../src/bout++.cxx:505 -#, fuzzy, c++-format +#: ../src/bout++.cxx:512 +#, c++-format msgid "DataDir \"{:s}\" is not a directory\n" -msgstr "\"{:s}\" 不是目录\n" +msgstr "" +"数据目录 \"{:s}\" 不是目录\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" +"错误:求解器已经初始化\n" -#: ../src/bout++.cxx:209 -#, fuzzy, c++-format +#: ../src/bout++.cxx:216 +#, c++-format msgid "Error encountered during initialisation: {:s}\n" -msgstr "启动时遇到错误 : {:s}\n" +msgstr "" +"初始化期间发生错误:{:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" -msgstr "" +msgstr "写入设置时发生错误" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" -msgstr "" +msgstr "错误:nx 必须大于 2 倍 MXG(2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" +"求解器初始化失败 -> 中止\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" +"正在查找 NXPE 的值(理想值 = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "" +"正在初始化求解器\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" msgstr "" +"设置的输入文件和输出文件必须不同。\n" +"请提供 -o 以避免此问题。\n" #: ../src/sys/optionsreader.cxx:76 msgid "Invalid command line option '-' found - maybe check whitespace?" -msgstr "" +msgstr "发现无效的命令行选项 '-',也许应检查空白字符?" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" -msgstr "" +msgstr "正在加载网格" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" -msgstr "" +msgstr "网格必须包含 nx" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" -msgstr "" +msgstr "网格必须包含 ny" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" +"缺少整数数组 {:s}\n" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" +"监视器发出退出信号(异常 {})\n" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" -msgstr "" +msgstr "监视器发出退出信号(返回码 {})" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" -msgstr "" +msgstr "触发停止的文件名" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" -msgstr "" +msgstr "该处理器中没有边界区域" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" +"没有边界区域;区域是周期性的\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" +"处理器数量 ({:d}) 不能被 x 方向上的 NP 数 ({:d}) 整除\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" +"处理器数量 ({:d}) 不能被 y 方向上的 NP 数 ({:d}) 整除\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" +"只剩 {:e} 秒({:.2f} 步)。正在退出\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, c++-format msgid "Option {:s} has no value" -msgstr "" +msgstr "选项 {:s} 没有值" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, c++-format msgid "Option {:s}:{:s} does not exist" -msgstr "" +msgstr "选项 {:s}:{:s} 不存在" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." -msgstr "" +msgstr "选项:正在将来自同一来源 ({:s}) 的值设置为新值 '{:s}',旧值为 '{:s}'。" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " -msgstr "" +msgstr "可能的边界区域有:" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" +"处理器编号:{:d} / {:d}\n" +"\n" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" -msgstr "" +msgstr "已注册 2D 区域 {:s}" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" -msgstr "" +msgstr "已注册 3D 区域 {:s}" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" -msgstr "" +msgstr "已注册 Perp 区域 {:s}" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, c++-format msgid "Revision: {:s}\n" msgstr "" +"修订版本:{:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "计算时间" #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -714,66 +847,73 @@ msgstr "" #: ../tests/unit/src/test_bout++.cxx:359 msgid "Signal" -msgstr "" +msgstr "信号" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" +"模拟时间 | RHS 次数 | 墙钟时间 | 计算 反演 通信 I/O 求解器\n" +"\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" +"模拟时间 | RHS_e 次数 | RHS_I 次数 | 墙钟时间 | 计算 反演 通信 I/O 求解器\n" +"\n" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" +"求解器正在运行 {:d} 个输出,监视步长为 {:e}\n" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" +"求解器正在运行 {:d} 个输出,输出步长为 {:e}\n" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" -msgstr "" +msgstr "Solver::addMonitor:在调用 init 之后无法将时间步长从 {:g} 减少到 {:g}!" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" +"时间导数位于错误位置 - 字段位于 {:s},导数位于 {:s},对应字段 '{:s}'\n" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" -msgstr "" +msgstr "变量 '{:s}' 的时间导数尚未设置" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" -msgstr "" +msgstr "试图将已存在的区域 {:s} 添加到 regionMap2D" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" -msgstr "" +msgstr "试图将已存在的区域 {:s} 添加到 regionMap3D" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" -msgstr "" +msgstr "试图将已存在的区域 {:s} 添加到 regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -781,156 +921,179 @@ msgid "" "This is likely the result of clashing input options, and you may have to " "rename one of them.\n" msgstr "" +"正在尝试用 '{1}' 索引选项 '{0}',但 '{0}' 是一个值,而不是一个节。\n" +"这很可能是输入选项冲突导致的,您可能需要重命名其中之一。\n" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" +"无法识别的 paralleltransform 选项。\n" +"有效选项为 'identity'、'shifted'、'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" +"未使用的选项:\n" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" +"用法:{:s} -d <数据目录>\n" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" +"用法:{:s} -f <选项文件名>\n" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" +"用法:{:s} -l <日志文件名>\n" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" +"用法:{:s} -o <设置文件名>\n" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" +"用法:{} {} <名称>\n" #: ../tests/unit/src/test_bout++.cxx:32 ../tests/unit/src/test_bout++.cxx:46 msgid "Usage:" -msgstr "" +msgstr "用法:" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " "[VAR=VALUE]\n" msgstr "" +"用法:{:s} [-d <数据目录>] [-f <选项文件名>] [restart [append]] [VAR=VALUE]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" +"用户发出退出信号。正在返回\n" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "选项 {:s} = {:e} 的值不是布尔值" + +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" -msgstr "" +msgstr "选项 {:s} = {:e} 的值不是整数" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 BoutReal" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 Field2D" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 Field3D" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 FieldPerp" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 bool" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 Array" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 Matrix" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" -msgstr "" +msgstr "选项 {:s} 的值无法转换为 Tensor" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" -msgstr "" +msgstr "选项 {:s} 的值不是整数" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" -msgstr "" +msgstr "变量 '{:s}' 尚未初始化" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" +"警告:为了获得高效的 FFT 性能,环向点数应为 2^n;如果使用 FFT,请考虑修改 MZ ({:d})\n" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" +"警告:正在将输入网格量外推到 x 边界单元\n" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" +"警告:正在将输入网格量外推到 x 边界单元。设置选项 extrapolate_x=false 可禁用此行为。\n" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" +"警告:正在将输入网格量外推到 y 边界单元\n" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" +"警告:正在将输入网格量外推到 y 边界单元。设置选项 extrapolate_y=false 可禁用此行为。\n" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" -msgstr "" +msgstr "墙钟时间限制(小时)。默认值(< 0)表示不限制" #: ../src/sys/optionsreader.cxx:42 #, c++-format msgid "Writing options to file {:s}\n" msgstr "" +"正在将选项写入文件 {:s}\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" -msgstr "" +msgstr "默认" #~ msgid "\tChecking disabled\n" #~ msgstr "\t测试关掉\n" @@ -939,9 +1102,5 @@ msgstr "" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\t测试打开,级别 {:d}\n" -#, fuzzy -#~ msgid "Option {:s} is not a section" -#~ msgstr "\"{:s}\" 不是目录\n" - #~ msgid "Error encountered during initialisation\n" #~ msgstr "启动时遇到错误\n" diff --git a/locale/zh_TW/libbout.po b/locale/zh_TW/libbout.po index de0230d68d..8b79978d95 100644 --- a/locale/zh_TW/libbout.po +++ b/locale/zh_TW/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2018-10-22 22:56+0100\n" "Last-Translator: \n" "Language-Team: Chinese (traditional)\n" @@ -16,109 +16,131 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> Core 區域 jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> Core 區域 jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" +"\t -> Core 區域 jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" -msgstr "\t -> 好的號碼\n" +msgstr "" +"\t -> 好的號碼\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" +"\t -> Leg 區域 jyseps1_1+1 ({:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" +"\t -> leg 區域 jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" +"\t -> leg 區域 ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" +"\t -> leg 區域 ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) 必須是 MYSUB ({:d}) 的整數倍\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" +"\t -> ny/NYPE ({:d}/{:d} = {:d}) 必須 >= MYG ({:d})\n" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" +"\tADIOS2 支援 {}\n" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" +"\t例外中的回溯 {}\n" #. Loop over all possibilities #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:288 +#, c++-format msgid "\tCandidate value: {:d}\n" -msgstr "\t候選人數目 {:d}\n" +msgstr "" +"\t候選值:{:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" +"\t日誌著色 {}\n" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " -msgstr "" +msgstr "\t本次執行的命令列選項:" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 -#, fuzzy, c++-format +#: ../src/bout++.cxx:595 +#, c++-format msgid "\tCompiled with flags : {:s}\n" -msgstr "\t用設置編譯: {:s}\n" +msgstr "" +"\t編譯旗標:{:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 -#, fuzzy, c++-format +#: ../src/mesh/impls/bout/boutmesh.cxx:315 +#, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" -msgstr "\t域 (NXPE={:d}, NYPE={:d}) 分裂成域 (localNx={:d}, localNy={:d})\n" +msgstr "" +"\t網域已拆分為 (NXPE={:d}, NYPE={:d}),局部網域為 (localNx={:d}, localNy={:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" +"\t錯誤:無法將 {:d} 個 Y 點平均分配給 {:d} 個處理器\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" +"\t錯誤:無法將 {:d} 個 Z 點平均分配給 {:d} 個處理器\n" #: ../src/sys/options/options_ini.cxx:200 #, c++-format @@ -126,39 +148,46 @@ msgid "" "\tEmpty key\n" "\tLine: {:s}" msgstr "" +"\t空鍵\n" +"\t行:{:s}" #: ../src/sys/optionsreader.cxx:127 -#, fuzzy, c++-format +#, c++-format msgid "\tEmpty key or value in command line '{:s}'\n" -msgstr "\t命令行中的空鍵或值 '{:s}'\n" +msgstr "" +"\t命令列中存在空鍵或空值 '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" +"\t額外除錯輸出 {}\n" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" +"\tFFT 支援 {}\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" +"\t欄位名稱追蹤 {}\n" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" +"\t浮點例外 {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "\t網格大小: " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " -msgstr "" +msgstr "\t保護單元 (x,y,z):" #: ../src/sys/options/options_ini.cxx:204 #, c++-format @@ -166,140 +195,159 @@ msgid "" "\tKey must not contain ':' character\n" "\tLine: {:s}" msgstr "" +"\t鍵中不可包含字元 ':'\n" +"\t行:{:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" +"\tLAPACK 支援 {}\n" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" +"\t訊息堆疊 {}\n" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" +"\t度量模式為 {}\n" #: ../src/sys/optionsreader.cxx:111 #, c++-format msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" +"\t命令列參數 '{:s}' 中包含多個 '='\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" +"\t自然語言支援 {}\n" -#: ../src/bout++.cxx:567 -#, fuzzy, c++-format +#: ../src/bout++.cxx:574 +#, c++-format msgid "\tNetCDF support {}{}\n" -msgstr "\tOpenMP並行化已禁用\n" +msgstr "" +"\tNetCDF 支援 {}{}\n" -#: ../src/bout++.cxx:577 -#, fuzzy, c++-format -msgid "\tOpenMP parallelisation {}" -msgstr "\tOpenMP並行化已禁用\n" +#: ../src/bout++.cxx:585 +#, c++-format +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "" +"\tOpenMP 平行化 {},使用 {} 個執行緒\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\t選項 " -#: ../src/sys/options.cxx:447 -#, fuzzy, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "\t選項 '{:s}': 布爾預期. 拿到 '{:s}'\n" +#: ../src/sys/options.cxx:369 +#, c++-format +msgid "\tOption {} = {}" +msgstr "\t選項 {} = {}" #: ../src/sys/options/options_ini.cxx:70 -#, fuzzy, c++-format +#, c++-format msgid "\tOptions file '{:s}' not found\n" -msgstr "\t找不到選項文件 '{:s}'\n" +msgstr "" +"\t找不到選項檔案 '{:s}'\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" +"\tPETSc 支援 {}\n" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" +"\tPVODE 支援 {}\n" -#: ../src/bout++.cxx:557 -#, fuzzy +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" -msgstr "\tOpenMP並行化已禁用\n" +msgstr "" +"\t平行 NetCDF 支援已停用\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" +"\t平行 NetCDF 支援已啟用\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" +"\t詳細函式名稱支援 {}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" +"\t已從輸入網格檔案讀取 nz\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " -msgstr "" +msgstr "\t正在讀取逆變向量 " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " -msgstr "" +msgstr "\t正在讀取協變向量 " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" -msgstr "" +msgstr "\t執行期錯誤檢查 {}" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" +"\tSLEPc 支援 {}\n" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" +"\tSUNDIALS 支援 {}\n" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" +"\tScore-P 支援 {}\n" -#: ../src/bout++.cxx:584 -#, fuzzy, c++-format +#: ../src/bout++.cxx:589 +#, c++-format msgid "\tSignal handling support {}\n" -msgstr "\t測試關掉\n" +msgstr "" +"\t訊號處理支援 {}\n" #: ../src/solver/impls/split-rk/split-rk.cxx:76 #, c++-format msgid "\tUsing a timestep {:e}\n" msgstr "" +"\t使用時間步長 {:e}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" -msgstr "\t完\n" +msgstr "" +"\t完\n" #: ../src/solver/impls/split-rk/split-rk.cxx:41 msgid "" "\n" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" +"\n" +"\tSplit Runge-Kutta-Legendre 與 SSP-RK3 求解器\n" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -309,37 +357,47 @@ msgid "" " -v, --verbose\t\t\tIncrease verbosity\n" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" +"\n" +" -d <資料目錄>\t\t在 <資料目錄> 中尋找輸入/輸出檔案\n" +" -f <選項檔名>\t\t使用 <選項檔名> 中給出的 OPTIONS\n" +" -o <設定檔名>\t將已使用的 OPTIONS 儲存到 <選項檔名>\n" +" -l, --log <日誌檔名>\t將日誌輸出到 <日誌檔名>\n" +" -v, --verbose\t\t\t提高詳細程度\n" +" -q, --quiet\t\t\t降低詳細程度\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" " {1: ^{2}}{0}\n" " Did you mean '{0}'?" msgstr "" +"\n" +" {1: ^{2}}{0}\n" +" 您是不是想寫 '{0}'?" -#: ../src/solver/solver.cxx:580 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:586 +#, c++-format msgid "" "\n" "Run finished at : {:s}\n" msgstr "" "\n" -"计算结束于 {:s}\n" +"執行結束時間:{:s}\n" -#: ../src/solver/solver.cxx:532 -#, fuzzy, c++-format +#: ../src/solver/solver.cxx:540 +#, c++-format msgid "" "\n" "Run started at : {:s}\n" msgstr "" "\n" -"计算从 {:s} 开始\n" +"執行開始時間:{:s}\n" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -366,8 +424,30 @@ msgid "" "\n" "{}" msgstr "" +"\n" +"發現未使用的輸入選項:\n" +"-----\n" +"{:i}\n" +"-----\n" +"有些選項可能被拼錯了。BOUT++ 的輸入參數現在區分大小寫,\n" +"而且其中有些名稱已經改變。您可以嘗試執行\n" +"\n" +" /bin/bout-v5-input-file-upgrader.py {}/{}\n" +"\n" +"來自動修正常見問題。如果上面的這些選項有時會依賴其他選項\n" +"才被使用,您可以呼叫 `Options::setConditionallyUsed()`,例如:\n" +"\n" +" Options::root()[\"{}\"].setConditionallyUsed();\n" +"\n" +"將某個區段或值標記為依賴其他值,從而在這項檢查中忽略它。或者,\n" +"如果您確定以上輸入不是錯誤,可以設定\n" +"'input:error_on_unused_options=false' 來關閉這項未使用選項檢查。\n" +"您也隨時可以設定 'input:validate=true',在不執行完整模擬的情況下\n" +"檢查輸入。\n" +"\n" +"{}" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -399,118 +479,148 @@ msgid "" "For all possible input parameters, see the user manual and/or the physics " "model source (e.g. {:s}.cxx)\n" msgstr "" +" --print-config\t\t顯示編譯時設定\n" +" --list-solvers\t\t列出可用的時間求解器\n" +" --help-solver \t顯示指定時間求解器的說明\n" +" --list-laplacians\t\t列出可用的拉普拉斯反演求解器\n" +" --help-laplacian \t顯示指定拉普拉斯反演求解器的說明\n" +" --list-laplacexz\t\t列出可用的 LaplaceXZ 反演求解器\n" +" --help-laplacexz \t顯示指定 LaplaceXZ 反演求解器的說明\n" +" --list-invertpars\t\t列出可用的 InvertPar 求解器\n" +" --help-invertpar \t顯示指定 InvertPar 求解器的說明\n" +" --list-rkschemes\t\t列出可用的 Runge-Kutta 格式\n" +" --help-rkscheme \t顯示指定 Runge-Kutta 格式的說明\n" +" --list-meshes\t\t\t列出可用的 Mesh\n" +" --help-mesh \t\t顯示指定 Mesh 的說明\n" +" --list-xzinterpolations\t列出可用的 XZInterpolation\n" +" --help-xzinterpolation \t顯示指定 XZInterpolation 的說明\n" +" --list-zinterpolations\t列出可用的 ZInterpolation\n" +" --help-zinterpolation \t顯示指定 ZInterpolation 的說明\n" +" -h, --help\t\t\t此訊息\n" +" restart [append]\t\t重新啟動模擬。若指定 append,則附加到現有輸出檔案,否則覆寫它們\n" +" VAR=VALUE\t\t\t為輸入參數 VAR 指定一個 VALUE\n" +"\n" +"有關所有可能的輸入參數,請參閱使用者手冊和/或物理模型原始碼(例如 {:s}.cxx)\n" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" +" -c, --color\t\t\t使用 bout-log-color 輸出彩色日誌\n" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" -msgstr "" +msgstr ") 被覆寫為:" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" -msgstr "" - -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" +msgstr ", 等級 {}" #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" -msgstr "" +msgstr "4 / 8" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" +"所有選項皆已使用\n" -#: ../src/bout++.cxx:528 -#, fuzzy, c++-format +#: ../src/bout++.cxx:535 +#, c++-format msgid "BOUT++ version {:s}\n" -msgstr "BOUT++ 版 {:s}\n" +msgstr "" +"BOUT++ 版本 {:s}\n" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" +"錯誤的命令列參數:\n" + +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "布林運算子參數 {:e} 不是布林值" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " -msgstr "" +msgstr "此處理器中的邊界區域:" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" +"無法將 {:d} 個 X 點平均分配給 {:d} 個處理器\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." -msgstr "" +msgstr "檢查檔案是否存在,若存在則結束。" -#: ../src/bout++.cxx:533 -#, fuzzy, c++-format +#: ../src/bout++.cxx:540 +#, c++-format msgid "" "Code compiled on {:s} at {:s}\n" "\n" msgstr "" -"代碼於 {:s} {:s} 编译\n" +"程式碼編譯於 {:s},時間 {:s}\n" "\n" #: ../src/sys/optionsreader.cxx:130 msgid "Command line" -msgstr "" +msgstr "命令列" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" -msgstr "編譯選項:\n" +msgstr "" +"編譯選項:\n" #: ../tests/unit/src/test_bout++.cxx:362 -#, fuzzy msgid "Compiled with flags" -msgstr "\t用設置編譯: {:s}\n" +msgstr "編譯旗標" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" -msgstr "" +msgstr "正在建立預設區域" -#: ../src/bout++.cxx:520 -#, fuzzy, c++-format +#: ../src/bout++.cxx:527 +#, c++-format msgid "Could not create PID file {:s}" -msgstr "無法打開輸出文件 '{:s}'\n" +msgstr "無法建立 PID 檔案 {:s}" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "無法找到NXPE的有效值。 嘗試不同數量的處理器。" #: ../src/sys/options/options_ini.cxx:160 -#, fuzzy, c++-format +#, c++-format msgid "Could not open output file '{:s}'\n" -msgstr "無法打開輸出文件 '{:s}'\n" +msgstr "" +"無法開啟輸出檔案 '{:s}'\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" -msgstr "" +msgstr "無法開啟 {:s}/{:s}.{:d} 以供寫入" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" +"無法讀取整數陣列 '{:s}'\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" +"無法執行 bout-log-color。請確認它在您的 PATH 中\n" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" -msgstr "" +msgstr "無法加入監視器:{:g} 不是 {:g} 的整數倍!" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -518,195 +628,216 @@ msgid "" "may need to change your input file.\n" "{}" msgstr "" +"找不到產生器 '{}'。BOUT++ 表達式現在區分大小寫,因此\n" +"您可能需要修改輸入檔案。\n" +"{}" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" -msgstr "" +msgstr "無法在 regionMap2D 中找到區域 {:s}" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" -msgstr "" +msgstr "無法在 regionMap3D 中找到區域 {:s}" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" -msgstr "" +msgstr "無法在 regionMapPerp 中找到區域 {:s}" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" -msgstr "" +msgstr "無法從選項 {1:s} = '{2:s}' 取得 {0}:{3}" -#: ../src/bout++.cxx:508 -#, fuzzy, c++-format +#: ../src/bout++.cxx:515 +#, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" -msgstr "\"{:s}\" 不存在或不可訪問\n" +msgstr "" +"資料目錄 \"{:s}\" 不存在或無法存取\n" -#: ../src/bout++.cxx:505 -#, fuzzy, c++-format +#: ../src/bout++.cxx:512 +#, c++-format msgid "DataDir \"{:s}\" is not a directory\n" -msgstr "\"{:s}\" 不是目錄\n" +msgstr "" +"資料目錄 \"{:s}\" 不是目錄\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" +"錯誤:求解器已初始化\n" -#: ../src/bout++.cxx:209 -#, fuzzy, c++-format +#: ../src/bout++.cxx:216 +#, c++-format msgid "Error encountered during initialisation: {:s}\n" -msgstr "啟動時遇到錯誤 : {:s}\n" +msgstr "" +"初始化期間發生錯誤:{:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" -msgstr "" +msgstr "寫入設定時發生錯誤" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" -msgstr "" +msgstr "錯誤:nx 必須大於 2 倍 MXG(2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" +"初始化求解器失敗 -> 中止\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" +"正在尋找 NXPE 的值(理想值 = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" -msgstr "初始化求解器\n" +msgstr "" +"初始化求解器\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" msgstr "" +"設定的輸入檔與輸出檔必須不同。\n" +"請提供 -o 以避免此問題。\n" #: ../src/sys/optionsreader.cxx:76 msgid "Invalid command line option '-' found - maybe check whitespace?" -msgstr "" +msgstr "找到無效的命令列選項 '-',也許應檢查空白字元?" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "加載網格" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" -msgstr "" +msgstr "網格必須包含 nx" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" -msgstr "" +msgstr "網格必須包含 ny" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" +"缺少整數陣列 {:s}\n" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" +"監視器發出離開訊號(例外 {})\n" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" -msgstr "" +msgstr "監視器發出離開訊號(回傳碼 {})" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" -msgstr "" +msgstr "其存在會觸發停止的檔案名稱" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" -msgstr "" +msgstr "此處理器中沒有邊界區域" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" +"沒有邊界區域;區域是週期性的\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" +"處理器數量 ({:d}) 無法被 x 方向上的 NP 數 ({:d}) 整除\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" +"處理器數量 ({:d}) 無法被 y 方向上的 NP 數 ({:d}) 整除\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" +"只剩下 {:e} 秒({:.2f} 步)。正在結束\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 +#, c++-format msgid "Option {:s} has no value" -msgstr "\"{:s}\" 不是目錄\n" +msgstr "選項 {:s} 沒有值" #. Doesn't exist -#: ../src/sys/options.cxx:159 -#, fuzzy, c++-format +#: ../src/sys/options.cxx:172 +#, c++-format msgid "Option {:s}:{:s} does not exist" -msgstr "選項{:s}:{:s}不存在" +msgstr "選項 {:s}:{:s} 不存在" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." -msgstr "" +msgstr "選項:正在將來自相同來源 ({:s}) 的值設定為新值 '{:s}',舊值為 '{:s}'。" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " -msgstr "" +msgstr "可能的邊界區域有:" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" +"處理器編號:{:d} / {:d}\n" +"\n" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" -msgstr "" +msgstr "已註冊 2D 區域 {:s}" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" -msgstr "" +msgstr "已註冊 3D 區域 {:s}" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" -msgstr "" +msgstr "已註冊 Perp 區域 {:s}" -#: ../src/bout++.cxx:529 -#, fuzzy, c++-format +#: ../src/bout++.cxx:536 +#, c++-format msgid "Revision: {:s}\n" -msgstr "版: {:s}\n" +msgstr "" +"修訂版:{:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "計算時間" #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -716,72 +847,73 @@ msgstr "" #: ../tests/unit/src/test_bout++.cxx:359 msgid "Signal" -msgstr "" +msgstr "訊號" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -"模擬時間 | 評估數量 | 時鐘時間 | 計算 逆溫 通訊 輸入輸出 時" -"間整合\n" +"模擬時間 | 評估數量 | 時鐘時間 | 計算 逆溫 通訊 輸入輸出 時間整合\n" "\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -"模擬時間 | 評估數量(e) | 評估數量(I) | 時鐘時間 | 計算 逆溫 " -"通訊 輸入輸出 時間整合\n" +"模擬時間 | 評估數量(e) | 評估數量(I) | 時鐘時間 | 計算 逆溫 通訊 輸入輸出 時間整合\n" "\n" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" +"求解器正在執行 {:d} 個輸出,監視步長為 {:e}\n" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" +"求解器正在執行 {:d} 個輸出,輸出步長為 {:e}\n" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" -msgstr "" +msgstr "Solver::addMonitor:在呼叫 init 之後無法將時間步長從 {:g} 降低到 {:g}!" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" +"時間導數位於錯誤位置 - 欄位位於 {:s},導數位於 {:s},對應欄位 '{:s}'\n" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" -msgstr "" +msgstr "變數 '{:s}' 的時間導數尚未設定" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" -msgstr "" +msgstr "嘗試將已存在的區域 {:s} 加入 regionMap2D" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" -msgstr "" +msgstr "嘗試將已存在的區域 {:s} 加入 regionMap3D" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" -msgstr "" +msgstr "嘗試將已存在的區域 {:s} 加入 regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -789,157 +921,188 @@ msgid "" "This is likely the result of clashing input options, and you may have to " "rename one of them.\n" msgstr "" +"正在嘗試以 '{1}' 索引選項 '{0}',但 '{0}' 是一個值,而不是一個區段。\n" +"這很可能是輸入選項互相衝突的結果,您可能需要重新命名其中之一。\n" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" +"無法辨識的 paralleltransform 選項。\n" +"有效選項為 'identity'、'shifted'、'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" +"未使用的選項:\n" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" +"用法:{:s} -d <資料目錄>\n" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" +"用法:{:s} -f <選項檔名>\n" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" +"用法:{:s} -l <日誌檔名>\n" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" +"用法:{:s} -o <設定檔名>\n" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" +"用法:{} {} <名稱>\n" #: ../tests/unit/src/test_bout++.cxx:32 ../tests/unit/src/test_bout++.cxx:46 msgid "Usage:" -msgstr "" +msgstr "用法:" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " "[VAR=VALUE]\n" msgstr "" +"用法:{:s} [-d <資料目錄>] [-f <選項檔名>] [restart [append]] [VAR=VALUE]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" +"使用者發出離開訊號。正在返回\n" + +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "選項 {:s} = {:e} 的值不是布林值" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" -msgstr "" +msgstr "選項 {:s} = {:e} 的值不是整數" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 BoutReal" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 Field2D" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 Field3D" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 FieldPerp" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 bool" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 Array" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 Matrix" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" -msgstr "" +msgstr "選項 {:s} 的值無法轉換為 Tensor" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" -msgstr "" +msgstr "選項 {:s} 的值不是整數" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" -msgstr "" +msgstr "變數 '{:s}' 尚未初始化" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" +"警告:為了獲得高效的 FFT 效能,環向點數應為 2^n;若使用 FFT,請考慮修改 MZ ({:d})\n" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" +"警告:正在將輸入網格量外推到 x 邊界單元\n" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" +"警告:正在將輸入網格量外推到 x 邊界單元。設定選項 extrapolate_x=false 可停用此行為。\n" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" +"警告:正在將輸入網格量外推到 y 邊界單元\n" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" +"警告:正在將輸入網格量外推到 y 邊界單元。設定選項 extrapolate_y=false 可停用此行為。\n" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" -msgstr "" +msgstr "牆鐘時間限制(小時)。預設值(< 0)表示不限制" #: ../src/sys/optionsreader.cxx:42 -#, fuzzy, c++-format +#, c++-format msgid "Writing options to file {:s}\n" -msgstr "寫選項到文件 " +msgstr "" +"正在將選項寫入檔案 {:s}\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "默认设置" +#, fuzzy, c++-format +#~ msgid "\tOpenMP parallelisation {}" +#~ msgstr "\tOpenMP並行化已禁用\n" + +#, fuzzy, c++-format +#~ msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +#~ msgstr "\t選項 '{:s}': 布爾預期. 拿到 '{:s}'\n" + #~ msgid "\tChecking disabled\n" #~ msgstr "\t測試關掉\n" @@ -947,13 +1110,5 @@ msgstr "默认设置" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\t測試打開,级别 {:d}\n" -#, fuzzy -#~ msgid "\tOpenMP parallelisation enabled, using {:d} threads\n" -#~ msgstr "\t啟用OpenMP並行化。 使用{:d}個線程\n" - -#, fuzzy -#~ msgid "Option {:s} is not a section" -#~ msgstr "\"{:s}\" 不是目錄\n" - #~ msgid "Error encountered during initialisation\n" #~ msgstr "啟動時遇到錯誤\n" diff --git a/manual/CMakeLists.txt b/manual/CMakeLists.txt index c8e22b1dcf..87f5101e58 100644 --- a/manual/CMakeLists.txt +++ b/manual/CMakeLists.txt @@ -6,28 +6,37 @@ find_package(Sphinx REQUIRED) set(BOUT_SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/sphinx) set(BOUT_SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs) -add_custom_target(sphinx-html - COMMAND ${SPHINX_EXECUTABLE} -b html ${BOUT_SPHINX_SOURCE} ${BOUT_SPHINX_BUILD} - COMMAND ${CMAKE_COMMAND} -E echo "Generated HTML docs in file://${BOUT_SPHINX_BUILD}/index.html" +set(env_command ${CMAKE_COMMAND} -E env + PYTHONPATH=${BOUT_PYTHONPATH}:$ENV{PYTHONPATH} +) + +add_custom_target( + sphinx-html + COMMAND ${env_command} ${SPHINX_EXECUTABLE} -b html ${BOUT_SPHINX_SOURCE} + ${BOUT_SPHINX_BUILD} + COMMAND ${CMAKE_COMMAND} -E echo + "Generated HTML docs in file://${BOUT_SPHINX_BUILD}/index.html" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating HTML documentation with Sphinx in ${BOUT_SPHINX_BUILD}" ) -add_custom_target(sphinx-pdf - COMMAND ${SPHINX_EXECUTABLE} -M latexpdf ${BOUT_SPHINX_SOURCE} ${BOUT_SPHINX_BUILD} - COMMAND ${CMAKE_COMMAND} -E echo "Generated PDF docs in file://${BOUT_SPHINX_BUILD}" +add_custom_target( + sphinx-pdf + COMMAND ${env_command} ${SPHINX_EXECUTABLE} -M latexpdf ${BOUT_SPHINX_SOURCE} + ${BOUT_SPHINX_BUILD} + COMMAND ${CMAKE_COMMAND} -E echo + "Generated PDF docs in file://${BOUT_SPHINX_BUILD}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating PDF documentation with Sphinx in ${BOUT_SPHINX_BUILD}" ) -set_target_properties(sphinx-html sphinx-pdf PROPERTIES - ENVIRONMENT PYTHONPATH=${BOUT_PYTHONPATH}:$ENV{PYTHONPATH} -) - -add_custom_target(docs ALL) +add_custom_target(docs) add_dependencies(docs sphinx-html) -install(DIRECTORY ${BOUT_SPHINX_BUILD}/ +install( + DIRECTORY ${BOUT_SPHINX_BUILD}/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/bout++/ + EXCLUDE_FROM_ALL + COMPONENT docs PATTERN .* EXCLUDE ) diff --git a/manual/RELEASE_HOWTO.md b/manual/RELEASE_HOWTO.md index d8ced2afb5..d0a6ddb231 100644 --- a/manual/RELEASE_HOWTO.md +++ b/manual/RELEASE_HOWTO.md @@ -29,11 +29,10 @@ Before merging PR: - Be aware that this *will* update the timestamps and *possibly* reorder file paths in the .po and .pot files - [ ] Update [`CHANGELOG.md`][changelog]: - - Run [bout-changelog-generator.py LAST_RELEASE NEXT_RELEASE][bin/bout-changelog-generator.py] + - Run [`bout-changelog-generator.py LAST_RELEASE NEXT_RELEASE`][bin/bout-changelog-generator.py] - See the docs for how to get the token -- [ ] Get list of authors: - - [ ] `git log --format='%aN' | sort | uniq` - - [ ] Compare to list in [`CITATION.cff`][citation], add new authors +- [ ] Run [`update_citations.py`][bin/update_citations.py] to add new + authors to [`CITATION.cff`](CITATION.cff) - [ ] Prep a new Zenodo release: - https://doi.org/10.5281/zenodo.1423212 - "New Version" @@ -44,13 +43,7 @@ Before merging PR: - [ ] Change DOI in [`README.md`][README] to new DOI - [ ] Change date-released in [`CITATION.cff`][citation] - [ ] Check `abidiff` to see if `soname` needs bumping in `makefile`: -- [ ] Change version number, removing prerelease tag in: - - [ ] [`configure.ac`][configure]: `AC_INIT` - - [ ] [`CITATION.cff`][citation]: `version` - - [ ] [`manual/sphinx/conf.py`][sphinx_conf]: `version` and `release` - - [ ] [`manual/doxygen/Doxyfile_readthedocs`][Doxyfile_readthedocs]: `PROJECT_NUMBER` - - [ ] [`manual/doxygen/Doxyfile`][Doxyfile]: `PROJECT_NUMBER` - - [ ] [`CMakeLists.txt`][CMakeLists]: `_bout_previous_version`, `_bout_next_version` +- [ ] Run [`update_version_number.py LAST_RELEASE NEXT_RELEASE`][bin/update_version_number.py] - [ ] Update what version of PETSc and SUNDIALS we support (upper bound) diff --git a/manual/doxygen/Doxyfile b/manual/doxygen/Doxyfile index 0e3c6f6945..b7ae4d7a58 100644 --- a/manual/doxygen/Doxyfile +++ b/manual/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = BOUT++ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 5.1.1 +PROJECT_NUMBER = 5.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -246,34 +246,6 @@ ALIASES = TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it @@ -328,21 +300,7 @@ AUTOLINK_SUPPORT = YES # diagrams that involve STL classes more complete and accurate. # The default value is: NO. -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO +BUILTIN_STL_SUPPORT = YES # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make @@ -352,7 +310,7 @@ SIP_SUPPORT = NO # should set this option to NO. # The default value is: YES. -IDL_PROPERTY_SUPPORT = YES +IDL_PROPERTY_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first @@ -435,13 +393,13 @@ LOOKUP_CACHE_SIZE = 0 # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = YES +EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = YES +EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. @@ -463,14 +421,6 @@ EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = YES - # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of @@ -508,7 +458,7 @@ HIDE_FRIEND_COMPOUNDS = NO # blocks will be appended to the function's detailed documentation block. # The default value is: NO. -HIDE_IN_BODY_DOCS = NO +HIDE_IN_BODY_DOCS = YES # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation @@ -590,7 +540,7 @@ SORT_BRIEF_DOCS = NO # detailed member documentation. # The default value is: NO. -SORT_MEMBERS_CTORS_1ST = NO +SORT_MEMBERS_CTORS_1ST = YES # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will @@ -623,19 +573,19 @@ STRICT_PROTO_MATCHING = NO # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. -GENERATE_TODOLIST = YES +GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. -GENERATE_TESTLIST = YES +GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. -GENERATE_BUGLIST = YES +GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in @@ -673,7 +623,7 @@ SHOW_USED_FILES = YES # (if specified). # The default value is: YES. -SHOW_FILES = YES +SHOW_FILES = NO # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the @@ -791,7 +741,7 @@ WARN_LOGFILE = # Note: If this tag is empty the current directory is searched. INPUT = ../../include/bout \ - ../../src/ + ../../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -816,11 +766,8 @@ INPUT_ENCODING = UTF-8 # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. -FILE_PATTERNS = *.c \ - *.cxx \ - *.h \ - *.hxx \ - *.py +FILE_PATTERNS = *.h \ + *.hxx # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -840,7 +787,8 @@ EXCLUDE = ../../examples \ ../../manual/ \ ../../bin/ \ ../../externalpackages/googletest/ \ - ../../tests/ + ../../tests/ \ + ../../build/_deps/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -858,99 +806,6 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1005,7 +860,7 @@ REFERENCES_LINK_SOURCE = YES # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. -SOURCE_TOOLTIPS = YES +SOURCE_TOOLTIPS = NO # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in @@ -1048,21 +903,6 @@ VERBATIM_HEADERS = NO ALPHABETICAL_INDEX = NO -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- @@ -1070,542 +910,7 @@ IGNORE_PREFIX = # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /