diff --git a/.build_petsc_for_ci.sh b/.build_petsc_for_ci.sh index f9516b882a..ce69944c9c 100755 --- a/.build_petsc_for_ci.sh +++ b/.build_petsc_for_ci.sh @@ -20,7 +20,7 @@ if test $BUILD_PETSC ; then --with-scalar-type=real \ --with-shared-libraries=1 \ --with-debugging=0 \ - {C,CXX,F}OPTFLAGS="-O3 -march=native" \ + {C,CXX,F}OPTFLAGS="-O3" \ --prefix=$HOME/local/petsc make && make install diff --git a/.ci_fedora.sh b/.ci_fedora.sh index badb1daa29..1a3d2d92b2 100755 --- a/.ci_fedora.sh +++ b/.ci_fedora.sh @@ -58,7 +58,7 @@ else cd cd BOUT-dev echo "starting configure" - time cmake -DBOUT_USE_PETSC=ON -S . -B build + time cmake -S . -B build -DBOUT_USE_PETSC=ON time make -C build build-check -j 2 time make -C build check fi diff --git a/.ci_with_cmake.sh b/.ci_with_cmake.sh index 2108ebe807..3381c4a380 100755 --- a/.ci_with_cmake.sh +++ b/.ci_with_cmake.sh @@ -3,13 +3,23 @@ set -ex cmake --version -cmake . -B build $@ -DCMAKE_INSTALL_PREFIX=$(pwd)/installed +cmake -S . -B build $@ -DCMAKE_INSTALL_PREFIX=$(pwd)/installed + +if test ".$UNIT_ONLY" = ".YES" ; then + make -C build build-check-unit-tests + make -C build check-unit-tests + exit 0 +fi + cmake --build build --target build-check -j 2 cd build ctest --output-on-failure --timeout 300 +export LD_LIBRARY_PATH=/home/runner/local/lib:$LD_LIBRARY_PATH + # Test bout-config basic functionallity cd ../examples/make-script +PATH=../../build/bin:$PATH bout-config --all PATH=../../build/bin:$PATH make ./test --help cd - @@ -25,6 +35,7 @@ rm -rf build # Test installation with plain `make` cd ../examples/make-script rm test +PATH=../../installed/bin:$PATH bout-config --all PATH=../../installed/bin:$PATH make ./test --help cd - diff --git a/.clang-tidy b/.clang-tidy index fbd5d2f27c..7a1c58af80 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,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-vararg,-clang-analyzer-optin.mpi*,-bugprone-exception-escape,-cppcoreguidelines-pro-bounds-pointer-arithmetic' +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,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-vararg,-clang-analyzer-optin.mpi*,-bugprone-exception-escape,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-readability-function-cognitive-complexity' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false diff --git a/.docker/build.sh b/.docker/build.sh new file mode 100644 index 0000000000..12b56c767f --- /dev/null +++ b/.docker/build.sh @@ -0,0 +1,29 @@ +set -ex + +if which docker &> /dev/null ; then + cmd="time sudo docker" +else + cmd="time podman" +fi + +file=$1 +(test $file && test -f $file) || file=.docker/fedora/Dockerfile +test $# -gt 0 && shift + +if test -x $file +then + COMMIT=$(git rev-parse HEAD) $file $@ > Dockerfile +else + cp $file Dockerfile +fi + +$cmd login -p $DOCKER_TOKEN -u $DOCKER_USER + +cat Dockerfile + +$cmd build -t mobydick . --build-arg=COMMIT=$(git rev-parse HEAD) --build-arg=MPI=$MPI --build-arg=CMAKE_OPTIONS="$CMAKE_OPTIONS" --build-arg=BASE=$BASE +for tag in $TAGS +do + $cmd tag mobydick $tag + $cmd push $tag +done diff --git a/.docker/fedora/Dockerfile b/.docker/fedora/Dockerfile new file mode 100644 index 0000000000..56445f8cea --- /dev/null +++ b/.docker/fedora/Dockerfile @@ -0,0 +1,39 @@ +ARG BASE +FROM ghcr.io/dschwoerer/bout-container-base:$BASE + +# ---------------------------------------------------------------- +# Build and install BOUT++ +# ---------------------------------------------------------------- +# user: boutuser +# password: boutforever + +ARG MPI +ARG URL +ARG COMMIT +ARG CMAKE_OPTIONS + +RUN sudo ls + +# Checkout submodules now so configure later is fast, and iterating on +# it less painful +RUN git clone $URL \ + && chown -R boutuser /home/boutuser/BOUT-dev \ + && cd BOUT-dev \ + && git checkout $COMMIT \ + && git submodule update --init --recursive + + +WORKDIR /home/boutuser/BOUT-dev + +RUN cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/opt/bout++/ \ + -DBOUT_GENERATE_FIELDOPS=OFF \ + -DBOUT_USE_PETSC=ON -DPETSc_ROOT=/opt/petsc \ + -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) + + +RUN make -C build -j 2 +RUN sudo make -C build install + +RUN find /opt/bout++ diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..efa4ca465b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 + +updates: + - package-ecosystem: "gitsubmodule" + schedule: + interval: "daily" + directory: "/" + + - package-ecosystem: "pip" + schedule: + interval: "daily" + directory: "/" + + - package-ecosystem: "github-actions" + schedule: + interval: "weekly" + directory: "/" diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 86161f583d..24e87cd447 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -22,7 +22,7 @@ jobs: submodules: true - name: Run clang-tidy - uses: ZedThree/clang-tidy-review@v0.8.4 + uses: ZedThree/clang-tidy-review@v0.13.1 id: review with: build_dir: build @@ -44,3 +44,6 @@ jobs: -DBOUT_ENABLE_PYTHON=OFF \ -DCMAKE_EXPORT_COMPILE_COMMANDS=On \ -DBOUT_UPDATE_GIT_SUBMODULE=OFF + + - name: Upload clang-tidy fixes + uses: ZedThree/clang-tidy-review/upload@v0.13.1 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000000..dda81cd8fc --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,84 @@ +name: Docker + +on: + push: + branches: + - master + - next + # Add your branch here if you want containers for it + - db-WIP + - docker-ci + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build: + name: Build ${{ matrix.config.name }} Container (${{ matrix.metric3d.name }} ; ${{matrix.mpi}}) + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + strategy: + fail-fast: false + matrix: + mpi: [mpich] + metric3d: + - name: "With OpenMP" + cmake: ON + base_prefix: "openmp-" + tag_prefix: "3d-" + - name: "Without OpenMP" + cmake: OFF + base_prefix: "" + tag_prefix: "" + config: + - name: "Debug" + tag_postfix: "debug" + options: "-DCHECK=3" + base_postfix: "mini" + + - name: "Optimised" + tag_postfix: "opt" + options: "-DCHECK=0" + base_postfix: "mini" + + - name: "Full" + tag_postfix: "full" + options: "-DCHECK=3" + base_postfix: "full" + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + prefix=${{ matrix.mpi }}-${{matrix.metric3d.tag_prefix}}${{ matrix.config.tag_postfix }}- + + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + 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 }} + COMMIT=${{ github.sha }} + URL=${{ github.server_url }}/${{ github.repository }} + context: .docker/fedora/ + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ec0c7f2759..da209d6595 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: OMPI_MCA_rmaps_base_oversubscribe: yes MPIRUN: mpiexec -np strategy: - fail-fast: false + fail-fast: true matrix: # Need this to be able to exclude the coverage job is_master_or_next: @@ -33,37 +33,34 @@ jobs: config: - name: "Default options, Ubuntu 20.04" os: ubuntu-20.04 - configure_options: "" - script_flags: "-uim" + cmake_options: "" - - name: "Optimised, shared, Python" + - name: "Optimised, static" os: ubuntu-20.04 - configure_options: "--enable-shared - --enable-checks=no - --enable-optimize=3 - --disable-signal - --disable-track - --disable-backtrace - --with-petsc - --with-slepc - --with-sundials=/home/runner/local" - script_flags: "-uim -t shared -t python" - omp_num_threads: 1 + cmake_options: "-DCHECK=0 + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_CXX_FLAGS=-Ofast + -DBOUT_ENABLE_SIGNAL=OFF + -DBOUT_ENABLE_TRACK=OFF + -DBOUT_ENABLE_BACKTRACE=OFF + -DBOUT_USE_PETSC=ON + -DBOUT_USE_SLEPC=ON + -DBOUT_USE_SUNDIALS=ON + -DSUNDIALS_ROOT=/home/runner/local" - name: "Debug, shared" os: ubuntu-20.04 - configure_options: "--enable-shared - --enable-sigfpe - --enable-debug - --enable-track - --with-petsc - --with-slepc - --with-sundials=/home/runner/local" - script_flags: "-uim" - omp_num_threads: 1 - - - name: "CMake, shared, release" - os: ubuntu-latest + cmake_options: "-DCHECK=3 + -DCMAKE_BUILD_TYPE=Debug + -DBOUT_ENABLE_SIGNAL=ON + -DBOUT_ENABLE_TRACK=ON + -DBOUT_USE_PETSC=ON + -DBOUT_USE_SLEPC=ON + -DBOUT_USE_SUNDIALS=ON + -DSUNDIALS_ROOT=/home/runner/local" + + - name: "Shared, release, Ubuntu 20.04" + os: ubuntu-20.04 cmake_options: "-DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_OPENMP=ON -DCMAKE_BUILD_TYPE=Release @@ -74,7 +71,7 @@ jobs: -DSUNDIALS_ROOT=/home/runner/local" omp_num_threads: 2 - - name: "CMake, shared, OpenMP, 3D metrics" + - name: "Shared, OpenMP, 3D metrics" os: ubuntu-latest cmake_options: "-DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_METRIC_3D=ON @@ -103,16 +100,17 @@ jobs: - name: "Coverage" os: ubuntu-20.04 - configure_options: "--enable-shared - --enable-code-coverage - --enable-debug - --enable-track - --with-lapack - --with-petsc - --with-slepc - --with-sundials=/home/runner/local" - omp_num_threads: 1 - script_flags: "-u" + cmake_options: "-DBUILD_SHARED_LIBS=ON + -DCMAKE_BUILD_TYPE=Debug + -DCHECK=3 + -DENABLE_COVERAGE=ON + -DBOUT_USE_PETSC=ON + -DBOUT_USE_SLEPC=ON + -DBOUT_USE_HDF5=ON + -DBOUT_USE_SUNDIALS=ON + -DBOUT_ENABLE_PYTHON=ON + -DSUNDIALS_ROOT=/home/runner/local" + unit_only: YES exclude: # Don't run the coverage tests if the branch isn't master or next - is_master_or_next: false @@ -123,7 +121,6 @@ jobs: - name: Job information run: | echo Build: ${{ matrix.config.name }}, ${{ matrix.config.os }} - echo Configure options: ${{ matrix.config.configure_options }} echo CMake options: ${{ matrix.config.cmake_options }} - name: Install dependencies @@ -152,7 +149,7 @@ jobs: - name: Install pip packages run: | - ./.pip_install_for_ci.sh 'cython~=0.29' 'netcdf4~=1.5' 'sympy~=1.5' 'gcovr' 'cmake' 'h5py' 'zoidberg' 'natsort' + ./.pip_install_for_ci.sh 'cython~=0.29' 'netcdf4~=1.5' 'sympy~=1.5' 'gcovr' 'cmake' zoidberg fastcov # Add the pip install location to the runner's PATH echo ~/.local/bin >> $GITHUB_PATH @@ -168,16 +165,8 @@ jobs: - name: Build PETSc run: BUILD_PETSC=${{ matrix.config.build_petsc }} ./.build_petsc_for_ci.sh - - name: Build (configure) - if: ${{ ! contains(matrix.config.name, 'CMake') }} - run: ./.ci_script.sh ${{ matrix.config.script_flags }} - env: - LD_LIBRARY_PATH: /home/runner/local/lib:$LD_LIBRARY_PATH - CONFIGURE_OPTIONS: ${{ matrix.config.configure_options }} - - - name: Build (CMake) - if: ${{ contains(matrix.config.name, 'CMake') }} - run: ./.ci_with_cmake.sh ${{ matrix.config.cmake_options }} + - name: Build BOUT++ + run: UNIT_ONLY=${{ matrix.config.unit_only }} ./.ci_with_cmake.sh ${{ matrix.config.cmake_options }} - name: Capture coverage if: ${{ matrix.config.name == 'Coverage' }} @@ -189,7 +178,7 @@ jobs: # This is to try and make the coverage report slightly more accurate # It still won't include, e.g. any solvers we don't build with though find . -name "*.gcno" -exec sh -c 'touch -a "${1%.gcno}.gcda"' _ {} \; - make code-coverage-capture + make -C build code-coverage-capture - name: Upload coverage if: ${{ matrix.config.name == 'Coverage' }} diff --git a/.gitignore b/.gitignore index 88b3e5a574..7ddf9526ab 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,9 @@ src/fmt/format.cxx /tests/integrated/test-options-netcdf/time.nc /tests/integrated/test-yupdown-weights/test_yupdown_weights +coverage.info +coverage/ + # Potential user build directories /build/ /build*/ @@ -78,4 +81,7 @@ src/fmt/format.cxx # Python stuff /_wheel*/ /dist/ +/manual/sphinx/_build /_version.txt +/BOUT++-v*.tar.gz +/BOUT++-v*.tar.xz diff --git a/.pip_install_for_ci.sh b/.pip_install_for_ci.sh index 26ca80481a..4a5258cc2d 100755 --- a/.pip_install_for_ci.sh +++ b/.pip_install_for_ci.sh @@ -4,7 +4,7 @@ set -e export PATH=${HOME}/.local/bin:${PATH} pip3 install --user --upgrade pip~=20.0 setuptools~=46.1 -pip3 install --user --upgrade scipy~=1.4 numpy~=1.18 +pip3 install --user --upgrade scipy~=1.4 numpy~=1.18 natsort~=8.1.0 for package in $@ do if test $package == "cython" diff --git a/CHANGELOG.md b/CHANGELOG.md index 328c9fd4c1..4d20a10f78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,49 @@ # Changelog +## [v5.1.0](https://github.com/boutproject/BOUT-dev/tree/v5.1.0 + +[Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.0.0...v5.1.0) + +- Update RELEASE_HOWTO.md [\#2741][https://github.com/boutproject/BOUT-dev/pull/2741] ([dschwoerer][https://github.com/dschwoerer]) +- Remove h5py - we only support netcdf [\#2735][https://github.com/boutproject/BOUT-dev/pull/2735] ([dschwoerer][https://github.com/dschwoerer]) +- CI: Install dnf5 for Fedora [\#2731][https://github.com/boutproject/BOUT-dev/pull/2731] ([dschwoerer][https://github.com/dschwoerer]) +- Improving compatibility with fmt 10 [\#2730][https://github.com/boutproject/BOUT-dev/pull/2730] ([dschwoerer][https://github.com/dschwoerer]) +- Bump `clang-tidy-review` version [\#2726][https://github.com/boutproject/BOUT-dev/pull/2726] ([ZedThree][https://github.com/ZedThree]) +- Revert sundials detection [\#2725][https://github.com/boutproject/BOUT-dev/pull/2725] ([dschwoerer][https://github.com/dschwoerer]) +- Fix static CI build [\#2724][https://github.com/boutproject/BOUT-dev/pull/2724] ([dschwoerer][https://github.com/dschwoerer]) +- CI install natsort [\#2723][https://github.com/boutproject/BOUT-dev/pull/2723] ([bendudson][https://github.com/bendudson]) +- Fix FV::Div_a_Grad_perp Y alignment [\#2722][https://github.com/boutproject/BOUT-dev/pull/2722] ([bendudson][https://github.com/bendudson]) +- Generate BOUT++ tar via boutpp backend [\#2708][https://github.com/boutproject/BOUT-dev/pull/2708] ([dschwoerer][https://github.com/dschwoerer]) +- Build containers in GHA CI [\#2511][https://github.com/boutproject/BOUT-dev/pull/2511] ([dschwoerer][https://github.com/dschwoerer]) +- Update to dnf5 (master) [\#2732][https://github.com/boutproject/BOUT-dev/pull/2732] ([dschwoerer][https://github.com/dschwoerer]) +- Solver improvements [\#2716][https://github.com/boutproject/BOUT-dev/pull/2716] ([bendudson][https://github.com/bendudson]) +- Get mesh outputs after physics init [\#2714][https://github.com/boutproject/BOUT-dev/pull/2714] ([bendudson][https://github.com/bendudson]) +- Remove unnecessary check for aligned fields when applying twist-shift [\#2711][https://github.com/boutproject/BOUT-dev/pull/2711] ([dschwoerer][https://github.com/dschwoerer]) +- Do not try to run SLEPc or PETSc in configure [\#2709][https://github.com/boutproject/BOUT-dev/pull/2709] ([dschwoerer][https://github.com/dschwoerer]) +- Update `make dist` invocation [\#2707][https://github.com/boutproject/BOUT-dev/pull/2707] ([dschwoerer][https://github.com/dschwoerer]) +- Add support for PETSc & SLEPc 3.18 / 3.19 [\#2704][https://github.com/boutproject/BOUT-dev/pull/2704] ([ZedThree][https://github.com/ZedThree]) +- mesh:paralleltransform is a section [\#2702][https://github.com/boutproject/BOUT-dev/pull/2702] ([dschwoerer][https://github.com/dschwoerer]) +- Remove last uses of `bout::globals::dump` [\#2699][https://github.com/boutproject/BOUT-dev/pull/2699] ([ZedThree][https://github.com/ZedThree]) +- Docs: Fix default branch for "suggest edit" [\#2697][https://github.com/boutproject/BOUT-dev/pull/2697] ([ZedThree][https://github.com/ZedThree]) +- CI: do not run on removed old ubuntu [\#2695][https://github.com/boutproject/BOUT-dev/pull/2695] ([dschwoerer][https://github.com/dschwoerer]) +- isUniform: Do not fail if numbers are only almost equal [\#2693][https://github.com/boutproject/BOUT-dev/pull/2693] ([dschwoerer][https://github.com/dschwoerer]) +- Docs for docs improvements [\#2690][https://github.com/boutproject/BOUT-dev/pull/2690] ([dschwoerer][https://github.com/dschwoerer]) +- Recommend `requirements.txt` for dependencies [\#2689][https://github.com/boutproject/BOUT-dev/pull/2689] ([dschwoerer][https://github.com/dschwoerer]) +- Fall back to pkgconfig for finding netcdf-cxx4 [\#2686][https://github.com/boutproject/BOUT-dev/pull/2686] ([dschwoerer][https://github.com/dschwoerer]) +- Fix pvode warnings [\#2684][https://github.com/boutproject/BOUT-dev/pull/2684] ([dschwoerer][https://github.com/dschwoerer]) +- Python: If we are on a tag, we should use that as version [\#2683][https://github.com/boutproject/BOUT-dev/pull/2683] ([dschwoerer][https://github.com/dschwoerer]) +- CI: switch to openmpi for fedora GHA [\#2682][https://github.com/boutproject/BOUT-dev/pull/2682] ([dschwoerer][https://github.com/dschwoerer]) +- Fix SUNDIALS `Context` construction for MPICH [\#2678][https://github.com/boutproject/BOUT-dev/pull/2678] ([dschwoerer][https://github.com/dschwoerer]) +- Fix versions after release [\#2669][https://github.com/boutproject/BOUT-dev/pull/2669] ([dschwoerer][https://github.com/dschwoerer]) +- Some fixes for tokamak-2fluid example [\#2668][https://github.com/boutproject/BOUT-dev/pull/2668] ([ZedThree][https://github.com/ZedThree]) +- Fix some warnings and deprecated headers [\#2666][https://github.com/boutproject/BOUT-dev/pull/2666] ([ZedThree][https://github.com/ZedThree]) +- Improve docs + fix boutpp docs (master) [\#2664][https://github.com/boutproject/BOUT-dev/pull/2664] ([dschwoerer][https://github.com/dschwoerer]) +- Fix some warnings [\#2661][https://github.com/boutproject/BOUT-dev/pull/2661] ([dschwoerer][https://github.com/dschwoerer]) +- Error early with in-source-builds [\#2660][https://github.com/boutproject/BOUT-dev/pull/2660] ([dschwoerer][https://github.com/dschwoerer]) +- Squash optional [\#2659][https://github.com/boutproject/BOUT-dev/pull/2659] ([dschwoerer][https://github.com/dschwoerer]) +- Merge v5 into next - resolve conflicts [\#2658][https://github.com/boutproject/BOUT-dev/pull/2658] ([dschwoerer][https://github.com/dschwoerer]) +- Update bundled boututils and boutdata [\#2657][https://github.com/boutproject/BOUT-dev/pull/2657] ([dschwoerer][https://github.com/dschwoerer]) + ## [v5.0.0](https://github.com/boutproject/BOUT-dev/tree/next) [Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v4.3.2...next) diff --git a/CITATION.cff b/CITATION.cff index cdd0f7bf2f..8a5145df85 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -185,11 +185,14 @@ authors: - family-names: James given-names: Toby -version: 5.0.0 -date-released: 2023-02-08 + - family-names: Chapman + given-names: Tom + +version: 5.1.0 +date-released: 2023-04-10 repository-code: https://github.com/boutproject/BOUT-dev url: http://boutproject.github.io/ -doi: 10.5281/zenodo.7603558 +doi: 10.5281/zenodo.8369888 license: 'LGPL-3.0-or-later' references: - type: article diff --git a/CMakeLists.txt b/CMakeLists.txt index 9233b9e0f1..2db9b79528 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,10 +25,10 @@ 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 "v5.0.0") -set(_bout_next_version "5.0.1") +set(_bout_previous_version "5.1.0") +set(_bout_next_version "5.2.0") execute_process( - COMMAND "git" describe --tags --match=${_bout_previous_version} + 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 OUTPUT_VARIABLE BOUT_FULL_VERSION @@ -40,16 +40,19 @@ foreach(error_code ${error_codes}) 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}) +# Get the trailing tag 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++ DESCRIPTION "Fluid PDE solver framework" VERSION ${BOUT_CMAKE_ACCEPTABLE_VERSION} LANGUAGES CXX) -message(STATUS "Configuring BOUT++ version ${BOUT_FULL_VERSION}") - include(CMakeDependentOption) option(BUILD_SHARED_LIBS "Build shared libs" ON) @@ -395,6 +398,21 @@ This warning is only important for BOUT++ developers and can otherwise be \ safely ignored.") endif() +include(GNUInstallDirs) + +# use, i.e. don't skip the full RPATH for the build tree +set(CMAKE_SKIP_BUILD_RPATH FALSE) + +# when building, don't use the install RPATH already +# (but later on when installing) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + +# add the automatically determined parts of the RPATH +# 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:]))" RESULT_VARIABLE PYTHON_WORKING OUTPUT_VARIABLE PYTHON_SITEPATH_SUFFIX @@ -402,8 +420,13 @@ execute_process(COMMAND ${Python3_EXECUTABLE} -c "import site ; print('/'.join(s ) set(CMAKE_INSTALL_PYTHON_SITEARCH lib/${PYTHON_SITEPATH_SUFFIX} CACHE STRING "Location to install python arch-specific modules") -set(BOUT_ENABLE_PYTHON MAYBE CACHE STRING "Build the Python interface") -if (BOUT_ENABLE_PYTHON OR BOUT_ENABLE_PYTHON STREQUAL "MAYBE") +set(ON_OFF_AUTO ON OFF AUTO) +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) + message(FATAL_ERROR "BOUT_ENABLE_PYTHON must be one of ${ON_OFF_AUTO}") +endif() +if (BOUT_ENABLE_PYTHON OR BOUT_ENABLE_PYTHON STREQUAL "AUTO") add_subdirectory(tools/pylib/_boutpp_build) else() set(BOUT_ENABLE_PYTHON OFF) @@ -418,6 +441,7 @@ add_custom_command( MAIN_DEPENDENCY "${CMAKE_CURRENT_LIST_DIR}/cmake/GenerateDateTimeFile.cmake" ) + add_library(bout++ ${BOUT_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/bout++-time.cxx @@ -433,7 +457,7 @@ 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.0.0) + SOVERSION 5.1.0) # Set some variables for the bout-config script set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} -L\$BOUT_LIB_PATH -lbout++") @@ -679,9 +703,6 @@ endif() ################################################## # L10N: localisation - include translations - -include(GNUInstallDirs) - find_package(Gettext) if (GETTEXT_FOUND) @@ -717,7 +738,7 @@ endif() add_custom_target(dist - COMMAND ${CMAKE_SOURCE_DIR}/bin/bout-archive-helper.sh v${BOUT_FULL_VERSION} + 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} @@ -753,8 +774,32 @@ else() set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS}") endif() +set(ISINSTALLED "FALSE") + +set(_CONFIG_LDFLAGS) +string(REPLACE " " ";" CONFIG_LDFLAGS_LIST ${CONFIG_LDFLAGS}) +foreach (flag ${CONFIG_LDFLAGS_LIST}) + string(REGEX MATCH "^-.*$" isopt "${flag}") + if (isopt) + # message("${flag} is an option") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} ${flag}") + # All good + else() + if(EXISTS ${flag}) + # message("${flag} is a file") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} ${flag}") + else() + message("Fixing ${flag} to -l${flag}") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag}") + endif() + endif() +endforeach() +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(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 @@ -762,6 +807,7 @@ configure_file(bin/bout-config.in bin/bout-config @ONLY) 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}") @@ -773,8 +819,13 @@ 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}") +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(bout++Config.cmake.in bout++Config.cmake-install @ONLY) ################################################## # Installation @@ -811,6 +862,12 @@ install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/bin/bout-config-install" 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 @@ -824,14 +881,9 @@ install(EXPORT bout++Targets DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bout++" ) -configure_package_config_file(bout++Config.cmake.in bout++Config.cmake - INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake" - ) - # CMake configuration files install( FILES - "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/bout++ConfigVersion.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/BOUT++functions.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CorrectWindowsPaths.cmake" @@ -850,14 +902,11 @@ install( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ResolveCompilerPaths.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bout++" ) - -configure_package_config_file(tools/pylib/boutconfig/__init__.py.cin tools/pylib/boutconfig/__init__.py - INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib/boutconfig/__init__.py" - ) - install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib/boutconfig/__init__.py" - DESTINATION "${CMAKE_INSTALL_PYTHON_SITEARCH}/boutconfig" + FILES + "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake-install" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/bout++" + RENAME "bout++Config.cmake" ) export(EXPORT bout++Targets @@ -897,7 +946,7 @@ message(" RAJA enabled : ${BOUT_HAS_RAJA} Umpire enabled : ${BOUT_HAS_UMPIRE} Caliper enabled : ${BOUT_HAS_CALIPER} - CUDA enabled : ${BOUT_USE_CUDA} + CUDA enabled : ${BOUT_HAS_CUDA} Metric type : ${BOUT_METRIC_TYPE} Python API support : ${BOUT_USE_PYTHON} Sanitizers enabled : ${BOUT_USE_SANITIZERS} diff --git a/README.md b/README.md index 35e5fba02c..569f921c1d 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.1423213.svg)](https://doi.org/10.5281/zenodo.1423213) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8369888.svg)](https://doi.org/10.5281/zenodo.8369888) ``` .______ ______ __ __ .___________. diff --git a/autoconf_build_defines.hxx.in b/autoconf_build_defines.hxx.in index 5f8929b213..a1f23082a1 100644 --- a/autoconf_build_defines.hxx.in +++ b/autoconf_build_defines.hxx.in @@ -76,7 +76,7 @@ #undef BOUT_USE_COLOR /* Enable CUDA */ -#undef BOUT_USE_CUDA +#undef BOUT_HAS_CUDA /* Is the metric field 3D */ #undef BOUT_USE_METRIC_3D diff --git a/bout++Config.cmake.in b/bout++Config.cmake.in index 4f2981bd07..e33e950e6f 100644 --- a/bout++Config.cmake.in +++ b/bout++Config.cmake.in @@ -8,7 +8,7 @@ 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_USE_CUDA @BOUT_USE_CUDA@) +set(BOUT_HAS_CUDA @BOUT_HAS_CUDA@) set(BOUT_HAS_OUTPUT_DEBUG @BOUT_HAS_OUTPUT_DEBUG@) set(BOUT_CHECK_LEVEL @BOUT_CHECK_LEVEL@) set(BOUT_USE_METRIC_3D @BOUT_USE_METRIC_3D@) @@ -30,21 +30,28 @@ set(BOUT_HAS_RAJA @BOUT_HAS_RAJA@) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") -# Enables the use of the build directory directly, without having to -# specify the paths for the external packages as well -if(EXISTS "@CMAKE_BINARY_DIR@/externalpackages/fmt") - list(APPEND CMAKE_PREFIX_PATH "@CMAKE_BINARY_DIR@/externalpackages/fmt") -endif() -if(EXISTS "@CMAKE_BINARY_DIR@/externalpackages/mpark.variant") - list(APPEND CMAKE_PREFIX_PATH "@CMAKE_BINARY_DIR@/externalpackages/mpark.variant") -endif() -if(EXISTS "@CMAKE_BINARY_DIR@/externalpackages/PVODE") - list(APPEND CMAKE_PREFIX_PATH "@CMAKE_BINARY_DIR@/externalpackages/PVODE") -endif() +if(NOT "@ISINSTALLED@") + # Enables the use of the build directory directly, without having to + # specify the paths for the external packages as well + if(EXISTS "@CMAKE_BINARY_DIR@/externalpackages/fmt") + list(APPEND CMAKE_PREFIX_PATH "@CMAKE_BINARY_DIR@/externalpackages/fmt") + endif() + if(EXISTS "@CMAKE_BINARY_DIR@/externalpackages/mpark.variant") + list(APPEND CMAKE_PREFIX_PATH "@CMAKE_BINARY_DIR@/externalpackages/mpark.variant") + endif() + if(EXISTS "@CMAKE_BINARY_DIR@/externalpackages/PVODE") + list(APPEND CMAKE_PREFIX_PATH "@CMAKE_BINARY_DIR@/externalpackages/PVODE") + endif() -# If using the build directory directly, we need the CMake modules too -if(EXISTS "@PROJECT_SOURCE_DIR@/cmake") - list(APPEND CMAKE_MODULE_PATH "@PROJECT_SOURCE_DIR@/cmake") + # If using the build directory directly, we need the CMake modules too + if(EXISTS "@PROJECT_SOURCE_DIR@/cmake") + list(APPEND CMAKE_MODULE_PATH "@PROJECT_SOURCE_DIR@/cmake") + endif() +else() + if(EXISTS "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/cmake/") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/cmake/ ") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + endif() endif() include(BOUT++functions) diff --git a/cmake/FindNumpy.cmake b/cmake/FindNumpy.cmake index 5ab59c948f..201bc19221 100644 --- a/cmake/FindNumpy.cmake +++ b/cmake/FindNumpy.cmake @@ -7,12 +7,18 @@ # # :: # -# Numpy_FOUND - true if FFTW was found -# Numpy_VERSION - Location of the FFTW includes -# Numpy_INCLUDE_DIR - Required libraries +# Numpy_FOUND +# Numpy_VERSION +# Numpy_INCLUDE_DIR -find_package(Python 3.6 REQUIRED COMPONENTS Interpreter Development) +find_package(Python 3.6 COMPONENTS Interpreter Development) + +if (NOT Python_FOUND) + message(STATUS "Could not find numpy as python was not found. Maybe the developement package is missing?") + set(Numpy_FOUND ${Python_FOUND}) + return() +endif() if (NOT Numpy_FOUND) execute_process(COMMAND ${Python_EXECUTABLE} -c "import numpy ; print(numpy.__version__)" diff --git a/cmake/FindPETSc.cmake b/cmake/FindPETSc.cmake index 6f2e895b1e..c93d464673 100644 --- a/cmake/FindPETSc.cmake +++ b/cmake/FindPETSc.cmake @@ -55,6 +55,12 @@ else() endforeach() endif() +if(NOT PETSC_DIR) + if(EXISTS "${BOUT_USE_PETSC}") + set(PETSC_DIR "${BOUT_USE_PETSC}") + 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) ") diff --git a/cmake/FindSUNDIALS.cmake b/cmake/FindSUNDIALS.cmake index c67e2be100..1ecb5db429 100644 --- a/cmake/FindSUNDIALS.cmake +++ b/cmake/FindSUNDIALS.cmake @@ -32,8 +32,13 @@ include(FindPackageHandleStandardArgs) find_package(SUNDIALS CONFIG QUIET) + if (SUNDIALS_FOUND) - return() + if (TARGET SUNDIALS::nvecparallel) + return() + else() + message(STATUS "SUNDIALS found but not SUNDIALS::nvecparallel") + endif() endif() find_path(SUNDIALS_INCLUDE_DIR diff --git a/cmake/FindnetCDF.cmake b/cmake/FindnetCDF.cmake index 824fb4a3c2..393c57549b 100644 --- a/cmake/FindnetCDF.cmake +++ b/cmake/FindnetCDF.cmake @@ -28,6 +28,10 @@ include(BOUT++functions) include(CMakePrintHelpers) +if (NOT netCDF_ROOT AND EXISTS "${BOUT_USE_NETCDF}") + set(netCDF_ROOT "${BOUT_USE_NETCDF}") +endif() + find_package(netCDF QUIET CONFIG) if (netCDF_FOUND) diff --git a/cmake/FindnetCDFCxx.cmake b/cmake/FindnetCDFCxx.cmake index 14e086623a..d4155dc760 100644 --- a/cmake/FindnetCDFCxx.cmake +++ b/cmake/FindnetCDFCxx.cmake @@ -27,6 +27,10 @@ include(BOUT++functions) +if (NOT netCDFCxx_ROOT AND EXISTS "${BOUT_USE_NETCDF}") + set(netCDFCxx_ROOT "${BOUT_USE_NETCDF}") +endif() + if (NOT EXISTS ${NCXX4_CONFIG}) # Only search if NCXX4_CONFIG was not set explicitly find_package(netCDFCxx QUIET CONFIG) diff --git a/cmake/Sanitizers.cmake b/cmake/Sanitizers.cmake index a94be2cddd..715a08ab88 100644 --- a/cmake/Sanitizers.cmake +++ b/cmake/Sanitizers.cmake @@ -10,24 +10,22 @@ function(enable_sanitizers target_name) if(ENABLE_COVERAGE) target_compile_options(${target_name} PUBLIC --coverage -O0 -g) - target_link_libraries(${target_name} PUBLIC --coverage) + target_link_libraries(${target_name} PUBLIC --coverage -lgcov) - find_program(fastcov_FOUND fastcov) - message(STATUS "Looking for fastcov: ${fastcov_FOUND}") + find_program(lcov_FOUND lcov) + message(STATUS "Looking for lcov: ${lcov_FOUND}") find_program(genhtml_FOUND genhtml) - message(STATUS "Looking for genhtml: ${fastcov_FOUND}") + message(STATUS "Looking for genhtml: ${genhtml_FOUND}") - if (fastcov_FOUND AND genhtml_FOUND) + 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") add_custom_target(code-coverage-capture COMMAND - fastcov --include "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/include" - --exclude "${CMAKE_CURRENT_SOURCE_DIR}/externalpackages" - --lcov --process-gcno - --output "${COVERAGE_FILE}" + 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 @@ -41,11 +39,11 @@ function(enable_sanitizers target_name) add_custom_target(code-coverage-clean COMMAND - fastcov --zerocounters + lcov --zerocounters COMMENT "Cleaning coverage information" ) else() - message(STATUS "Coverage enabled, but coverage-capture not available. Please install fastcov and lcov") + message(FATAL_ERROR "Coverage enabled, but coverage-capture not available. Please install lcov") endif() endif() diff --git a/cmake/SetupBOUTThirdParty.cmake b/cmake/SetupBOUTThirdParty.cmake index 25ce8f5581..78dfc6b56e 100644 --- a/cmake/SetupBOUTThirdParty.cmake +++ b/cmake/SetupBOUTThirdParty.cmake @@ -11,9 +11,9 @@ if (BOUT_USE_OPENMP) endif() # determined in SetupCompilers.cmake -if (BOUT_USE_CUDA) +if (BOUT_HAS_CUDA) enable_language(CUDA) - message(STATUS "BOUT_USE_CUDA ${CMAKE_CUDA_COMPILER}") + message(STATUS "BOUT_HAS_CUDA ${CMAKE_CUDA_COMPILER}") # Get all the .cxx files from BOUT_SOURCES set(BOUT_SOURCES_CXX ${BOUT_SOURCES}) @@ -65,7 +65,7 @@ if (BOUT_USE_HYPRE) enable_language(C) find_package(HYPRE REQUIRED) target_link_libraries(bout++ PUBLIC HYPRE::HYPRE) - if (HYPRE_WITH_CUDA AND BOUT_USE_CUDA) + 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 () @@ -81,7 +81,7 @@ if (BOUT_USE_PETSC) find_package(PETSc REQUIRED) target_link_libraries(bout++ PUBLIC PETSc::PETSc) string(JOIN " " CONFIG_PETSC_LIBRARIES ${PETSC_LIBRARIES}) - set(CONFIG_LDFLAGS "${CONFIG_PETSC_LIBRARIES} ${CONFIG_LDFLAGS}") + set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${CONFIG_PETSC_LIBRARIES}") foreach(PETSC_INCLUDE ${PETSC_INCLUDES}) set(CONFIG_CFLAGS "${CONFIG_CFLAGS} -I${PETSC_INCLUDE}") endforeach() @@ -194,18 +194,29 @@ endif() message(STATUS "FFTW support: ${BOUT_USE_FFTW}") set(BOUT_HAS_FFTW ${BOUT_USE_FFTW}) -option(BOUT_USE_LAPACK "Enable support for LAPACK" ON) +set(ON_OFF_AUTO ON OFF AUTO) +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") # Cray wrappers sort this out for us - find_package(LAPACK REQUIRED) - target_link_libraries(bout++ PUBLIC "${LAPACK_LIBRARIES}") - string(JOIN " " CONFIG_LAPACK_LIBRARIES ${LAPACK_LIBRARIES}) - set(CONFIG_LDFLAGS "${CONFIG_LDFLAGS} ${CONFIG_LAPACK_LIBRARIES}") + if (BOUT_USE_LAPACK STREQUAL ON) + find_package(LAPACK REQUIRED) + else() + find_package(LAPACK) + endif() + 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}") + endif() endif() endif() -message(STATUS "LAPACK support: ${BOUT_USE_LAPACK}") -set(BOUT_HAS_LAPACK ${BOUT_USE_LAPACK}) + +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) diff --git a/cmake/SetupCompilers.cmake b/cmake/SetupCompilers.cmake index 1cd0bc2732..647cb20f75 100644 --- a/cmake/SetupCompilers.cmake +++ b/cmake/SetupCompilers.cmake @@ -41,4 +41,4 @@ if(BOUT_ENABLE_CUDA) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler ${OpenMP_CXX_FLAGS}") endif () endif() -set(BOUT_USE_CUDA ${BOUT_ENABLE_CUDA}) +set(BOUT_HAS_CUDA ${BOUT_ENABLE_CUDA}) diff --git a/cmake_build_defines.hxx.in b/cmake_build_defines.hxx.in index edd7ede233..a637dbc46a 100644 --- a/cmake_build_defines.hxx.in +++ b/cmake_build_defines.hxx.in @@ -30,7 +30,7 @@ #cmakedefine01 BOUT_HAS_UMPIRE #cmakedefine01 BOUT_HAS_CALIPER #cmakedefine01 BOUT_HAS_RAJA -#cmakedefine01 BOUT_USE_CUDA +#cmakedefine01 BOUT_HAS_CUDA #cmakedefine BOUT_METRIC_TYPE @BOUT_METRIC_TYPE@ #cmakedefine01 BOUT_USE_METRIC_3D #cmakedefine01 BOUT_USE_MSGSTACK diff --git a/configure b/configure index df39acf7c0..359fd6d7a9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for BOUT++ 5.0.0. +# Generated by GNU Autoconf 2.69 for BOUT++ 5.1.0. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='BOUT++' PACKAGE_TARNAME='bout--' -PACKAGE_VERSION='5.0.0' -PACKAGE_STRING='BOUT++ 5.0.0' +PACKAGE_VERSION='5.1.0' +PACKAGE_STRING='BOUT++ 5.1.0' PACKAGE_BUGREPORT='bd512@york.ac.uk' PACKAGE_URL='' @@ -680,7 +680,7 @@ CONFIG_CFLAGS BOUT_HAS_CALIPER BOUT_HAS_UMPIRE BOUT_HAS_RAJA -BOUT_USE_CUDA +BOUT_HAS_CUDA LTLIBOBJS POSUB LTLIBINTL @@ -1403,7 +1403,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures BOUT++ 5.0.0 to adapt to many kinds of systems. +\`configure' configures BOUT++ 5.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1468,7 +1468,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of BOUT++ 5.0.0:";; + short | recursive ) echo "Configuration of BOUT++ 5.1.0:";; esac cat <<\_ACEOF @@ -1617,7 +1617,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -BOUT++ configure 5.0.0 +BOUT++ configure 5.1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2024,7 +2024,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by BOUT++ $as_me 5.0.0, which was +It was created by BOUT++ $as_me 5.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -14450,7 +14450,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by BOUT++ $as_me 5.0.0, which was +This file was extended by BOUT++ $as_me 5.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14511,7 +14511,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -BOUT++ config.status 5.0.0 +BOUT++ config.status 5.1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -15264,19 +15264,19 @@ CONFIG_LDFLAGS=`$MAKE ldflags -f output.make` ############################################################# # Defines which are supported by CMake build but not autoconf -BOUT_USE_CUDA="no" +BOUT_HAS_CUDA="no" BOUT_HAS_RAJA="no" BOUT_HAS_UMPIRE="no" BOUT_HAS_CALIPER="no" -if test "x$BOUT_USE_CUDA" = "xyes"; then : +if test "x$BOUT_HAS_CUDA" = "xyes"; then : -$as_echo "#define BOUT_USE_CUDA 1" >>confdefs.h +$as_echo "#define BOUT_HAS_CUDA 1" >>confdefs.h else -$as_echo "#define BOUT_USE_CUDA 0" >>confdefs.h +$as_echo "#define BOUT_HAS_CUDA 0" >>confdefs.h fi @@ -16209,7 +16209,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by BOUT++ $as_me 5.0.0, which was +This file was extended by BOUT++ $as_me 5.1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16279,7 +16279,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -BOUT++ config.status 5.0.0 +BOUT++ config.status 5.1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 66426c2655..0bacd1097a 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ # AC_PREREQ([2.69]) -AC_INIT([BOUT++],[5.0.0],[bd512@york.ac.uk]) +AC_INIT([BOUT++],[5.1.0],[bd512@york.ac.uk]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) @@ -1346,12 +1346,12 @@ CONFIG_LDFLAGS=`$MAKE ldflags -f output.make` ############################################################# # Defines which are supported by CMake build but not autoconf -BOUT_USE_CUDA="no" +BOUT_HAS_CUDA="no" BOUT_HAS_RAJA="no" BOUT_HAS_UMPIRE="no" BOUT_HAS_CALIPER="no" -BOUT_DEFINE_SUBST(BOUT_USE_CUDA, [Enable CUDA]) +BOUT_DEFINE_SUBST(BOUT_HAS_CUDA, [Enable CUDA]) BOUT_DEFINE_SUBST(BOUT_HAS_RAJA, [RAJA support]) BOUT_DEFINE_SUBST(BOUT_HAS_UMPIRE, [Umpire support]) BOUT_DEFINE_SUBST(BOUT_HAS_CALIPER, [Caliper support]) diff --git a/examples/blob2d-outerloop/CMakeLists.txt b/examples/blob2d-outerloop/CMakeLists.txt index e7c77a59f3..cd7187ee3f 100644 --- a/examples/blob2d-outerloop/CMakeLists.txt +++ b/examples/blob2d-outerloop/CMakeLists.txt @@ -8,6 +8,6 @@ endif() bout_add_example(blob2d-outerloop SOURCES blob2d.cxx) -if(BOUT_USE_CUDA) +if(BOUT_HAS_CUDA) set_source_files_properties(blob2d.cxx PROPERTIES LANGUAGE CUDA) endif() diff --git a/examples/elm-pb-outerloop/CMakeLists.txt b/examples/elm-pb-outerloop/CMakeLists.txt index f682aadc5a..008918a87f 100644 --- a/examples/elm-pb-outerloop/CMakeLists.txt +++ b/examples/elm-pb-outerloop/CMakeLists.txt @@ -11,7 +11,7 @@ bout_add_example(elm_pb_outerloop EXTRA_FILES cbm18_dens8.grid_nx68ny64.nc ) -if(BOUT_USE_CUDA) +if(BOUT_HAS_CUDA) set_source_files_properties(elm_pb_outerloop.cxx PROPERTIES LANGUAGE CUDA ) endif() diff --git a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx index 144691be3a..691f4303f4 100644 --- a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx +++ b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx @@ -5,7 +5,7 @@ * Can also include the Vpar compressional term * This version uses indexed operators * which reduce the number of loops over the domain - * GPU processing is enabled if BOUT_ENABLE_CUDA is defined + * GPU processing is enabled if BOUT_HAS_CUDA is defined * GPU version Hypre solver is enable if BOUT_HAS_HYPRE is defined * Profiling markers and ranges are set if USE_NVTX is defined * Based on model code, Yining Qin update GPU RAJA code since 1117-2020 diff --git a/examples/hasegawa-wakatani-3d/CMakeLists.txt b/examples/hasegawa-wakatani-3d/CMakeLists.txt index 89d2d3d052..0cdb5207f8 100644 --- a/examples/hasegawa-wakatani-3d/CMakeLists.txt +++ b/examples/hasegawa-wakatani-3d/CMakeLists.txt @@ -8,6 +8,6 @@ endif() bout_add_example(hw3d SOURCES hw.cxx) -if(BOUT_USE_CUDA) +if(BOUT_HAS_CUDA) set_source_files_properties(hw.cxx PROPERTIES LANGUAGE CUDA) endif() diff --git a/examples/hasegawa-wakatani-3d/hw.cxx b/examples/hasegawa-wakatani-3d/hw.cxx index 7f528cab01..023d50c0d6 100644 --- a/examples/hasegawa-wakatani-3d/hw.cxx +++ b/examples/hasegawa-wakatani-3d/hw.cxx @@ -3,7 +3,7 @@ /// This version uses indexed operators /// which reduce the number of loops over the domain /// -/// GPU processing is enabled if BOUT_ENABLE_CUDA is defined +/// GPU processing is enabled if BOUT_HAS_CUDA is defined /// Profiling markers and ranges are set if USE_NVTX is defined /// Based on Ben Dudson, Steven Glenn code, Yining Qin update 0521-2020 diff --git a/examples/laplacexy/simple-hypre/CMakeLists.txt b/examples/laplacexy/simple-hypre/CMakeLists.txt index 6c37a4a8fa..788ebb1776 100644 --- a/examples/laplacexy/simple-hypre/CMakeLists.txt +++ b/examples/laplacexy/simple-hypre/CMakeLists.txt @@ -10,6 +10,6 @@ bout_add_example(test_laplacexy_hypre SOURCES test-laplacexy-hypre.cxx REQUIRES BOUT_HAS_HYPRE) -if(BOUT_USE_CUDA) +if(BOUT_HAS_CUDA) set_source_files_properties(test-laplacexy-hypre.cxx PROPERTIES LANGUAGE CUDA ) endif() diff --git a/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx b/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx index e38a285cfc..af2367e1a0 100644 --- a/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx +++ b/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx @@ -23,7 +23,7 @@ int main(int argc, char** argv) { bout::writeDefaultOutputFile(dump); } BoutFinalise(); -#if BOUT_USE_CUDA +#if BOUT_HAS_CUDA cudaDeviceReset(); #endif return 0; diff --git a/externalpackages/PVODE/source/cvode.cpp b/externalpackages/PVODE/source/cvode.cpp index 48ac3209f2..135662a40f 100644 --- a/externalpackages/PVODE/source/cvode.cpp +++ b/externalpackages/PVODE/source/cvode.cpp @@ -179,7 +179,7 @@ namespace pvode { #define MSG_Y0_NULL CVM "y0=NULL illegal.\n\n" -#define MSG_BAD_N CVM "N=%d < 1 illegal.\n\n" +#define MSG_BAD_N CVM "N=%d < 1 illegal.\n\n" #define MSG_BAD_LMM_1 CVM "lmm=%d illegal.\n" #define MSG_BAD_LMM_2 "The legal values are ADAMS=%d and BDF=%d.\n\n" diff --git a/include/bout/array.hxx b/include/bout/array.hxx index 68607e6b58..060b4900a1 100644 --- a/include/bout/array.hxx +++ b/include/bout/array.hxx @@ -65,7 +65,7 @@ struct ArrayData { // even though the Array object itself can't. #if BOUT_HAS_UMPIRE auto& rm = umpire::ResourceManager::getInstance(); -#if BOUT_USE_CUDA +#if BOUT_HAS_CUDA auto allocator = rm.getAllocator(umpire::resource::Pinned); #else auto allocator = rm.getAllocator("HOST"); diff --git a/include/bout/build_config.hxx b/include/bout/build_config.hxx index 1e6087395b..a98c615c77 100644 --- a/include/bout/build_config.hxx +++ b/include/bout/build_config.hxx @@ -36,7 +36,7 @@ constexpr auto use_output_debug = static_cast(BOUT_USE_OUTPUT_DEBUG); constexpr auto use_sigfpe = static_cast(BOUT_USE_SIGFPE); constexpr auto use_signal = static_cast(BOUT_USE_SIGNAL); constexpr auto use_track = static_cast(BOUT_USE_TRACK); -constexpr auto use_cuda = static_cast(BOUT_USE_CUDA); +constexpr auto has_cuda = static_cast(BOUT_HAS_CUDA); constexpr auto use_metric_3d = static_cast(BOUT_USE_METRIC_3D); constexpr auto use_msgstack = static_cast(BOUT_USE_MSGSTACK); @@ -46,7 +46,7 @@ constexpr auto use_msgstack = static_cast(BOUT_USE_MSGSTACK); #undef STRINGIFY1 #undef STRINGIFY -#if BOUT_USE_CUDA && defined(__CUDACC__) +#if BOUT_HAS_CUDA && defined(__CUDACC__) #define BOUT_HOST_DEVICE __host__ __device__ #define BOUT_HOST __host__ #define BOUT_DEVICE __device__ diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index f52c689e8b..42efcad84c 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -149,7 +149,7 @@ public: FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& region = "RGN_NOBNDRY") const; FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -161,7 +161,7 @@ public: Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& region = "RGN_NOBNDRY") const; Field3D DDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -232,9 +232,22 @@ private: /// `Coordinates::geometry` 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}; + /// 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(); }; /* diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 80f3dc37c9..be347f60d0 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -367,7 +367,7 @@ inline bool isUniform(const T& f, bool allpe = false, /// @param[in] allpe Check over all processors /// @param[in] region The region to assume is uniform template > -inline BoutReal getUniform(const T& f, bool allpe = false, +inline BoutReal getUniform(const T& f, MAYBE_UNUSED(bool allpe) = false, const std::string& region = "RGN_ALL") { #if CHECK > 1 if (not isUniform(f, allpe, region)) { diff --git a/include/bout/field2d.hxx b/include/bout/field2d.hxx index 783eb79e9e..1c1169a175 100644 --- a/include/bout/field2d.hxx +++ b/include/bout/field2d.hxx @@ -199,7 +199,7 @@ public: * significantly reduce performance. */ BOUT_HOST_DEVICE inline BoutReal& operator()(int jx, int jy) { -#if CHECK > 2 && !BOUT_USE_CUDA +#if CHECK > 2 && !BOUT_HAS_CUDA if (!isAllocated()) { throw BoutException("Field2D: () operator on empty data"); } @@ -213,7 +213,7 @@ public: return data[jx * ny + jy]; } BOUT_HOST_DEVICE inline const BoutReal& operator()(int jx, int jy) const { -#if CHECK > 2 && !BOUT_USE_CUDA +#if CHECK > 2 && !BOUT_HAS_CUDA if (!isAllocated()) { throw BoutException("Field2D: () operator on empty data"); } diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index d0341c95d4..8213742248 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -479,13 +479,11 @@ public: /// Note: does not just copy values in boundary region. void setBoundaryTo(const Field3D& f3d); - void applyParallelBoundary(); - void applyParallelBoundary(BoutReal t); - void applyParallelBoundary(const std::string& condition); - void applyParallelBoundary(const char* condition) { - applyParallelBoundary(std::string(condition)); - } - void applyParallelBoundary(const std::string& region, const std::string& condition); + void applyParallelBoundary() override; + void applyParallelBoundary(BoutReal t) override; + void applyParallelBoundary(const std::string& condition) override; + void applyParallelBoundary(const std::string& region, + const std::string& condition) override; void applyParallelBoundary(const std::string& region, const std::string& condition, Field3D* f); diff --git a/include/bout/field_data.hxx b/include/bout/field_data.hxx index 57921a0f0b..59bd751fc4 100644 --- a/include/bout/field_data.hxx +++ b/include/bout/field_data.hxx @@ -88,7 +88,13 @@ public: virtual void applyBoundary(bool UNUSED(init) = false) {} virtual void applyTDerivBoundary(){}; - //JMAD + + 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)){}; + // JMAD void addBndryFunction(FuncPtr userfunc, BndryLoc location); void addBndryGenerator(FieldGeneratorPtr gen, BndryLoc location); diff --git a/include/bout/hypre_interface.hxx b/include/bout/hypre_interface.hxx index 7f6271865a..2bbdfdae63 100644 --- a/include/bout/hypre_interface.hxx +++ b/include/bout/hypre_interface.hxx @@ -26,7 +26,7 @@ BOUT_ENUM_CLASS(HYPRE_SOLVER_TYPE, gmres, bicgstab, pcg); namespace bout { -#if BOUT_USE_CUDA && defined(__CUDACC__) // HYPRE with Cuda enabled +#if BOUT_HAS_CUDA && defined(__CUDACC__) // HYPRE with Cuda enabled #define HypreMalloc(P, SIZE) cudaMallocManaged(&P, SIZE) #define HypreFree(P) cudaFree(P) #else @@ -870,7 +870,7 @@ public: HYPRE_BoomerAMGCreate(&precon); HYPRE_BoomerAMGSetOldDefault(precon); -#if BOUT_USE_CUDA +#if BOUT_HAS_CUDA // 18 or 7 for GPU implementation, 7 is slower to converge HYPRE_BoomerAMGSetRelaxType(precon, 18); HYPRE_BoomerAMGSetRelaxOrder(precon, false); // must be false for GPU diff --git a/include/bout/invertable_operator.hxx b/include/bout/invertable_operator.hxx index 49b254187a..7168324b75 100644 --- a/include/bout/invertable_operator.hxx +++ b/include/bout/invertable_operator.hxx @@ -430,7 +430,8 @@ public: KSPConvergedReason reason; ierr = KSPGetConvergedReason(ksp, &reason); if (reason <= 0) { - throw BoutException("KSPSolve failed with reason {:d}.", reason); + throw BoutException("KSPSolve failed. Reason {} ({:d})", + KSPConvergedReasons[reason], static_cast(reason)); } // Probably want to remove the following in the long run diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index 2f6d343bd0..bb00dcbd45 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -60,7 +60,7 @@ public: return f; } - virtual bool canToFromFieldAligned() = 0; + virtual bool canToFromFieldAligned() const = 0; struct PositionsAndWeights { int i, j, k; @@ -157,7 +157,7 @@ public: return {{i, j + yoffset, k, 1.0}}; } - bool canToFromFieldAligned() override { return true; } + bool canToFromFieldAligned() const override { return true; } bool requiresTwistShift(bool twist_shift_enabled, YDirectionType UNUSED(ytype)) override { @@ -219,7 +219,7 @@ public: "for `type = shifted`. Try `type = shiftedinterp`"); } - bool canToFromFieldAligned() override { return true; } + bool canToFromFieldAligned() const override { return true; } /// Save zShift to the output void outputVars(Options& output_options) override; diff --git a/include/bout/petsclib.hxx b/include/bout/petsclib.hxx index e731405e1c..dd3daa28aa 100644 --- a/include/bout/petsclib.hxx +++ b/include/bout/petsclib.hxx @@ -64,6 +64,10 @@ class Options; #include #include +#include "bout/boutexception.hxx" + +#define BOUT_DO_PETSC(cmd) PetscLib::assertIerr(cmd, #cmd) + /*! * Handles initialisation and finalisation of PETSc library. * The first instance which is created initialises PETSc @@ -111,6 +115,14 @@ public: */ static void cleanup(); + static inline void assertIerr(PetscErrorCode ierr, std::string op = "PETSc operation") { + if (ierr) { + throw BoutException("{:s} failed with {:d}", op, ierr); + } + } + + static BoutException SNESFailure(SNES& snes); + private: static int count; ///< How many instances? static char help[]; ///< Help string diff --git a/include/bout/single_index_ops.hxx b/include/bout/single_index_ops.hxx index 23542ce1f4..6a9089510b 100644 --- a/include/bout/single_index_ops.hxx +++ b/include/bout/single_index_ops.hxx @@ -9,12 +9,12 @@ #if BOUT_HAS_RAJA //-- RAJA CUDA settings--------------------------------------------------------start -#if BOUT_USE_CUDA +#if BOUT_HAS_CUDA const int CUDA_BLOCK_SIZE = 256; // TODO: Make configurable using EXEC_POL = RAJA::cuda_exec; -#else // BOUT_ENABLE_CUDA not defined +#else // not BOUT_USE_CUDA using EXEC_POL = RAJA::loop_exec; -#endif // defined(BOUT_ENABLE_CUDA) +#endif // end BOUT_USE_CUDA ////-----------CUDA settings------------------------------------------------------end #endif diff --git a/include/bout/vectormetric.hxx b/include/bout/vectormetric.hxx new file mode 100644 index 0000000000..3ac31c2a45 --- /dev/null +++ b/include/bout/vectormetric.hxx @@ -0,0 +1,11 @@ +#pragma once + +#include "bout/build_config.hxx" + +#if BOUT_USE_METRIC_3D +#include "bout/vector3d.hxx" +using VectorMetric = Vector3D; +#else +#include "bout/vector2d.hxx" +using VectorMetric = Vector2D; +#endif diff --git a/locale/de/libbout.po b/locale/de/libbout.po index 2193e0575b..987fa61572 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: 2023-02-03 16:41+0000\n" +"POT-Creation-Date: 2023-09-22 11:03+0100\n" "PO-Revision-Date: 2019-02-06 17:32+0000\n" "Last-Translator: David \n" "Language-Team: German\n" @@ -463,7 +463,7 @@ msgstr "" "{:d} Punkte in der X-Richtung können nicht gleichmässig zwischen {:d} " "Prozessen verteilt werden\n" -#: ../src/bout++.cxx:808 +#: ../src/bout++.cxx:817 msgid "Check if a file exists, and exit if it does." msgstr "" @@ -527,7 +527,7 @@ msgstr "" "Der Befehl 'bout-log-color' konnte nicht ausgeführt werden. Stellen Sie " "sicher, dass er sich in $PATH befindet.\n" -#: ../src/solver/solver.cxx:757 +#: ../src/solver/solver.cxx:765 #, fuzzy msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" @@ -584,7 +584,7 @@ msgstr "FEHLER: Der Integrator ist bereits initialisiert.\n" msgid "Error encountered during initialisation: {:s}\n" msgstr "Es wurde ein Fehler während der Initialisierung gefunden: {:s}\n" -#: ../src/bout++.cxx:734 +#: ../src/bout++.cxx:743 msgid "Error whilst writing settings" msgstr "Es wurde ein Fehler beim Schreiben der Einstellungsdatei gefunden" @@ -639,17 +639,17 @@ msgstr "Das Gitter muss ny enthalten" msgid "Missing integer array {:s}\n" msgstr "Ganzzahlen-Array '{:s}' nicht gesetzt\n" -#: ../src/solver/solver.cxx:897 +#: ../src/solver/solver.cxx:905 #, fuzzy msgid "Monitor signalled to quit (exception {})\n" msgstr "Beendigung durch Monitor\n" -#: ../src/solver/solver.cxx:875 +#: ../src/solver/solver.cxx:883 #, fuzzy msgid "Monitor signalled to quit (return code {})" msgstr "Der Monitor signaliserte die Beendigung" -#: ../src/bout++.cxx:813 +#: ../src/bout++.cxx:822 msgid "Name of file whose existence triggers a stop" msgstr "" @@ -679,7 +679,7 @@ msgstr "" "d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:886 +#: ../src/bout++.cxx:895 #, fuzzy msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "Nur noch {:e} Sekunden verfügbar. Abbruch\n" @@ -758,7 +758,7 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:855 +#: ../src/bout++.cxx:864 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" @@ -767,7 +767,7 @@ msgstr "" "Integrator\n" "\n" -#: ../src/bout++.cxx:858 +#: ../src/bout++.cxx:867 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -788,7 +788,7 @@ msgstr "" msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "Integriere {:d} Zeitschritte von je {:e}\n" -#: ../src/solver/solver.cxx:773 +#: ../src/solver/solver.cxx:781 #, fuzzy msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " @@ -797,7 +797,7 @@ msgstr "" "Der Integrator kann den Zeitschritt nicht von {:g} auf {:g} reduzieren, " "nachdem er initialisiert wurde!" -#: ../src/solver/solver.cxx:1273 +#: ../src/solver/solver.cxx:1281 #, fuzzy msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " @@ -806,7 +806,7 @@ 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" -#: ../src/solver/solver.cxx:1472 +#: ../src/solver/solver.cxx:1480 #, fuzzy msgid "Time derivative for variable '{:s}' not set" msgstr "Zeitliche Ableitung für Variable '{:s}' nicht gesetzt" @@ -834,7 +834,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1546 +#: ../src/mesh/coordinates.cxx:1462 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -887,7 +887,7 @@ msgstr "" "[VAR=WERT]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:913 +#: ../src/solver/solver.cxx:921 #, fuzzy msgid "User signalled to quit. Returning\n" msgstr "Beendigung durch Monitor\n" @@ -941,7 +941,7 @@ msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" msgid "Value for option {:s} is not an integer" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/solver/solver.cxx:1224 ../src/solver/solver.cxx:1230 +#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 #, fuzzy msgid "Variable '{:s}' not initialised" msgstr "Variable '{:s}' ist nicht initialisiert" @@ -955,7 +955,7 @@ msgstr "" "WARNUNG: Anzahl der toroidalen Punkte sollte 2^n für effiziente FFTs sein. " "Ändere MZ falls FFTs verwendet werden\n" -#: ../src/mesh/coordinates.cxx:655 +#: ../src/mesh/coordinates.cxx:633 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" @@ -965,7 +965,7 @@ msgid "" "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:660 +#: ../src/mesh/coordinates.cxx:638 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" @@ -975,7 +975,7 @@ msgid "" "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:804 +#: ../src/bout++.cxx:813 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" diff --git a/locale/es/libbout.po b/locale/es/libbout.po index 51ffe3b998..a51e465437 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: 2023-02-03 16:41+0000\n" +"POT-Creation-Date: 2023-09-22 11:03+0100\n" "PO-Revision-Date: 2019-02-11 12:46+0900\n" "Last-Translator: Marta \n" "Language-Team: Spanish\n" @@ -458,7 +458,7 @@ msgstr "Regiones frontera en este procesador: " 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" -#: ../src/bout++.cxx:808 +#: ../src/bout++.cxx:817 msgid "Check if a file exists, and exit if it does." msgstr "" @@ -522,7 +522,7 @@ msgstr "" "No se pudo ejecutar bout-log-color. Asegúrese de que se encuentre en su " "PATH\n" -#: ../src/solver/solver.cxx:757 +#: ../src/solver/solver.cxx:765 #, fuzzy 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}!" @@ -575,7 +575,7 @@ msgstr "ERROR: el Solver ya se encuentra inicializado\n" msgid "Error encountered during initialisation: {:s}\n" msgstr "Error encontrado durante la inicialización:{:s}\n" -#: ../src/bout++.cxx:734 +#: ../src/bout++.cxx:743 msgid "Error whilst writing settings" msgstr "Error durante el paso de opciones" @@ -628,17 +628,17 @@ msgstr "La malla `mesh` debe contener ny" msgid "Missing integer array {:s}\n" msgstr "Fala la matriz entera {:s}\n" -#: ../src/solver/solver.cxx:897 +#: ../src/solver/solver.cxx:905 #, fuzzy msgid "Monitor signalled to quit (exception {})\n" msgstr "Monitor indicó salir\n" -#: ../src/solver/solver.cxx:875 +#: ../src/solver/solver.cxx:883 #, fuzzy msgid "Monitor signalled to quit (return code {})" msgstr "Monitor indicó salir" -#: ../src/bout++.cxx:813 +#: ../src/bout++.cxx:822 msgid "Name of file whose existence triggers a stop" msgstr "" @@ -668,7 +668,7 @@ msgstr "" "d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:886 +#: ../src/bout++.cxx:895 #, fuzzy msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "Solo faltan {:e} segundos. Saliendo\n" @@ -747,7 +747,7 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:855 +#: ../src/bout++.cxx:864 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" @@ -756,7 +756,7 @@ msgstr "" "SOLVER\n" "\n" -#: ../src/bout++.cxx:858 +#: ../src/bout++.cxx:867 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -780,7 +780,7 @@ msgstr "" "Solver corriendo para {:d} outputs con intervalos de tiempo de output de {:" "e}\n" -#: ../src/solver/solver.cxx:773 +#: ../src/solver/solver.cxx:781 #, fuzzy msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " @@ -789,7 +789,7 @@ 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:1273 +#: ../src/solver/solver.cxx:1281 #, fuzzy msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " @@ -798,7 +798,7 @@ 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" -#: ../src/solver/solver.cxx:1472 +#: ../src/solver/solver.cxx:1480 #, fuzzy msgid "Time derivative for variable '{:s}' not set" msgstr "Derivada del tiempo para la variable '{:s}' no fijada" @@ -826,7 +826,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1546 +#: ../src/mesh/coordinates.cxx:1462 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -879,7 +879,7 @@ msgstr "" "[VAR=VALUE]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:913 +#: ../src/solver/solver.cxx:921 #, fuzzy msgid "User signalled to quit. Returning\n" msgstr "Monitor indicó salir\n" @@ -933,7 +933,7 @@ msgstr "Valor para la opción {:s} = {:e} no es un entero" msgid "Value for option {:s} is not an integer" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/solver/solver.cxx:1224 ../src/solver/solver.cxx:1230 +#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 #, fuzzy msgid "Variable '{:s}' not initialised" msgstr "Variable '{:s}' sin inicializar" @@ -947,7 +947,7 @@ 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" -#: ../src/mesh/coordinates.cxx:655 +#: ../src/mesh/coordinates.cxx:633 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" @@ -957,7 +957,7 @@ msgid "" "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:660 +#: ../src/mesh/coordinates.cxx:638 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" @@ -967,7 +967,7 @@ msgid "" "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:804 +#: ../src/bout++.cxx:813 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" diff --git a/locale/fr/libbout.po b/locale/fr/libbout.po index bb11ad94a1..dd1853bb3c 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: 2023-02-03 16:41+0000\n" +"POT-Creation-Date: 2023-09-22 11:03+0100\n" "PO-Revision-Date: 2018-10-21 22:46+0100\n" "Last-Translator: \n" "Language-Team: French\n" @@ -399,7 +399,7 @@ msgstr "" msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:808 +#: ../src/bout++.cxx:817 msgid "Check if a file exists, and exit if it does." msgstr "" @@ -455,7 +455,7 @@ msgstr "" msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:757 +#: ../src/solver/solver.cxx:765 msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" @@ -504,7 +504,7 @@ msgstr "" msgid "Error encountered during initialisation: {:s}\n" msgstr "Erreur rencontrée lors de l'initialisation : {:s}\n" -#: ../src/bout++.cxx:734 +#: ../src/bout++.cxx:743 msgid "Error whilst writing settings" msgstr "" @@ -551,15 +551,15 @@ msgstr "" msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:897 +#: ../src/solver/solver.cxx:905 msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:875 +#: ../src/solver/solver.cxx:883 msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:813 +#: ../src/bout++.cxx:822 msgid "Name of file whose existence triggers a stop" msgstr "" @@ -582,7 +582,7 @@ msgid "" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:886 +#: ../src/bout++.cxx:895 msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" @@ -647,13 +647,13 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:855 +#: ../src/bout++.cxx:864 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:858 +#: ../src/bout++.cxx:867 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -672,19 +672,19 @@ 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" -#: ../src/solver/solver.cxx:773 +#: ../src/solver/solver.cxx:781 msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1273 +#: ../src/solver/solver.cxx:1281 msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1472 +#: ../src/solver/solver.cxx:1480 msgid "Time derivative for variable '{:s}' not set" msgstr "" @@ -708,7 +708,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1546 +#: ../src/mesh/coordinates.cxx:1462 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -751,7 +751,7 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:913 +#: ../src/solver/solver.cxx:921 msgid "User signalled to quit. Returning\n" msgstr "" @@ -796,7 +796,7 @@ msgstr "" msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1224 ../src/solver/solver.cxx:1230 +#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 msgid "Variable '{:s}' not initialised" msgstr "" @@ -806,7 +806,7 @@ msgid "" "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:655 +#: ../src/mesh/coordinates.cxx:633 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" @@ -816,7 +816,7 @@ msgid "" "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:660 +#: ../src/mesh/coordinates.cxx:638 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" @@ -826,7 +826,7 @@ msgid "" "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:804 +#: ../src/bout++.cxx:813 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" diff --git a/locale/libbout.pot b/locale/libbout.pot index 86bd7942db..3ece452da2 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: 2023-02-03 16:41+0000\n" +"POT-Creation-Date: 2023-09-22 11:03+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -392,7 +392,7 @@ msgstr "" msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:808 +#: ../src/bout++.cxx:817 msgid "Check if a file exists, and exit if it does." msgstr "" @@ -445,7 +445,7 @@ msgstr "" msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:757 +#: ../src/solver/solver.cxx:765 msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" @@ -490,7 +490,7 @@ msgstr "" msgid "Error encountered during initialisation: {:s}\n" msgstr "" -#: ../src/bout++.cxx:734 +#: ../src/bout++.cxx:743 msgid "Error whilst writing settings" msgstr "" @@ -537,15 +537,15 @@ msgstr "" msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:897 +#: ../src/solver/solver.cxx:905 msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:875 +#: ../src/solver/solver.cxx:883 msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:813 +#: ../src/bout++.cxx:822 msgid "Name of file whose existence triggers a stop" msgstr "" @@ -568,7 +568,7 @@ msgid "" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:886 +#: ../src/bout++.cxx:895 msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" @@ -631,13 +631,13 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:855 +#: ../src/bout++.cxx:864 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:858 +#: ../src/bout++.cxx:867 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -652,19 +652,19 @@ msgstr "" msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:773 +#: ../src/solver/solver.cxx:781 msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1273 +#: ../src/solver/solver.cxx:1281 msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1472 +#: ../src/solver/solver.cxx:1480 msgid "Time derivative for variable '{:s}' not set" msgstr "" @@ -688,7 +688,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1546 +#: ../src/mesh/coordinates.cxx:1462 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -731,7 +731,7 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:913 +#: ../src/solver/solver.cxx:921 msgid "User signalled to quit. Returning\n" msgstr "" @@ -776,7 +776,7 @@ msgstr "" msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1224 ../src/solver/solver.cxx:1230 +#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 msgid "Variable '{:s}' not initialised" msgstr "" @@ -786,7 +786,7 @@ msgid "" "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:655 +#: ../src/mesh/coordinates.cxx:633 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" @@ -796,7 +796,7 @@ msgid "" "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:660 +#: ../src/mesh/coordinates.cxx:638 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" @@ -806,7 +806,7 @@ msgid "" "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:804 +#: ../src/bout++.cxx:813 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" diff --git a/locale/zh_CN/libbout.po b/locale/zh_CN/libbout.po index faaca8acbe..295d6a1c13 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: 2023-02-03 16:41+0000\n" +"POT-Creation-Date: 2023-09-22 11:03+0100\n" "PO-Revision-Date: 2018-10-22 22:56+0100\n" "Last-Translator: \n" "Language-Team: Chinese (simplified)\n" @@ -398,7 +398,7 @@ msgstr "" msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:808 +#: ../src/bout++.cxx:817 msgid "Check if a file exists, and exit if it does." msgstr "" @@ -454,7 +454,7 @@ msgstr "" msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:757 +#: ../src/solver/solver.cxx:765 msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" @@ -502,7 +502,7 @@ msgstr "" msgid "Error encountered during initialisation: {:s}\n" msgstr "启动时遇到错误 : {:s}\n" -#: ../src/bout++.cxx:734 +#: ../src/bout++.cxx:743 msgid "Error whilst writing settings" msgstr "" @@ -549,15 +549,15 @@ msgstr "" msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:897 +#: ../src/solver/solver.cxx:905 msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:875 +#: ../src/solver/solver.cxx:883 msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:813 +#: ../src/bout++.cxx:822 msgid "Name of file whose existence triggers a stop" msgstr "" @@ -580,7 +580,7 @@ msgid "" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:886 +#: ../src/bout++.cxx:895 msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" @@ -645,13 +645,13 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:855 +#: ../src/bout++.cxx:864 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:858 +#: ../src/bout++.cxx:867 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -666,19 +666,19 @@ msgstr "" msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:773 +#: ../src/solver/solver.cxx:781 msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1273 +#: ../src/solver/solver.cxx:1281 msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1472 +#: ../src/solver/solver.cxx:1480 msgid "Time derivative for variable '{:s}' not set" msgstr "" @@ -702,7 +702,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1546 +#: ../src/mesh/coordinates.cxx:1462 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -745,7 +745,7 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:913 +#: ../src/solver/solver.cxx:921 msgid "User signalled to quit. Returning\n" msgstr "" @@ -790,7 +790,7 @@ msgstr "" msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1224 ../src/solver/solver.cxx:1230 +#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 msgid "Variable '{:s}' not initialised" msgstr "" @@ -800,7 +800,7 @@ msgid "" "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:655 +#: ../src/mesh/coordinates.cxx:633 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" @@ -810,7 +810,7 @@ msgid "" "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:660 +#: ../src/mesh/coordinates.cxx:638 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" @@ -820,7 +820,7 @@ msgid "" "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:804 +#: ../src/bout++.cxx:813 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" diff --git a/locale/zh_TW/libbout.po b/locale/zh_TW/libbout.po index 685827c0b8..0991e90ab9 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: 2023-02-03 16:41+0000\n" +"POT-Creation-Date: 2023-09-22 11:03+0100\n" "PO-Revision-Date: 2018-10-22 22:56+0100\n" "Last-Translator: \n" "Language-Team: Chinese (traditional)\n" @@ -408,7 +408,7 @@ msgstr "" msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:808 +#: ../src/bout++.cxx:817 msgid "Check if a file exists, and exit if it does." msgstr "" @@ -467,7 +467,7 @@ msgstr "" msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:757 +#: ../src/solver/solver.cxx:765 msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" @@ -515,7 +515,7 @@ msgstr "" msgid "Error encountered during initialisation: {:s}\n" msgstr "啟動時遇到錯誤 : {:s}\n" -#: ../src/bout++.cxx:734 +#: ../src/bout++.cxx:743 msgid "Error whilst writing settings" msgstr "" @@ -562,15 +562,15 @@ msgstr "" msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:897 +#: ../src/solver/solver.cxx:905 msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:875 +#: ../src/solver/solver.cxx:883 msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:813 +#: ../src/bout++.cxx:822 msgid "Name of file whose existence triggers a stop" msgstr "" @@ -593,7 +593,7 @@ msgid "" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:886 +#: ../src/bout++.cxx:895 msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" @@ -661,7 +661,7 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:855 +#: ../src/bout++.cxx:864 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" @@ -670,7 +670,7 @@ msgstr "" "間整合\n" "\n" -#: ../src/bout++.cxx:858 +#: ../src/bout++.cxx:867 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -688,19 +688,19 @@ msgstr "" msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:773 +#: ../src/solver/solver.cxx:781 msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1273 +#: ../src/solver/solver.cxx:1281 msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1472 +#: ../src/solver/solver.cxx:1480 msgid "Time derivative for variable '{:s}' not set" msgstr "" @@ -724,7 +724,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1546 +#: ../src/mesh/coordinates.cxx:1462 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -767,7 +767,7 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:913 +#: ../src/solver/solver.cxx:921 msgid "User signalled to quit. Returning\n" msgstr "" @@ -812,7 +812,7 @@ msgstr "" msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1224 ../src/solver/solver.cxx:1230 +#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 msgid "Variable '{:s}' not initialised" msgstr "" @@ -822,7 +822,7 @@ msgid "" "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:655 +#: ../src/mesh/coordinates.cxx:633 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" @@ -832,7 +832,7 @@ msgid "" "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:660 +#: ../src/mesh/coordinates.cxx:638 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" @@ -842,7 +842,7 @@ msgid "" "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:804 +#: ../src/bout++.cxx:813 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" diff --git a/manual/RELEASE_HOWTO.md b/manual/RELEASE_HOWTO.md index 3c12c4fdc4..4103e6f197 100644 --- a/manual/RELEASE_HOWTO.md +++ b/manual/RELEASE_HOWTO.md @@ -51,7 +51,6 @@ Before merging PR: - [ ] [`manual/doxygen/Doxyfile_readthedocs`][Doxyfile_readthedocs]: `PROJECT_NUMBER` - [ ] [`manual/doxygen/Doxyfile`][Doxyfile]: `PROJECT_NUMBER` - [ ] [`CMakeLists.txt`][CMakeLists]: `_bout_previous_version`, `_bout_next_version` - - [ ] [`tools/pylib/_boutpp_build/backend.py`][backend.py]: `_bout_previous_version`, `_bout_next_version` After PR is merged: @@ -60,6 +59,10 @@ After PR is merged: - [ ] Try to summarise the changes! - [ ] Make [GitHub Release][gh_release], include change summary **NB:** tag should have leading `v` +- [ ] Make tarball: `cmake -S . -B build && make dist -C build` +- [ ] Check tarball: + - [ ] Is the folder name correct? + - [ ] grep for the version - is always the released version used, not a pre-release? - [ ] Upload tarball to GitHub Release - [ ] Upload tarball to Zenodo and publish new version - [ ] Email BOUT++ User Group mailing list, include change summary diff --git a/manual/doxygen/Doxyfile b/manual/doxygen/Doxyfile index 19afabe013..216ef60915 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.0.0 +PROJECT_NUMBER = 5.1.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 diff --git a/manual/doxygen/Doxyfile_readthedocs b/manual/doxygen/Doxyfile_readthedocs index 89cfe3c92d..e27df586ec 100644 --- a/manual/doxygen/Doxyfile_readthedocs +++ b/manual/doxygen/Doxyfile_readthedocs @@ -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.0.0 +PROJECT_NUMBER = 5.1.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 diff --git a/manual/sphinx/conf.py b/manual/sphinx/conf.py index c5a9f4716d..0705e9e5c8 100755 --- a/manual/sphinx/conf.py +++ b/manual/sphinx/conf.py @@ -49,7 +49,6 @@ def __getattr__(cls, name): return MagicMock() MOCK_MODULES = [ - "h5py", "netCDF4", "mayavi2", "enthought", @@ -185,9 +184,9 @@ def __getattr__(cls, name): # built documents. # # The short X.Y version. -version = "5.0" +version = "5.1" # The full version, including alpha/beta/rc tags. -release = "5.0.0" +release = "5.1.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/manual/sphinx/developer_docs/data_types.rst b/manual/sphinx/developer_docs/data_types.rst index fa19f83bbc..2e303381f9 100644 --- a/manual/sphinx/developer_docs/data_types.rst +++ b/manual/sphinx/developer_docs/data_types.rst @@ -347,7 +347,7 @@ offsets there is a function ``offset(x,y,z)`` so that Note that by default no bounds checking is performed. If the checking level is increased to 3 or above then bounds checks will be performed. This will have a significant (bad) impact on performance, so is -just for debugging purposes. Configure with ``--enable-checks=3`` +just for debugging purposes. Configure with ``-DCHECK=3`` option to do this. diff --git a/manual/sphinx/developer_docs/mesh.rst b/manual/sphinx/developer_docs/mesh.rst index afdd723faa..ff3e40d4b0 100644 --- a/manual/sphinx/developer_docs/mesh.rst +++ b/manual/sphinx/developer_docs/mesh.rst @@ -263,7 +263,7 @@ The mesh spacing is given by the public members `Coordinates::dx`, Field2D zlength(); // Computed from dz `Coordinates::FieldMetric` can be either `Field2D` or if BOUT++ has -been configured with ``--enable-metric-3d`` then a `Field3D`. +been configured with ``-DBOUT_ENABLE_METRIC_3D`` then a `Field3D`. Metrics ------- diff --git a/manual/sphinx/developer_docs/performance_profiling.rst b/manual/sphinx/developer_docs/performance_profiling.rst index 9ba5c8d484..d93c1e904b 100644 --- a/manual/sphinx/developer_docs/performance_profiling.rst +++ b/manual/sphinx/developer_docs/performance_profiling.rst @@ -82,11 +82,10 @@ percent of runtime. Configure and build ~~~~~~~~~~~~~~~~~~~ -Configure with ``--with-scorep`` to enable Scorep instrumentation, then build -as normal. This option can be combined with other options, but it is usually -desirable to profile the optimized code, configuring with the flags -``--enable-optimize=3 --enable-checks=0``. Build the code with ``make`` as -normal. +Configure with ``-BOUT_USE_SCOREP`` to enable Scorep instrumentation, +then build as normal. This option can be combined with other options, +but it is usually desirable to profile the optimized code, configuring +with the flags ````. Build the code with ``make`` as normal. With CMake: @@ -95,6 +94,7 @@ With CMake: $ SCOREP_WRAPPER=off cmake \ -DCMAKE_C_COMPILER=scorep-mpicc \ -DCMAKE_CXX_COMPILER=scorep-mpicxx \ + -DCMAKE_CXX_FLAGS=-O3 -DCHECK=0 \ This will turn off the instrumentation during the configure diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index 5e230b8ad8..b2b6b49c80 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -14,53 +14,24 @@ SUNDIALS and PETSc. Optimisation and run-time checking ---------------------------------- -Configure with ``--enable-checks=3`` enables a lot of checks of +Configure with ``-DCHECK=3`` enables a lot of checks of operations performed by the field objects. This is very useful for debugging a code, and can be omitted once bugs have been removed. -``--enable=checks=2`` enables less checking, especially the -computationally rather expensive ones, while ``--enable-checks=0`` +``-DCHECK=2`` enables less checking, especially the +computationally rather expensive ones, while ``-DCHECK=0`` disables most checks. -To get most checking, both from BOUT++ and from the compiler -``--enable-debug`` can be used. That enables checks of level 3, as -well as debug flags, e.g. ``-g`` for gcc. - For (sometimes) more useful error messages, there is the -``--enable-track`` option. This keeps track of the names of variables -and includes these in error messages. +``-DBOUT_ENABLE_TRACK=ON`` option. This keeps track of the names of +variables and includes these in error messages. To get a backtrace, you can set the environment variable ``BOUT_SHOW_BACKTRACE`` in order for the exception to include the backtrace. -To enable optimization, configure with ``--enable-optimize=3``. -This will try to set appropriate flags, but may not set the best ones. -This should work well for gcc. Similar to checks, different levels can -be specified, where 3 is high, and 0 means disabling all -optimization. ``--enable-optimize=fast`` will set the ``-Ofast`` flag -for gcc which enables optimizations that are not standard conforming, so -proceed at own risk. - -Manually set compilation flags ------------------------------- - -You can set the following environment variables if you need more -control over how BOUT++ is built: - -- ``LDFLAGS``: extra flags for linking, e.g. ``-L`` - -- ``LIBS``: extra libraries for linking, e.g. ``-l`` +To enable optimization, configure with appropriate flags for your +compiler, e.g. with ``-DCMAKE_CXX_FLAGS=" -O3 "`` for a gnu compiler. -- ``CPPFLAGS``: preprocessor flags, e.g. ``-I`` - -- ``CXXFLAGS``: compiler flags, e.g. ``-Wall`` - -- ``SUNDIALS_EXTRA_LIBS`` specifies additional libraries for linking - to SUNDIALS, which are put at the end of the link command. - -It is possible to change flags for BOUT++ after running configure, by -editing the ``make.config`` file. Note that this is not recommended, -as e.g. PVODE will not be built with these flags. Install dependencies: --------------------- @@ -234,9 +205,11 @@ Compiling with Apple Clang 12, the following configuration has been known to wor .. code-block:: tcsh - cmake . -B build -DBOUT_ENABLE_BACKTRACE=Off -DBUILD_SHARED_LIBS=Off -DBOUT_USE_NLS=Off -DBOUT_USE_UUID_SYSTEM_GENERATOR=Off - cd build - make + cmake . -B -DBOUT_ENABLE_BACKTRACE=Off -DBUILD_SHARED_LIBS=Off -DBOUT_USE_NLS=Off -DBOUT_USE_UUID_SYSTEM_GENERATOR=Off + cd + cmake --build + +where ```` is the path to the build directory Marconi ~~~~~~~ @@ -334,7 +307,7 @@ BOUT++ will look for ``ncxx4-config`` or ``nc-config`` in your version than the one you want, you can point it at the correct version using:: - ./configure --with-netcdf=/path/to/ncxx4-config + cmake -S .. -B . -DBOUT_USE_NETCDF=ON -DnetCDFCxx_ROOT=/path/to/ncxx4-config where ``/path/to/ncxx4-config`` is the location of the ``ncxx4-config`` tool (``nc-config`` will also work, but @@ -391,9 +364,9 @@ OpenMP ------ BOUT++ can make use of OpenMP parallelism. To enable OpenMP, use the -``--enable-openmp`` flag to configure:: +``-DBOUT_ENABLE_OPENMP=ON`` flag to configure:: - ./configure --enable-openmp + cmake -S .. -B . -DBOUT_ENABLE_OPENMP=ON OpenMP can be used to parallelise in more directions than can be achieved with MPI alone. For example, it is currently difficult to @@ -416,7 +389,7 @@ some problem sizes on some machines) is setting the OpenMP schedule used in some of the OpenMP loops (specifically those using `BOUT_FOR`). This can be set using:: - ./configure --enable-openmp --with-openmp-schedule= + cmake . -DBOUT_ENABLE_OPENMP=ON -DBOUT_OPENMP_SCHEDULE= with ```` being one of: ``static`` (the default), ``dynamic``, ``guided``, ``auto`` or ``runtime``. @@ -486,9 +459,9 @@ solver, which evolves a system of the form :math:`\mathbf{f}(\mathbf{u},\dot{\mathbf{u}},t) = 0`. This allows algebraic constraints on variables to be specified. -Use the ``--with-sundials`` option to configure BOUT++ with SUNDIALS:: +Use the ``-DBOUT_USE_SUNDIALS=ON -DSUNDIALS_ROOT=`` option to configure BOUT++ with SUNDIALS:: - $ ./configure --with-sundials=/path/to/sundials/install + $ cmake . -DBOUT_USE_SUNDIALS=ON -DSUNDIALS_ROOT=/path/to/sundials/install SUNDIALS will allow you to select at run-time which solver to use. See :ref:`sec-timeoptions` for more details on how to do this. @@ -496,8 +469,6 @@ SUNDIALS will allow you to select at run-time which solver to use. See Notes: * If compiling SUNDIALS, make sure that it is configured with MPI (``MPI_ENABLE=ON``) -* If you install SUNDIALS to a non-standard (system) directory, you will probably have - to add the ``lib`` directory to the ``LD_LIBRARY_PATH`` environment variable. .. _sec-PETSc-install: @@ -508,15 +479,15 @@ BOUT++ can use PETSc https://www.mcs.anl.gov/petsc/ for time-integration and for solving elliptic problems, such as inverting Poisson and Helmholtz equations. -Currently, BOUT++ supports PETSc versions 3.7 - 3.14. More recent versions may +Currently, BOUT++ supports PETSc versions 3.7 - 3.19. More recent versions may well work, but the PETSc API does sometimes change in backward-incompatible -ways, so this is not guaranteed. To install PETSc version 3.13, use the +ways, so this is not guaranteed. To install PETSc version 3.19, use the following steps:: $ cd ~ - $ wget http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-3.13.4.tar.gz - $ tar -xzvf petsc-3.13.4.tar.gz - $ cd petsc-3.13.4 + $ wget https://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-3.19.1.tar.gz + $ tar -xzvf petsc-3.19.1.tar.gz + $ cd petsc-3.19.1 Use the following configure options to ensure PETSc is compatible with BOUT++:: @@ -551,10 +522,10 @@ installed to. to ``./configure``. -To make PETSc type what is shown in the terminal output after the configure +To make PETSc, type what is shown in the terminal output after the configure step, something like:: - $ make PETSC_DIR=$HOME/petsc-3.13.4 PETSC_ARCH=arch-linux2-cxx-debug all + $ make PETSC_DIR=$HOME/petsc-3.19.1 PETSC_ARCH=arch-linux2-cxx-debug all Should BLAS, LAPACK, or any other packages be missing, you will get an error, and a suggestion that you can append @@ -563,20 +534,20 @@ error, and a suggestion that you can append You may want to test that everything is configured properly. To do this replace ``all`` with ``test`` in the make command. It should be something like:: - $ make PETSC_DIR=$HOME/petsc-3.13.4 PETSC_ARCH=arch-linux2-cxx-debug test + $ make PETSC_DIR=$HOME/petsc-3.19.1 PETSC_ARCH=arch-linux2-cxx-debug test To install PETSc, replace ``test``/``all`` with ``install`` and run something like:: - $ make PETSC_DIR=$HOME/petsc-3.13.4 PETSC_ARCH=arch-linux2-cxx-debug install + $ make PETSC_DIR=$HOME/petsc-3.19.1 PETSC_ARCH=arch-linux2-cxx-debug install To configure BOUT++ with PETSc, add to the cmake configure command:: - -DBOUT_USE_PETSC=ON -DPETSC_ROOT=$HOME/local/petsc-version-options + -DBOUT_USE_PETSC=ON -DPETSC_DIR=$HOME/local/petsc-version-options For example like this:: - $ cmake -DBOUT_USE_PETSC=ON -DPETSC_ROOT=$HOME/local/petsc-version-options + $ cmake -S . -B -DBOUT_USE_PETSC=ON -DPETSC_DIR=$HOME/local/petsc-version-options BOUT++ can also work with PETSc if it has not been installed. In this case ensure that ``PETSC_DIR`` and ``PETSC_ARCH`` are set, for example @@ -596,11 +567,11 @@ serial performance. This does not add new features, but may be faster in some cases. LAPACK is however written in FORTRAN 77, which can cause linking headaches. To enable these routines use:: - $ ./configure --with-lapack + $ cmake -S . -B -DBOUT_USE_LAPACK=ON and to specify a non-standard path:: - $ ./configure --with-lapack=/path/to/lapack + $ cmake -S . -B -DBOUT_USE_LAPACK=ON -DLAPACK_ROOT=/path/to/lapack MPI compilers @@ -608,9 +579,7 @@ MPI compilers These are usually called something like mpicc and mpiCC (or mpicxx), and the configure script will look for several common names. If your -compilers aren’t recognised then set them using:: - - $ ./configure MPICC= MPICXX= +compilers aren’t recognised then check the `cmake documentation for MPI `_ NOTES: @@ -887,15 +856,11 @@ to ``next``, with an error like the following:: make: *** [src] Error 2 it's possible something has gone wrong with the submodules. To fix, -just run ``make submodules``:: +just run:: - $ make submodules - Downloading mpark.variant - git submodule update --init --recursive /home/peter/Codes/BOUT-dev/externalpackages/mpark.variant - Submodule path 'externalpackages/mpark.variant': checked out '0b488da9bebac980e7ba0e158a959c956a449676' + $ git submodule update --init --recursive ./externalpackages/* -If you regularly work on two different branches and need to run ``make -submodules`` a lot, you may consider telling git to automatically +If you regularly work on two different branches and need to run the above command a lot, you may consider telling git to automatically update the submodules:: git config submodule.recurse=true diff --git a/manual/sphinx/user_docs/input_grids.rst b/manual/sphinx/user_docs/input_grids.rst index a676aa23f3..3d6be2cf77 100644 --- a/manual/sphinx/user_docs/input_grids.rst +++ b/manual/sphinx/user_docs/input_grids.rst @@ -111,7 +111,7 @@ found, a warning will be printed and the default values used. - Differencing quantities in 2D/3D arrays ``dx(nx,ny[,nz])``, ``dy(nx,ny[,nz])`` and ``dz(nx,ny[,nz])``. If these are not found they will be set to 1. To allow variation in ``z`` direction, BOUT++ - has to be configured ``--enable-metric-3d``, otherwise 2D fields are + has to be configured ``-DBOUT_ENABLE_METRIC_3D``, otherwise 2D fields are used for the metric fields. Note that prior to BOUT++ version 5 ``dz`` was a constant. diff --git a/manual/sphinx/user_docs/installing.rst b/manual/sphinx/user_docs/installing.rst index 260909c8ba..7f8c26ffbe 100644 --- a/manual/sphinx/user_docs/installing.rst +++ b/manual/sphinx/user_docs/installing.rst @@ -476,14 +476,9 @@ gettext. If you are planning on installing BOUT++ (see you will be running BOUT++ from the directory you downloaded it into, then configure with the option:: - ./configure --localedir=$PWD/locale + cmake . -DCMAKE_INSTALL_LOCALEDIR=$PWD/locale -This will enable BOUT++ to find the translations. When ``configure`` -finishes, the configuration summary should contain a line like:: - - configure: Natural language support: yes (path: /home/user/BOUT-dev/locale) - -where the ``path`` is the directory containing the translations. +This will enable BOUT++ to find the translations. See :ref:`sec-run-nls` for details of how to switch language when running BOUT++ simulations. @@ -525,13 +520,17 @@ You can also install all the packages directly (see the documentation in the `bo `__ repos for the most up to date list) using pip:: - $ pip install --user numpy scipy matplotlib sympy netCDF4 h5py future importlib-metadata + $ pip install --user numpy scipy matplotlib sympy netCDF4 future importlib-metadata or conda:: - $ conda install numpy scipy matplotlib sympy netcdf4 h5py future importlib-metadata + $ conda install numpy scipy matplotlib sympy netcdf4 future importlib-metadata + +They may also be available from your Linux system's package manager. + +For example on Fedora:: -They may also be available from your Linux system's package manager. + $ sudo dnf install python3-boututils python3-boutdata To use the versions of ``boututils`` and ``boutdata`` provided by BOUT++, the path to ``tools/pylib`` should be added to the ``PYTHONPATH`` environment variable. This is not @@ -590,25 +589,14 @@ Compiling BOUT++ ---------------- Once BOUT++ has been configured, you can compile the bulk of the code by -going to the ``BOUT-dev`` directory (same as ``configure``) and running:: +going to the ``BOUT-dev`` directory and running:: - $ make + $ cmake --build -(on OS-X, FreeBSD, and AIX this should be ``gmake``). This should print -something like:: +where ```` is the path to the build directory - ----- Compiling BOUT++ ----- - CXX = mpicxx - CFLAGS = -O -DCHECK=2 -DSIGHANDLE \ - -DREVISION=13571f760cec446d907e1bbeb1d7a3b1c6e0212a \ - -DNCDF -DBOUT_HAS_PVODE - CHECKSUM = ff3fb702b13acc092613cfce3869b875 - INCLUDE = -I../include - Compiling field.cxx - Compiling field2d.cxx - -At the end of this, you should see a file ``libbout++.a`` in the -``lib/`` subdirectory of the BOUT++ distribution. If you get an error, +At the end of this, you should see a file ``libbout++.so`` in the +``lib/`` subdirectory of the BOUT++ build directory. If you get an error, please `create an issue on Github `__ including: @@ -616,7 +604,7 @@ including: - The output from make, including full error message -- The ``make.config`` file in the BOUT++ root directory +- The ``CMakeCache.txt`` file in the BOUT++ build directory .. _sec-runtestsuite: @@ -627,25 +615,25 @@ BOUT++ comes with three sets of test suites: unit tests, integrated tests and method of manufactured solutions (MMS) tests. The easiest way to run all of them is to simply do:: - $ make check + $ cmake --build --target check -from the top-level directory. Alternatively, if you just want to run -one them individually, you can do:: +Alternatively, if you just want to run +one set of them individually, you can do:: - $ make check-unit-tests - $ make check-integrated-tests - $ make check-mms-tests + $ cmake --build --target check-unit-tests + $ cmake --build --target check-integrated-tests + $ cmake --build --target check-mms-tests -**Note:** The integrated test suite currently uses the ``mpirun`` +**Note:** The integrated and MMS test suites currently uses the ``mpirun`` command to launch the runs, so won’t work on machines which use a job -submission system like PBS or SGE. +submission system like slurm or PBS. These tests should all pass, but if not please `create an issue on Github `__ containing: - Which machine you’re running on -- The ``make.config`` file in the BOUT++ root directory +- The ``CMakeCache.txt`` file in the BOUT++ build directory - The ``run.log.*`` files in the directory of the test which failed @@ -667,7 +655,7 @@ not widely used and so should be considered experimental. After configuring and compiling BOUT++ as above, BOUT++ can be installed to system directories by running as superuser or ``sudo``:: - $ sudo make install + $ sudo cmake --build --target install .. DANGER:: Do not do this unless you know what you're doing! @@ -677,39 +665,35 @@ This will install the following files under ``/usr/local/``: * ``/usr/local/include/bout++/...`` header files for BOUT++ -* ``/usr/local/lib/libbout++.a`` The main BOUT++ library +* ``/usr/local/lib/libbout++.so`` The main BOUT++ library -* ``/usr/local/lib/libpvode.a`` and ``/usr/local/lib/libpvpre.a``, the PVODE library +* ``/usr/local/lib/libpvode.so`` and ``/usr/local/lib/libpvpre.so``, the PVODE library * ``/usr/local/share/bout++/pylib/...`` Python analysis routines * ``/usr/local/share/bout++/idllib/...`` IDL analysis routines -* ``/usr/local/share/bout++/make.config`` A ``makefile`` configuration, used to compile many BOUT++ examples - -To install BOUT++ under a different directory, use the ``--prefix=`` +To install BOUT++ under a different directory, use the ``prefix=`` flag e.g. to install in your home directory:: - $ make install prefix=$HOME/local/ + $ cmake --build --target install -DCMAKE_INSTALL_PREFIX=$HOME/local/ You can also specify this prefix when configuring, in the usual way (see :ref:`sec-config-bout`):: - $ ./configure --prefix=$HOME/local/ - $ make - $ make install + $ cmake -S . -B -DCMAKE_INSTALL_PREFIX=$HOME/local/ + $ cmake --build -j 4 + $ cmake --build --target install More control over where files are installed is possible by passing options to -``configure``, following the GNU conventions: - -* ``--bindir=`` sets where ``bout-config`` will be installed ( default ``/usr/local/bin``) +``cmake``, following the GNU conventions: -* ``--includedir=`` sets where the ``bout++/*.hxx`` header files wil be installed (default ``/usr/local/include``) +* ``-DCMAKE_INSTALL_BINDIR=`` sets where ``bout-config`` will be installed ( default ``/usr/local/bin``) -* ``--libdir=`` sets where the ``libbout++.a``, ``libpvode.a`` and ``libpvpre.a`` libraries are installed (default ``/usr/local/lib``) +* ``-DCMAKE_INSTALL_INCLUDEDIR=`` sets where the ``bout++/*.hxx`` header files wil be installed (default ``/usr/local/include``) -* ``--datadir=`` sets where ``idllib``, ``pylib`` and ``make.config`` are installed (default ``/usr/local/share/``) +* ``-DCMAKE_INSTALL_LIBDIR=`` sets where the ``libbout++.so``, ``libpvode.so`` and ``libpvpre.so`` libraries are installed (default ``/usr/local/lib``) After installing, that you can run ``bout-config`` e.g:: diff --git a/manual/sphinx/user_docs/new_in_v5.rst b/manual/sphinx/user_docs/new_in_v5.rst index 8a1f5b0128..b9eb637cd5 100644 --- a/manual/sphinx/user_docs/new_in_v5.rst +++ b/manual/sphinx/user_docs/new_in_v5.rst @@ -20,12 +20,6 @@ allow simulations of devices such as stellarators. To enable 3D metrics, build BOUT++ like: -.. code-block:: console - - ./configure --enable-metric-3D - -or, with CMake: - .. code-block:: console cmake . -B build -DBOUT_ENABLE_METRIC_3D=ON diff --git a/manual/sphinx/user_docs/output_and_post.rst b/manual/sphinx/user_docs/output_and_post.rst index ff32da04d0..71f4098113 100644 --- a/manual/sphinx/user_docs/output_and_post.rst +++ b/manual/sphinx/user_docs/output_and_post.rst @@ -30,7 +30,7 @@ Requirements The Python tools provided with BOUT++ make heavy use of numpy_ and scipy_, as well as matplotlib_ for the plotting routines. In order -to read BOUT++ output in Python, you will need either netcdf4_ or h5py_. +to read BOUT++ output in Python, you will need either netcdf4_. While we try to ensure that the Python tools are compatible with both Python 2 and 3, we officially only support Python 3. @@ -55,7 +55,6 @@ supported versions of numpy, scipy, netcdf4, matplotlib and jinja2. .. _scipy: http://www.scipy.org/ .. _matplotlib: https://www.matplotlib.org .. _netcdf4: http://unidata.github.io/netcdf4-python/ -.. _h5py: http://www.h5py.org .. _Jinja2: http://jinja.pocoo.org/ .. _installation instructions: https://www.scipy.org/install.html diff --git a/manual/sphinx/user_docs/physics_models.rst b/manual/sphinx/user_docs/physics_models.rst index 609997c0c2..56e3b719b4 100644 --- a/manual/sphinx/user_docs/physics_models.rst +++ b/manual/sphinx/user_docs/physics_models.rst @@ -1122,9 +1122,9 @@ everything except ``output_warn`` and ``output_error``. To enable the ``output_debug`` messages, configure BOUT++ with a ``CHECK`` level ``>= 3``. To enable it at lower check levels, -configure BOUT++ with ``--enable-debug-output`` (for ``./configure``) -or ``-DENABLE_OUTPUT_DEBUG`` (for ``CMake``). When running BOUT++ add -a ``-v -v`` flag to see ``output_debug`` messages. +configure BOUT++ with ``-DENABLE_OUTPUT_DEBUG`` (for ``CMake``; +``--enable-debug-output`` for ``./configure``)). When running BOUT++ +add a ``-v -v`` flag to see ``output_debug`` messages. .. _sec-3to4: diff --git a/manual/sphinx/user_docs/python_boutpp.rst b/manual/sphinx/user_docs/python_boutpp.rst index 77786264a5..939a817ffe 100644 --- a/manual/sphinx/user_docs/python_boutpp.rst +++ b/manual/sphinx/user_docs/python_boutpp.rst @@ -1,55 +1,51 @@ The python boutpp module -========================== +======================== Installing ---------- -Installing boutpp can be tricky. -Ideally it should be just +Installing boutpp can be tricky, however in most cases it should be +automatically enabled if all dependencies are available. +To error out on missing dependencies, explicitly enable it:: .. code-block:: bash - ./configure --enable-shared - make -j 4 python + cmake -DBOUT_ENABLE_PYTHON=ON -but getting all the -dependencies can be difficult. -``make python`` creates the python3 module. +It can be especially tricky if you want to run boutpp on login nodes +for simple post processing, but due to differences in the instruction +set the compiled modules for the compute nodes do not run there. In +that case you need to manually install all needed dependencies. It is +probably a good idea to use a different build directory, to not +unintentionally modify your BOUT++ compilation for the compute nodes. -If problems arise, it might be worth checking a copy of the bout -module out, to reduce the risk of causing issues with the old bout -installation. This is especially true if you are trying to run -boutpp not on compute nodes of a super computer but rather on -post-processing/login/... nodes. +If you are running fedora - you can install pre-build binaries: -To use boutpp on the login node, a self compiled version of mpi may be -required, as the provided one may be only for the compute nodes. -Further, numpy header files are required, therefore numpy needs to be -compiled as well. -Further, the header files need to be exposed to the boutpp cython -compilation, e.g. by adding them to ``_boutpp_build/boutpp.pyx.in``. -It seems both ``NUMPY/numpy/core/include`` and -``NUMPY/build/src.linux-x86_64-2.7/numpy/core/include/numpy`` need to be -added, where ``NUMPY`` is the path of the numpy directory. -For running boutpp on the post processing nodes, fftw3 needs to be -compiled as well, if certain fftw routines are used. Note, fftw needs -to be configured with ``--enable-shared``. +.. code-block:: bash -After installing mpi e.g. in ``~/local/mpich``, bout needs to be -configured with something like: -``./configure --enable-shared MPICC=~/local/mpich/bin/mpicc MPICXX=~/local/mpich/bin/mpicxx --with-fftw=~/local/fftw/`` + sudo dnf install python3-bout++-mpich + module load mpi/mpich-$(arch) -``--enable-shared`` is required, so that pvode etc. is compiles as position -independent code. +You can also pip install boutpp with: -If you are running fedora - you can install pre-build binaries: +.. code-block:: bash + + pip install boutpp-nightly + +This will download the latest boutpp-nightly version, compile and +install it. Note that you still need all the non-python dependencies +like mpi. Note that after ``pip install boutpp-nightly`` the +``boutpp`` module is installed, so you can use ``import boutpp`` +independent of the version used. + +After the 5.0.0 release you will also be able to install the latest +released version of boutpp with: .. code-block:: bash - sudo dnf copr enable davidsch/bout - sudo dnf install python3-bout++-mpich - module load mpi/mpich-$(arch) + pip install boutpp + Purpose @@ -58,18 +54,18 @@ Purpose The boutpp module exposes (part) of the BOUT++ C++ library to python. It allows to calculate e.g. BOUT++ derivatives in python. -State ------ -Field3D and Field2D are working. If other fields are needed, please open an issue. -Fields can be accessed directly using the [] operators, and give a list of slice objects. -The get all data, ``f3d.getAll()`` is equivalent to ``f3d[:,:,]`` and returns a numpy array. -This array can be addressed with -e.g. ``[]`` operators, and then the field can be set again with -``f3d.setAll(numpyarray)``. -It is also possible to set a part of an Field3D with the ``[]`` operators. -Addition, multiplication etc. are all available. -The derivatives should all be working, if find a missing one, please open an issue. -Vectors are not exposed yet. +State ----- Field3D and Field2D are working. If other fields are +needed, please open an issue. Fields can be accessed directly using +the [] operators, similar to numpy. The get all data, ``f3d[:]`` is +equivalent to ``f3d[:, :, :]`` and returns a numpy array. This array +can be addressed with e.g. ``[]`` operators, and then the field can be +set again with ``f3d[:] = numpyarray``. It is also possible to set a +part of an Field3D with the ``[]`` operators. Addition, +multiplication etc. are all available. The derivatives should all be +working, if find a missing one, please open an issue. + +Note that views are currently not supported, thus ``f3d[:] += 1`` will +modify the returned copy, and the ``f3d`` object will be unchanged. Functions --------- @@ -84,12 +80,12 @@ Some trivial post processing: import boutpp import numpy as np - args="-d data -f BOUT.settings -o BOUT.post".split(" ") + args="-d data -f BOUT.settings -o BOUT.post" boutpp.init(args) - dens=boutpp.Field3D.fromCollect("n",path="data") - temp=boutpp.Field3D.fromCollect("T",path="data") - pres=dens*temp - dpdz=boutpp.DDZ(pres,outloc="CELL_ZLOW") + dens = boutpp.Field3D.fromCollect("n", path="data") + temp = boutpp.Field3D.fromCollect("T", path="data") + pres = dens * temp + dpdz = boutpp.DDZ(pres, outloc="CELL_ZLOW") @@ -100,14 +96,14 @@ A simple MMS test: import boutpp import numpy as np boutpp.init("-d data -f BOUT.settings -o BOUT.post") - for nz in [64,128,256]: - boutpp.setOption("meshz:nz","%d"%nz) - mesh=boutpp.Mesh(OptionSection="meshz") - f=boutpp.create3D("sin(z)",mesh) - sim=boutpp.DDZ(f) - ana=boutpp.create3D("cos(z)",mesh) - err=sim-ana - err=boutpp.max(boutpp.abs(err)) + for nz in [64, 128, 256]: + boutpp.setOption("meshz:nz", "%d"%nz) + mesh = boutpp.Mesh(OptionSection="meshz") + f = boutpp.create3D("sin(z)", mesh) + sim = boutpp.DDZ(f) + ana = boutpp.create3D("cos(z)", mesh) + err = sim - ana + err = boutpp.max(boutpp.abs(err)) errors.append(err) @@ -118,10 +114,10 @@ A real example - unstagger data: import boutpp boutpp.init("-d data -f BOUT.settings -o BOUT.post") # uses location from dump - is already staggered - upar=boutpp.Field3D.fromCollect("Upar") - upar=boutpp.interp_to(upar,"CELL_CENTRE") + upar = boutpp.Field3D.fromCollect("Upar") + upar = boutpp.interp_to(upar, "CELL_CENTRE") # convert to numpy array - upar=upar.getAll() + upar = upar[:] A real example - check derivative contributions: diff --git a/manual/sphinx/user_docs/quickstart.rst b/manual/sphinx/user_docs/quickstart.rst index 8162fdabf5..94ada4d27a 100644 --- a/manual/sphinx/user_docs/quickstart.rst +++ b/manual/sphinx/user_docs/quickstart.rst @@ -62,7 +62,7 @@ We can now run the conduction example:: You should see some output like:: - BOUT++ version 5.0.0 + BOUT++ version 5.1.0 Revision: b3ee80bfa2ad9b875b69ab072a392b3f548efea8 Code compiled on Jul 27 2022 at 18:13:23 @@ -102,6 +102,7 @@ We can now have a look at the results using xBOUT: >>> import xbout >>> df = xbout.open_boutdataset("data/BOUT.dmp.*.nc") >>> df["T"].plot() + >>> import matplotlib.pyplot as plt ; plt.show() which should produce something similar to the following figure: diff --git a/manual/sphinx/user_docs/running_bout.rst b/manual/sphinx/user_docs/running_bout.rst index 09102bab33..59c5b53828 100644 --- a/manual/sphinx/user_docs/running_bout.rst +++ b/manual/sphinx/user_docs/running_bout.rst @@ -232,26 +232,25 @@ when you need a way to debug your code too. which shows which functions were being run (most recent first). This should give a good indication of where an error occurred. If this stack isn’t printed, make sure checking is set to level 2 or higher - (``./configure –-enable-checks=2``). + (``cmake -DCHECK=2``). - If the error is due to non-finite numbers, increase the checking - level (``./configure –-enable-checks=3``) to perform more checking of + level (``cmake -DCHECK=3``) to perform more checking of values and (hopefully) find an error as soon as possible after it occurs. - If the error is a segmentation fault, you can try a debugger such as gdb or totalview. You will likely need to compile with some - debugging flags (``./configure --enable-debug``). + debugging flags (``cmake -DCMAKE_CXX_FLAGS=" -g "``). - You can also enable exceptions on floating point errors - (``./configure --enable-sigfpe``), though the majority of these + (``cmake -DBOUT_ENABLE_SIGFPE``), though the majority of these types of errors should be caught with checking level set to 3. - Expert users can try AddressSanitizer, which is a tool that comes with recent versions of GCC and Clang. To enable AddressSanitizer, include ``-fsanitize=leak -fsanitize=address -fsanitize=undefined`` - in ``CXXFLAGS`` when configuring BOUT++, or add them to - ``BOUT_FLAGS``. + in ``-DCMAKE_CXX_FLAGS`` when configuring BOUT++. Startup output -------------- diff --git a/manual/sphinx/user_docs/staggered_grids.rst b/manual/sphinx/user_docs/staggered_grids.rst index 42b5deb698..00f565d560 100644 --- a/manual/sphinx/user_docs/staggered_grids.rst +++ b/manual/sphinx/user_docs/staggered_grids.rst @@ -46,7 +46,7 @@ locations of the evolving variables are:: which makes the velocity ``v`` staggered to the lower side of the cell in Y, whilst the density :math:`n` remains cell centred. -.. note:: If BOUT++ was configued ``--with-checks``, +.. note:: If BOUT++ was not configued with ``-DCHECK=0``, `Field3D::setLocation` will throw an exception if you don't have staggered grids turned on and try to set the location to something other than `CELL_CENTRE`. If you want to be diff --git a/manual/sphinx/user_docs/time_integration.rst b/manual/sphinx/user_docs/time_integration.rst index 06aa1cf535..7d0b56abcc 100644 --- a/manual/sphinx/user_docs/time_integration.rst +++ b/manual/sphinx/user_docs/time_integration.rst @@ -34,33 +34,33 @@ needed to make the solver available. .. _tab-solvers: .. table:: Available time integration solvers - +---------------+-----------------------------------------+--------------------+ - | Name | Description | Compile options | - +===============+=========================================+====================+ - | euler | Euler explicit method (example only) | Always available | - +---------------+-----------------------------------------+--------------------+ - | rk4 | Runge-Kutta 4th-order explicit method | Always available | - +---------------+-----------------------------------------+--------------------+ - | rkgeneric | Generic Runge Kutta explicit methods | Always available | - +---------------+-----------------------------------------+--------------------+ - | rk3ssp | 3rd-order Strong Stability Preserving | Always available | - +---------------+-----------------------------------------+--------------------+ - | splitrk | Split RK3-SSP and RK-Legendre | Always available | - +---------------+-----------------------------------------+--------------------+ - | pvode | 1998 PVODE with BDF method | Always available | - +---------------+-----------------------------------------+--------------------+ - | cvode | SUNDIALS CVODE. BDF and Adams methods | –with-cvode | - +---------------+-----------------------------------------+--------------------+ - | ida | SUNDIALS IDA. DAE solver | –with-ida | - +---------------+-----------------------------------------+--------------------+ - | arkode | SUNDIALS ARKODE IMEX solver | –with-arkode | - +---------------+-----------------------------------------+--------------------+ - | petsc | PETSc TS methods | –with-petsc | - +---------------+-----------------------------------------+--------------------+ - | imexbdf2 | IMEX-BDF2 scheme | –with-petsc | - +---------------+-----------------------------------------+--------------------+ - | beuler / snes | Backward Euler with SNES solvers | --with-petsc | - +---------------+-----------------------------------------+--------------------+ + +---------------+-----------------------------------------+------------------------+ + | Name | Description | Compile options | + +===============+=========================================+========================+ + | euler | Euler explicit method (example only) | Always available | + +---------------+-----------------------------------------+------------------------+ + | rk4 | Runge-Kutta 4th-order explicit method | Always available | + +---------------+-----------------------------------------+------------------------+ + | rkgeneric | Generic Runge Kutta explicit methods | Always available | + +---------------+-----------------------------------------+------------------------+ + | rk3ssp | 3rd-order Strong Stability Preserving | Always available | + +---------------+-----------------------------------------+------------------------+ + | splitrk | Split RK3-SSP and RK-Legendre | Always available | + +---------------+-----------------------------------------+------------------------+ + | pvode | 1998 PVODE with BDF method | Always available | + +---------------+-----------------------------------------+------------------------+ + | cvode | SUNDIALS CVODE. BDF and Adams methods | -DBOUT_USE_SUNDIALS=ON | + +---------------+-----------------------------------------+------------------------+ + | ida | SUNDIALS IDA. DAE solver | -DBOUT_USE_SUNDIALS=ON | + +---------------+-----------------------------------------+------------------------+ + | arkode | SUNDIALS ARKODE IMEX solver | -DBOUT_USE_SUNDIALS=ON | + +---------------+-----------------------------------------+------------------------+ + | petsc | PETSc TS methods | -DBOUT_USE_PETSC=ON | + +---------------+-----------------------------------------+------------------------+ + | imexbdf2 | IMEX-BDF2 scheme | -DBOUT_USE_PETSC=ON | + +---------------+-----------------------------------------+------------------------+ + | beuler / snes | Backward Euler with SNES solvers | -DBOUT_USE_PETSC=ON | + +---------------+-----------------------------------------+------------------------+ Each solver can have its own settings which work in slightly different ways, but some common settings and which solvers they are used in are diff --git a/src/bout++.cxx b/src/bout++.cxx index 52d8927edb..7d7b38b947 100644 --- a/src/bout++.cxx +++ b/src/bout++.cxx @@ -685,24 +685,33 @@ void setRunFinishInfo(Options& options) { void addBuildFlagsToOptions(Options& options) { output_progress << "Setting up output (experimental output) file\n"; - options["BOUT_VERSION"] = bout::version::as_double; - options["has_fftw"] = bout::build::has_fftw; - options["has_gettext"] = bout::build::has_gettext; - options["has_lapack"] = bout::build::has_lapack; - options["has_netcdf"] = bout::build::has_netcdf; - options["has_petsc"] = bout::build::has_petsc; - options["has_pretty_function"] = bout::build::has_pretty_function; - options["has_pvode"] = bout::build::has_pvode; - options["has_scorep"] = bout::build::has_scorep; - options["has_slepc"] = bout::build::has_slepc; - options["has_sundials"] = bout::build::has_sundials; - options["use_backtrace"] = bout::build::use_backtrace; - options["use_color"] = bout::build::use_color; - options["use_openmp"] = bout::build::use_openmp; - options["use_output_debug"] = bout::build::use_output_debug; - options["use_sigfpe"] = bout::build::use_sigfpe; - options["use_signal"] = bout::build::use_signal; - options["use_track"] = bout::build::use_track; + options["BOUT_VERSION"].force(bout::version::as_double); + options["use_check_level"].force(bout::build::check_level); + options["use_openmp_schedule"].force(bout::build::openmp_schedule); + options["has_fftw"].force(bout::build::has_fftw); + options["has_gettext"].force(bout::build::has_gettext); + options["has_lapack"].force(bout::build::has_lapack); + options["has_netcdf"].force(bout::build::has_netcdf); + options["has_petsc"].force(bout::build::has_petsc); + options["has_hypre"].force(bout::build::has_hypre); + options["has_umpire"].force(bout::build::has_umpire); + options["has_caliper"].force(bout::build::has_caliper); + options["has_raja"].force(bout::build::has_raja); + options["has_pretty_function"].force(bout::build::has_pretty_function); + options["has_pvode"].force(bout::build::has_pvode); + options["has_scorep"].force(bout::build::has_scorep); + options["has_slepc"].force(bout::build::has_slepc); + options["has_sundials"].force(bout::build::has_sundials); + options["use_backtrace"].force(bout::build::use_backtrace); + options["use_color"].force(bout::build::use_color); + options["use_openmp"].force(bout::build::use_openmp); + options["use_output_debug"].force(bout::build::use_output_debug); + options["use_sigfpe"].force(bout::build::use_sigfpe); + options["use_signal"].force(bout::build::use_signal); + options["use_track"].force(bout::build::use_track); + options["has_cuda"].force(bout::build::has_cuda); + options["use_metric_3d"].force(bout::build::use_metric_3d); + options["use_msgstack"].force(bout::build::use_msgstack); } void writeSettingsFile(Options& options, const std::string& data_dir, diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index 439022e9bb..c1bc616bb1 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -1199,7 +1199,8 @@ const Field2D LaplaceXY::solve(const Field2D& rhs, const Field2D& x0) { KSPGetConvergedReason(ksp, &reason); if (reason <= 0) { - throw BoutException("LaplaceXY failed to converge. Reason {:d}", reason); + throw BoutException("LaplaceXY failed to converge. Reason {} ({:d})", + KSPConvergedReasons[reason], static_cast(reason)); } if (save_performance) { diff --git a/src/invert/laplacexy2/laplacexy2.cxx b/src/invert/laplacexy2/laplacexy2.cxx index dc7a4afa7f..8b5e98d747 100644 --- a/src/invert/laplacexy2/laplacexy2.cxx +++ b/src/invert/laplacexy2/laplacexy2.cxx @@ -383,7 +383,8 @@ Field2D LaplaceXY2::solve(const Field2D& rhs, const Field2D& x0) { KSPGetConvergedReason(ksp, &reason); if (reason <= 0) { - throw BoutException("LaplaceXY2 failed to converge. Reason {:d}", reason); + throw BoutException("LaplaceXY2 failed to converge. Reason {} ({:d})", + KSPConvergedReasons[reason], static_cast(reason)); } // Convert result into a Field2D diff --git a/src/invert/laplacexy2/laplacexy2_hypre.cxx b/src/invert/laplacexy2/laplacexy2_hypre.cxx index b6154d1222..b18903be3a 100644 --- a/src/invert/laplacexy2/laplacexy2_hypre.cxx +++ b/src/invert/laplacexy2/laplacexy2_hypre.cxx @@ -12,7 +12,7 @@ #include -#if BOUT_USE_CUDA && defined(__CUDACC__) +#if BOUT_HAS_CUDA && defined(__CUDACC__) #define gpuErrchk(ans) \ { gpuAssert((ans), __FILE__, __LINE__); } inline void gpuAssert(cudaError_t code, const char* file, int line, bool abort = true) { diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index ff28f6d51a..8ddb058ab2 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -942,7 +942,8 @@ Field3D LaplaceXZpetsc::solve(const Field3D& bin, const Field3D& x0in) { KSPGetConvergedReason(it.ksp, &reason); if (reason <= 0) { - throw BoutException("LaplaceXZ failed to converge. Reason {:d}", reason); + throw BoutException("LaplaceXZ failed to converge. Reason {} ({:d})", + KSPConvergedReasons[reason], static_cast(reason)); } ////////////////////////// diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index c6092eab14..25d623aad8 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -478,18 +478,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) g23 = getUnalignedAtLocation(g23, "g23", 0.0); // Check input metrics - // Diagonal metric components should be finite - bout::checkFinite(g11, "g11", "RGN_NOCORNERS"); - bout::checkFinite(g22, "g22", "RGN_NOCORNERS"); - bout::checkFinite(g33, "g33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g11, "g11", "RGN_NOCORNERS"); - bout::checkPositive(g22, "g22", "RGN_NOCORNERS"); - bout::checkPositive(g33, "g33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g12, "g12", "RGN_NOCORNERS"); - bout::checkFinite(g13, "g13", "RGN_NOCORNERS"); - bout::checkFinite(g23, "g23", "RGN_NOCORNERS"); + checkContravariant(); /// Find covariant metric components auto covariant_component_names = {"g_11", "g_22", "g_33", "g_12", "g_13", "g_23"}; @@ -542,18 +531,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) transform.get()); // Check covariant metrics - // Diagonal metric components should be finite - bout::checkFinite(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkFinite(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkFinite(g_33, "g_33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkPositive(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkPositive(g_33, "g_33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g_12, "g_12", "RGN_NOCORNERS"); - bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); - bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); + checkCovariant(); /// Calculate Jacobian and Bxy if (jacobian()) { @@ -702,18 +680,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, extrapolate_y, false, transform.get()); // Check input metrics - // Diagonal metric components should be finite - bout::checkFinite(g11, "g11", "RGN_NOCORNERS"); - bout::checkFinite(g22, "g22", "RGN_NOCORNERS"); - bout::checkFinite(g33, "g33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g11, "g11", "RGN_NOCORNERS"); - bout::checkPositive(g22, "g22", "RGN_NOCORNERS"); - bout::checkPositive(g33, "g33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g12, "g12", "RGN_NOCORNERS"); - bout::checkFinite(g13, "g13", "RGN_NOCORNERS"); - bout::checkFinite(g23, "g23", "RGN_NOCORNERS"); + checkContravariant(); /// Find covariant metric components auto covariant_component_names = {"g_11", "g_22", "g_33", "g_12", "g_13", "g_23"}; @@ -769,18 +736,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, transform.get()); // Check covariant metrics - // Diagonal metric components should be finite - bout::checkFinite(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkFinite(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkFinite(g_33, "g_33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkPositive(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkPositive(g_33, "g_33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g_12, "g_12", "RGN_NOCORNERS"); - bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); - bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); + checkCovariant(); /// Calculate Jacobian and Bxy if (jacobian()) { @@ -912,27 +868,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, transform.get()); // Check input metrics - // Diagonal metric components should be finite - bout::checkFinite(g11, "g11", "RGN_NOCORNERS"); - bout::checkFinite(g22, "g22", "RGN_NOCORNERS"); - bout::checkFinite(g33, "g33", "RGN_NOCORNERS"); - bout::checkFinite(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkFinite(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkFinite(g_33, "g_33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g11, "g11", "RGN_NOCORNERS"); - bout::checkPositive(g22, "g22", "RGN_NOCORNERS"); - bout::checkPositive(g33, "g33", "RGN_NOCORNERS"); - bout::checkPositive(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkPositive(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkPositive(g_33, "g_33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g12, "g12", "RGN_NOCORNERS"); - bout::checkFinite(g13, "g13", "RGN_NOCORNERS"); - bout::checkFinite(g23, "g23", "RGN_NOCORNERS"); - bout::checkFinite(g_12, "g_12", "RGN_NOCORNERS"); - bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); - bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); + checkContravariant(); + checkCovariant(); J = interpolateAndExtrapolate(coords_in->J, location, true, true, false, transform.get()); @@ -1023,31 +960,8 @@ int Coordinates::geometry(bool recalculate_staggered, } // Check input metrics - // Diagonal metric components should be finite - bout::checkFinite(g11, "g11", "RGN_NOCORNERS"); - bout::checkFinite(g22, "g22", "RGN_NOCORNERS"); - bout::checkFinite(g33, "g33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g11, "g11", "RGN_NOCORNERS"); - bout::checkPositive(g22, "g22", "RGN_NOCORNERS"); - bout::checkPositive(g33, "g33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g12, "g12", "RGN_NOCORNERS"); - bout::checkFinite(g13, "g13", "RGN_NOCORNERS"); - bout::checkFinite(g23, "g23", "RGN_NOCORNERS"); - - // Diagonal metric components should be finite - bout::checkFinite(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkFinite(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkFinite(g_33, "g_33", "RGN_NOCORNERS"); - // Diagonal metric components should be positive - bout::checkPositive(g_11, "g_11", "RGN_NOCORNERS"); - bout::checkPositive(g_22, "g_22", "RGN_NOCORNERS"); - bout::checkPositive(g_33, "g_33", "RGN_NOCORNERS"); - // Off-diagonal metric components should be finite - bout::checkFinite(g_12, "g_12", "RGN_NOCORNERS"); - bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); - bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); + checkContravariant(); + checkCovariant(); // Calculate Christoffel symbol terms (18 independent values) // Note: This calculation is completely general: metric @@ -1289,6 +1203,8 @@ int Coordinates::geometry(bool recalculate_staggered, // Invalidate and recalculate cached variables zlength_cache.reset(); + Grad2_par2_DDY_invSgCache.clear(); + invSgCache.reset(); return 0; } @@ -1575,13 +1491,13 @@ Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, const std::string& m Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, const std::string& method, - const std::string& region) { + const std::string& region) const { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDY(f, loc, method, region) / dy; } Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, - const std::string& region) { + const std::string& region) const { #if BOUT_USE_METRIC_3D if (!f.hasParallelSlices() and !transform->canToFromFieldAligned()) { Field3D f_parallel = f; @@ -1618,7 +1534,7 @@ Coordinates::FieldMetric Coordinates::Grad_par(const Field2D& var, ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == var.getLocation())); - return DDY(var) / sqrt(g_22); + return DDY(var) * invSg(); } Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, @@ -1626,7 +1542,7 @@ Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, TRACE("Coordinates::Grad_par( Field3D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); - return ::DDY(var, outloc, method) / sqrt(g_22); + return ::DDY(var, outloc, method) * invSg(); } ///////////////////////////////////////////////////////// @@ -1637,13 +1553,15 @@ Coordinates::FieldMetric Coordinates::Vpar_Grad_par(const Field2D& v, const Fiel MAYBE_UNUSED(CELL_LOC outloc), const std::string& UNUSED(method)) { ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); - return VDDY(v, f) / sqrt(g_22); + + return VDDY(v, f) * invSg(); } Field3D Coordinates::Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, const std::string& method) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); - return VDDY(v, f, outloc, method) / sqrt(g_22); + + return VDDY(v, f, outloc, method) * invSg(); } ///////////////////////////////////////////////////////// @@ -1680,8 +1598,8 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, Field3D f_B = f / Bxy_floc; f_B.splitParallelSlices(); for (int i = 0; i < f.getMesh()->ystart; ++i) { - f_B.yup(i) = f.yup(i) / Bxy_floc; - f_B.ydown(i) = f.ydown(i) / Bxy_floc; + f_B.yup(i) = f.yup(i) / Bxy_floc.yup(i); + f_B.ydown(i) = f.ydown(i) / Bxy_floc.ydown(i); } return Bxy * Grad_par(f_B, outloc, method); } @@ -1695,10 +1613,7 @@ Coordinates::FieldMetric Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outl TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); - auto invSg = 1.0 / sqrt(g_22); - // Communicate to get parallel slices - localmesh->communicate(invSg); - auto result = DDY(invSg, outloc, method) * DDY(f, outloc, method) * invSg + auto result = Grad2_par2_DDY_invSg(outloc, method) * DDY(f, outloc, method) + D2DY2(f, outloc, method) / g_22; return result; @@ -1712,16 +1627,11 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, } ASSERT1(location == outloc); - auto invSg = 1.0 / sqrt(g_22); - // Communicate to get parallel slices - localmesh->communicate(invSg); - auto sg = DDY(invSg, outloc, method) * invSg; - Field3D result = ::DDY(f, outloc, method); Field3D r2 = D2DY2(f, outloc, method) / g_22; - result = sg * result + r2; + result = Grad2_par2_DDY_invSg(outloc, method) * result + r2; ASSERT2(result.getLocation() == outloc); @@ -1978,3 +1888,135 @@ Field2D Coordinates::Laplace_perpXY(MAYBE_UNUSED(const Field2D& A), throw BoutException("Coordinates::Laplace_perpXY for 3D metric not implemented"); #endif } + +const Coordinates::FieldMetric& Coordinates::invSg() const { + if (invSgCache == nullptr) { + auto ptr = std::make_unique(); + (*ptr) = 1.0 / sqrt(g_22); + invSgCache = std::move(ptr); + } + return *invSgCache; +} + +const Coordinates::FieldMetric& +Coordinates::Grad2_par2_DDY_invSg(CELL_LOC outloc, const std::string& method) const { + if (auto search = Grad2_par2_DDY_invSgCache.find(method); + search != Grad2_par2_DDY_invSgCache.end()) { + return *search->second; + } + invSg(); + + // Communicate to get parallel slices + localmesh->communicate(*invSgCache); + invSgCache->applyParallelBoundary("parallel_neumann"); + + // cache + auto ptr = std::make_unique(); + *ptr = DDY(*invSgCache, outloc, method) * invSg(); + Grad2_par2_DDY_invSgCache[method] = std::move(ptr); + return *Grad2_par2_DDY_invSgCache[method]; +} + +void Coordinates::checkCovariant() { + // Diagonal metric components should be finite + bout::checkFinite(g_11, "g_11", "RGN_NOCORNERS"); + bout::checkFinite(g_22, "g_22", "RGN_NOCORNERS"); + bout::checkFinite(g_33, "g_33", "RGN_NOCORNERS"); + if (g_11.hasParallelSlices() && &g_11.ynext(1) != &g_11) { + for (int dy = 1; dy <= localmesh->ystart; ++dy) { + for (const auto sign : {1, -1}) { + bout::checkFinite(g_11.ynext(sign * dy), "g_11.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g_22.ynext(sign * dy), "g_22.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g_33.ynext(sign * dy), "g_33.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + } + } + } + // Diagonal metric components should be positive + bout::checkPositive(g_11, "g_11", "RGN_NOCORNERS"); + bout::checkPositive(g_22, "g_22", "RGN_NOCORNERS"); + bout::checkPositive(g_33, "g_33", "RGN_NOCORNERS"); + if (g_11.hasParallelSlices() && &g_11.ynext(1) != &g_11) { + for (int dy = 1; dy <= localmesh->ystart; ++dy) { + for (const auto sign : {1, -1}) { + bout::checkPositive(g_11.ynext(sign * dy), "g_11.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkPositive(g_22.ynext(sign * dy), "g_22.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkPositive(g_33.ynext(sign * dy), "g_33.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + } + } + } + + // Off-diagonal metric components should be finite + bout::checkFinite(g_12, "g_12", "RGN_NOCORNERS"); + bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); + bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); + if (g_23.hasParallelSlices() && &g_23.ynext(1) != &g_23) { + for (int dy = 1; dy <= localmesh->ystart; ++dy) { + for (const auto sign : {1, -1}) { + bout::checkFinite(g_12.ynext(sign * dy), "g_12.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g_13.ynext(sign * dy), "g_13.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g_23.ynext(sign * dy), "g_23.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + } + } + } +} + +void Coordinates::checkContravariant() { + // Diagonal metric components should be finite + bout::checkFinite(g11, "g11", "RGN_NOCORNERS"); + bout::checkFinite(g22, "g22", "RGN_NOCORNERS"); + bout::checkFinite(g33, "g33", "RGN_NOCORNERS"); + if (g11.hasParallelSlices() && &g11.ynext(1) != &g11) { + for (int dy = 1; dy <= localmesh->ystart; ++dy) { + for (const auto sign : {1, -1}) { + bout::checkFinite(g11.ynext(sign * dy), "g11.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g22.ynext(sign * dy), "g22.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g33.ynext(sign * dy), "g33.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + } + } + } + // Diagonal metric components should be positive + bout::checkPositive(g11, "g11", "RGN_NOCORNERS"); + bout::checkPositive(g22, "g22", "RGN_NOCORNERS"); + bout::checkPositive(g33, "g33", "RGN_NOCORNERS"); + if (g11.hasParallelSlices() && &g11.ynext(1) != &g11) { + for (int dy = 1; dy <= localmesh->ystart; ++dy) { + for (const auto sign : {1, -1}) { + bout::checkPositive(g11.ynext(sign * dy), "g11.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkPositive(g22.ynext(sign * dy), "g22.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkPositive(g33.ynext(sign * dy), "g33.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + } + } + } + + // Off-diagonal metric components should be finite + bout::checkFinite(g12, "g12", "RGN_NOCORNERS"); + bout::checkFinite(g13, "g13", "RGN_NOCORNERS"); + bout::checkFinite(g23, "g23", "RGN_NOCORNERS"); + if (g23.hasParallelSlices() && &g23.ynext(1) != &g23) { + for (int dy = 1; dy <= localmesh->ystart; ++dy) { + for (const auto sign : {1, -1}) { + bout::checkFinite(g12.ynext(sign * dy), "g12.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g13.ynext(sign * dy), "g13.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + bout::checkFinite(g23.ynext(sign * dy), "g23.ynext", + fmt::format("RGN_YPAR_{:+d}", sign * dy)); + } + } + } +} diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 37201b2d81..0a5d5f9624 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -1,10 +1,24 @@ - #include #include #include +#include #include -#include +namespace { +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); +} +} // namespace namespace FV { @@ -49,54 +63,9 @@ Field3D Div_a_Grad_perp(const Field3D& a, const Field3D& f) { } } - // Y and Z fluxes require Y derivatives - - // Fields containing values along the magnetic field - Field3D fup(mesh), fdown(mesh); - Field3D aup(mesh), adown(mesh); - - Field3D g23up(mesh), g23down(mesh); - Field3D g_23up(mesh), g_23down(mesh); - Field3D Jup(mesh), Jdown(mesh); - Field3D dyup(mesh), dydown(mesh); - Field3D dzup(mesh), dzdown(mesh); - Field3D Bxyup(mesh), Bxydown(mesh); - - // Values on this y slice (centre). - // This is needed because toFieldAligned may modify the field - Field3D fc = f; - Field3D ac = a; - - Field3D g23c = coord->g23; - Field3D g_23c = coord->g_23; - Field3D Jc = coord->J; - Field3D dyc = coord->dy; - Field3D dzc = coord->dz; - Field3D Bxyc = coord->Bxy; - - // Result of the Y and Z fluxes - Field3D yzresult(mesh); - yzresult.allocate(); - - if (f.hasParallelSlices() && a.hasParallelSlices()) { - // Both inputs have yup and ydown - - fup = f.yup(); - fdown = f.ydown(); - - aup = a.yup(); - adown = a.ydown(); - } else { - // At least one input doesn't have yup/ydown fields. - // Need to shift to/from field aligned coordinates - - fup = fdown = fc = toFieldAligned(f); - aup = adown = ac = toFieldAligned(a); - - yzresult.setDirectionY(YDirectionType::Aligned); - } + const bool fci = f.hasParallelSlices() && a.hasParallelSlices(); - if (bout::build::use_metric_3d) { + if (bout::build::use_metric_3d and fci) { // 3D Metric, need yup/ydown fields. // Requires previous communication of metrics // -- should insert communication here? @@ -105,118 +74,103 @@ Field3D Div_a_Grad_perp(const Field3D& a, const Field3D& f) { || !coord->Bxy.hasParallelSlices() || !coord->J.hasParallelSlices()) { throw BoutException("metrics have no yup/down: Maybe communicate in init?"); } + } - g23up = coord->g23.yup(); - g23down = coord->g23.ydown(); - - g_23up = coord->g_23.yup(); - g_23down = coord->g_23.ydown(); - - Jup = coord->J.yup(); - Jdown = coord->J.ydown(); - - dyup = coord->dy.yup(); - dydown = coord->dy.ydown(); + // Y and Z fluxes require Y derivatives - dzup = coord->dz.yup(); - dzdown = coord->dz.ydown(); + // Fields containing values along the magnetic field - Bxyup = coord->Bxy.yup(); - Bxydown = coord->Bxy.ydown(); + // 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); + + // Only in 3D case with FCI do the metrics have parallel slices + const bool metric_fci = fci and bout::build::use_metric_3d; + 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); - } else { - // No 3D metrics - // Need to shift to/from field aligned coordinates - g23up = g23down = g23c = toFieldAligned(coord->g23); - g_23up = g_23down = g_23c = toFieldAligned(coord->g_23); - Jup = Jdown = Jc = toFieldAligned(coord->J); - dyup = dydown = dyc = toFieldAligned(coord->dy); - dzup = dzdown = dzc = toFieldAligned(coord->dz); - Bxyup = Bxydown = Bxyc = toFieldAligned(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++) { - for (int k = 0; k < mesh->LocalNz; k++) { - // Calculate flux between j and j+1 - int kp = (k + 1) % mesh->LocalNz; - int km = (k - 1 + mesh->LocalNz) % mesh->LocalNz; - - BoutReal coef = - 0.5 - * (g_23c(i, j, k) / SQ(Jc(i, j, k) * Bxyc(i, j, k)) - + g_23up(i, j + 1, k) / SQ(Jup(i, j + 1, k) * Bxyup(i, j + 1, k))); - - // Calculate Z derivative at y boundary - BoutReal dfdz = - 0.5 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) - / (dzc(i, j, k) + dzup(i, j + 1, k)); - - // Y derivative - BoutReal dfdy = - 2. * (fup(i, j + 1, k) - fc(i, j, k)) / (dyup(i, j + 1, k) + dyc(i, j, k)); - - BoutReal fout = - 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) - * (Jc(i, j, k) * g23c(i, j, k) + Jup(i, j + 1, k) * g23up(i, j + 1, k)) - * (dfdz - coef * dfdy); - - yzresult(i, j, k) = fout / (dyc(i, j, k) * Jc(i, j, k)); - - // Calculate flux between j and j-1 - coef = - 0.5 - * (g_23c(i, j, k) / SQ(Jc(i, j, k) * Bxyc(i, j, k)) - + g_23down(i, j - 1, k) / SQ(Jdown(i, j - 1, k) * Bxydown(i, j - 1, k))); - - dfdz = 0.5 - * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) - / (dzc(i, j, k) + dzdown(i, j - 1, k)); - - dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) - / (dyc(i, j, k) + dydown(i, j - 1, k)); - - fout = 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) - * (Jc(i, j, k) * g23c(i, j, k) + Jdown(i, j - 1, k) * g23down(i, j - 1, k)) - * (dfdz - coef * dfdy); - - yzresult(i, j, k) -= fout / (dyc(i, j, k) * Jc(i, j, k)); - } + BOUT_FOR(i, yzresult.getRegion("RGN_NOBNDRY")) { + auto ikp = i.zp(); + auto ikm = i.zm(); + { + const BoutReal coef = 0.5 + * (g_23.c[i] / SQ(J.c[i] * Bxy.c[i]) + + g_23.up[i.yp()] / SQ(J.up[i.yp()] * Bxy.up[i.yp()])); + + // Calculate Z derivative at y boundary + const BoutReal dfdz = 0.5 + * (f_slice.c[ikp] - f_slice.c[ikm] + f_slice.up[ikp.yp()] + - f_slice.up[ikm.yp()]) + / (dz.c[i] + dz.up[i.yp()]); + + // Y derivative + const BoutReal dfdy = + 2. * (f_slice.up[i.yp()] - f_slice.c[i]) / (dy.up[i.yp()] + dy.c[i]); + + const BoutReal fout = 0.25 * (a_slice.c[i] + a_slice.up[i.yp()]) + * (J.c[i] * g23.c[i] + J.up[i.yp()] * g23.up[i.yp()]) + * (dfdz - coef * dfdy); + + yzresult[i] += fout / (dy.c[i] * J.c[i]); } - } - - // Z flux - - for (int i = mesh->xstart; i <= mesh->xend; i++) { - for (int j = mesh->ystart; j <= mesh->yend; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - // Calculate flux between k and k+1 - int kp = (k + 1) % mesh->LocalNz; - - // Coefficient in front of df/dy term - BoutReal coef = g_23c(i, j, k) - / (dyup(i, j + 1, k) + 2. * dyc(i, j, k) + dydown(i, j - 1, k)) - / SQ(Jc(i, j, k) * Bxyc(i, j, k)); - - BoutReal fout = - 0.25 * (ac(i, j, k) + ac(i, j, kp)) - * (Jc(i, j, k) * coord->g33(i, j, k) + Jc(i, j, kp) * coord->g33(i, j, kp)) - * ( // df/dz - (fc(i, j, kp) - fc(i, j, k)) / dzc(i, j, k) - // - g_yz * df/dy / SQ(J*B) - - coef - * (fup(i, j + 1, k) + fup(i, j + 1, kp) - fdown(i, j - 1, k) - - fdown(i, j - 1, kp))); - - yzresult(i, j, k) += fout / (Jc(i, j, k) * dzc(i, j, k)); - yzresult(i, j, kp) -= fout / (Jc(i, j, kp) * dzc(i, j, kp)); - } + { + // Calculate flux between j and j-1 + const BoutReal coef = + 0.5 + * (g_23.c[i] / SQ(J.c[i] * Bxy.c[i]) + + g_23.down[i.ym()] / SQ(J.down[i.ym()] * Bxy.down[i.ym()])); + + const BoutReal dfdz = 0.5 + * (f_slice.c[ikp] - f_slice.c[ikm] + f_slice.down[ikp.ym()] + - f_slice.down[ikm.ym()]) + / (dz.c[i] + dz.down[i.ym()]); + + const BoutReal dfdy = + 2. * (f_slice.c[i] - f_slice.down[i.ym()]) / (dy.c[i] + dy.down[i.ym()]); + + const BoutReal fout = 0.25 * (a_slice.c[i] + a_slice.down[i.ym()]) + * (J.c[i] * g23.c[i] + J.down[i.ym()] * g23.down[i.ym()]) + * (dfdz - coef * dfdy); + + yzresult[i] -= fout / (dy.c[i] * J.c[i]); + } + // Z flux + { + + // Coefficient in front of df/dy term + const BoutReal coef = g_23.c[i] / (dy.up[i.yp()] + 2. * dy.c[i] + dy.down[i.ym()]) + / SQ(J.c[i] * Bxy.c[i]); + + const BoutReal fout = + 0.25 * (a_slice.c[i] + a_slice.c[ikp]) + * (J.c[i] * coord->g33[i] + J.c[ikp] * coord->g33[ikp]) + * ( // df/dz + (f_slice.c[ikp] - f_slice.c[i]) / dz.c[i] + // - g_yz * df/dy / SQ(J*B) + - coef + * (f_slice.up[i.yp()] + f_slice.up[ikp.yp()] - f_slice.down[i.ym()] + - f_slice.down[ikp.ym()])); + + yzresult[i] += fout / (J.c[i] * dz.c[i]); + yzresult[ikp] -= fout / (J.c[ikp] * dz.c[ikp]); } } + // Check if we need to transform back - if (f.hasParallelSlices() && a.hasParallelSlices()) { + if (fci) { result += yzresult; } else { result += fromFieldAligned(yzresult); diff --git a/src/mesh/interpolation/hermite_spline_xz.cxx b/src/mesh/interpolation/hermite_spline_xz.cxx index b303ecbbea..029edb61ff 100644 --- a/src/mesh/interpolation/hermite_spline_xz.cxx +++ b/src/mesh/interpolation/hermite_spline_xz.cxx @@ -55,6 +55,7 @@ XZHermiteSpline::XZHermiteSpline(int y_offset, Mesh* mesh) void XZHermiteSpline::calcWeights(const Field3D& delta_x, const Field3D& delta_z, const std::string& region) { + const int ncz = localmesh->LocalNz; BOUT_FOR(i, delta_x.getRegion(region)) { const int x = i.x(); const int y = i.y(); @@ -84,6 +85,8 @@ void XZHermiteSpline::calcWeights(const Field3D& delta_x, const Field3D& delta_z t_x = 0.0; } + k_corner(x, y, z) = ((k_corner(x, y, z) % ncz) + ncz) % ncz; + // Check that t_x and t_z are in range if ((t_x < 0.0) || (t_x > 1.0)) { throw BoutException( @@ -136,7 +139,7 @@ void XZHermiteSpline::calcWeights(const Field3D& delta_x, const Field3D& delta_z std::vector XZHermiteSpline::getWeightsForYApproximation(int i, int j, int k, int yoffset) { const int ncz = localmesh->LocalNz; - const int k_mod = ((k_corner(i, j, k) % ncz) + ncz) % ncz; + const int k_mod = k_corner(i, j, k); const int k_mod_m1 = (k_mod > 0) ? (k_mod - 1) : (ncz - 1); const int k_mod_p1 = (k_mod + 1) % ncz; const int k_mod_p2 = (k_mod + 2) % ncz; @@ -187,9 +190,8 @@ Field3D XZHermiteSpline::interpolate(const Field3D& f, const std::string& region // Due to lack of guard cells in z-direction, we need to ensure z-index // wraps around - const int ncz = localmesh->LocalNz; - const int z_mod = ((k_corner(x, y, z) % ncz) + ncz) % ncz; - const int z_mod_p1 = (z_mod + 1) % ncz; + const int z_mod = k_corner(x, y, z); + const int z_mod_p1 = (z_mod + 1) % localmesh->LocalNz; const int y_next = y + y_offset; diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index b1b81b7635..d03bd688fd 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -123,7 +123,7 @@ public: throw BoutException("FCI method cannot transform from field aligned grid"); } - bool canToFromFieldAligned() override { return false; } + bool canToFromFieldAligned() const override { return false; } bool requiresTwistShift(bool UNUSED(twist_shift_enabled), MAYBE_UNUSED(YDirectionType ytype)) override { diff --git a/src/mesh/parallel/shiftedmetricinterp.hxx b/src/mesh/parallel/shiftedmetricinterp.hxx index 56c4ffff54..86ecfac853 100644 --- a/src/mesh/parallel/shiftedmetricinterp.hxx +++ b/src/mesh/parallel/shiftedmetricinterp.hxx @@ -75,7 +75,7 @@ public: throw BoutException("Not implemented yet"); } - bool canToFromFieldAligned() override { return true; } + bool canToFromFieldAligned() const override { return true; } std::vector getWeightsForYUpApproximation(int i, int j, int k) override { diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index 425c3e0073..11954d331a 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -1240,7 +1240,7 @@ PetscErrorCode IMEXBDF2::solve_implicit(BoutReal curtime, BoutReal gamma) { if (verbose) { output << "SNES failed to converge with reason " << reason << endl; } - throw BoutException("SNES failed to converge. Reason: {:d}\n", reason); + throw PetscLib::SNESFailure(snesUse); } int its; diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index db878cdb75..2143aad96a 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -770,7 +770,7 @@ int SNESSolver::run() { // Print diagnostics to help identify source of the problem output.write("\n======== SNES failed =========\n"); - output.write("\nReturn code: {}, reason: {}\n", ierr, reason); + output.write("\nReturn code: {}, reason: {}\n", ierr, static_cast(reason)); for (const auto& f : f2d) { output.write( "{} : ({} -> {}), ddt: ({} -> {})\n", f.name, @@ -866,7 +866,7 @@ int SNESSolver::run() { output.print("\r"); // Carriage return for printing to screen output.write("Time: {}, timestep: {}, nl iter: {}, lin iter: {}, reason: {}", - simtime, timestep, nl_its, lin_its, reason); + simtime, timestep, nl_its, lin_its, static_cast(reason)); if (snes_failures > 0) { output.write(", SNES failures: {}", snes_failures); snes_failures = 0; diff --git a/src/solver/solver.cxx b/src/solver/solver.cxx index 40551da607..9dd31f011e 100644 --- a/src/solver/solver.cxx +++ b/src/solver/solver.cxx @@ -725,15 +725,23 @@ void Solver::outputVars(Options& output_options, bool save_repeat) { void Solver::readEvolvingVariablesFromOptions(Options& options) { run_id = options["run_id"].withDefault(default_run_id); simtime = options["tt"].as(); - iteration = options["hist_hi"].as(); + iteration = options["hist_hi"].withDefault(0); for (auto& f : f2d) { - *(f.var) = options[f.name].as(); + if (options.isSet(f.name)) { + *(f.var) = options[f.name].as(); + } else { + output_warn.write("Restart does not contain Field2D '{}' => Initialising", f.name); + } } for (const auto& f : f3d) { - *(f.var) = options[f.name].as(); - if (mms) { - *(f.MMS_err) = options["E_" + f.name].as(); + if (options.isSet(f.name)) { + *(f.var) = options[f.name].as(); + if (mms) { + *(f.MMS_err) = options["E_" + f.name].as(); + } + } else { + output_warn.write("Restart does not contain Field3D '{}' => Initialising", f.name); } } } diff --git a/src/sys/hyprelib.cxx b/src/sys/hyprelib.cxx index d6b1c95468..e833162726 100644 --- a/src/sys/hyprelib.cxx +++ b/src/sys/hyprelib.cxx @@ -18,7 +18,7 @@ namespace bout { // Define all the static member variables int HypreLib::count = 0; -#if BOUT_USE_CUDA +#if BOUT_HAS_CUDA static constexpr auto BOUT_HYPRE_EXEC = HYPRE_EXEC_DEVICE; static constexpr auto BOUT_HYPRE_MEMORY = HYPRE_MEMORY_DEVICE; #else diff --git a/src/sys/petsclib.cxx b/src/sys/petsclib.cxx index f1ced63a21..b99c51320c 100644 --- a/src/sys/petsclib.cxx +++ b/src/sys/petsclib.cxx @@ -5,9 +5,10 @@ #include "bout/boutcomm.hxx" #include "bout/openmpwrap.hxx" #include "bout/options.hxx" +#include #include -#include +#include "petscsnes.h" // Define all the static member variables int PetscLib::count = 0; @@ -68,27 +69,15 @@ PetscLib::~PetscLib() { } void PetscLib::setOptionsFromInputFile(KSP& ksp) { - auto ierr = KSPSetOptionsPrefix(ksp, options_prefix.c_str()); - if (ierr) { - throw BoutException("KSPSetOptionsPrefix failed with error {}", ierr); - } + assertIerr(KSPSetOptionsPrefix(ksp, options_prefix.c_str()), "KSPSetOptionsPrefix"); - ierr = KSPSetFromOptions(ksp); - if (ierr) { - throw BoutException("KSPSetFromOptions failed with error {}", ierr); - } + assertIerr(KSPSetFromOptions(ksp), "KSPSetFromOptions"); } void PetscLib::setOptionsFromInputFile(SNES& snes) { - auto ierr = SNESSetOptionsPrefix(snes, options_prefix.c_str()); - if (ierr) { - throw BoutException("SNESSetOptionsPrefix failed with error %i", ierr); - } + BOUT_DO_PETSC(SNESSetOptionsPrefix(snes, options_prefix.c_str())); - ierr = SNESSetFromOptions(snes); - if (ierr) { - throw BoutException("SNESSetFromOptions failed with error %i", ierr); - } + BOUT_DO_PETSC(SNESSetFromOptions(snes)); } void PetscLib::cleanup() { @@ -135,4 +124,17 @@ void PetscLib::setPetscOptions(Options& options, const std::string& prefix) { } } } + +BoutException PetscLib::SNESFailure(SNES& snes) { + SNESConvergedReason reason; + BOUT_DO_PETSC(SNESGetConvergedReason(snes, &reason)); +#if PETSC_VERSION_GE(3, 15, 0) + const char* message; + BOUT_DO_PETSC(SNESGetConvergedReasonString(snes, &message)); +#else + const char* message{""}; +#endif + return BoutException("SNES failed to converge. Reason: {} ({:d})", message, + static_cast(reason)); +} #endif // BOUT_HAS_PETSC diff --git a/tests/MMS/GBS/gbs.cxx b/tests/MMS/GBS/gbs.cxx index f0b834d823..d0d1fcb039 100644 --- a/tests/MMS/GBS/gbs.cxx +++ b/tests/MMS/GBS/gbs.cxx @@ -25,8 +25,9 @@ int GBS::init(bool restarting) { // Switches in model section Options* optgbs = opt->getSection("GBS"); OPTION(optgbs, ionvis, false); - if (ionvis) - OPTION(optgbs, Ti, 10); // Ion temperature [eV] + if (ionvis) { + OPTION(optgbs, Ti, 10); // Ion temperature [eV] + } OPTION(optgbs, elecvis, false); // Include electron viscosity? OPTION(optgbs, resistivity, true); // Include resistivity? OPTION(optgbs, estatic, true); // Electrostatic? @@ -62,12 +63,15 @@ int GBS::init(bool restarting) { OPTION(opt->getSection("solver"), mms, false); - if (ionvis) + if (ionvis) { SAVE_REPEAT(Gi); - if (elecvis) + } + if (elecvis) { SAVE_REPEAT(Ge); - if (resistivity) + } + if (resistivity) { SAVE_REPEAT(nu); + } // Normalisation OPTION(optgbs, Tnorm, 100); // Reference temperature [eV] @@ -340,8 +344,9 @@ void GBS::LoadMetric(BoutReal Lnorm, BoutReal Bnorm) { } BoutReal sbp = 1.0; // Sign of Bp - if (min(Bpxy, true) < 0.0) + if (min(Bpxy, true) < 0.0) { sbp = -1.0; + } coords->g11 = SQ(Rxy * Bpxy); coords->g22 = 1.0 / SQ(hthe); @@ -527,14 +532,16 @@ const Field3D GBS::C(const Field3D& f) { // Curvature operator } const Field3D GBS::D(const Field3D& f, BoutReal d) { // Diffusion operator - if (d < 0.0) + if (d < 0.0) { return 0.0; + } return d * Delp2(f); } const Field3D GBS::H(const Field3D& f, BoutReal h) { // Numerical hyper-diffusion operator - if (h < 0.0) + if (h < 0.0) { return 0.0; + } return -h * (dx4 * D4DX4(f) + dz4 * D4DZ4(f)); // + dy4*D4DY4(f) } diff --git a/tests/MMS/diffusion2/diffusion.cxx b/tests/MMS/diffusion2/diffusion.cxx index 2c13fb4f69..bd2cd72a08 100644 --- a/tests/MMS/diffusion2/diffusion.cxx +++ b/tests/MMS/diffusion2/diffusion.cxx @@ -64,14 +64,17 @@ class Diffusion : public PhysicsModel { ddt(N) = 0.0; - if (Dx > 0.0) + if (Dx > 0.0) { ddt(N) += Dx * D2DX2(N); + } - if (Dy > 0.0) + if (Dy > 0.0) { ddt(N) += Dy * D2DY2(N); + } - if (Dz > 0.0) + if (Dz > 0.0) { ddt(N) += Dz * D2DZ2(N); + } return 0; } diff --git a/tests/MMS/elm-pb/elm_pb.cxx b/tests/MMS/elm-pb/elm_pb.cxx index 05e993531b..3ad8f70b85 100644 --- a/tests/MMS/elm-pb/elm_pb.cxx +++ b/tests/MMS/elm-pb/elm_pb.cxx @@ -293,11 +293,13 @@ class ELMpb : public PhysicsModel { OPTION(globalOptions->getSection("solver"), mms, false); - if (!include_curvature) + if (!include_curvature) { b0xcv = 0.0; + } - if (!include_jpar0) + if (!include_jpar0) { J0 = 0.0; + } ////////////////////////////////////////////////////////////// // INITIALIZE LAPLACIAN SOLVER @@ -316,8 +318,9 @@ class ELMpb : public PhysicsModel { } else { // Dimits style, using local coordinate system - if (include_curvature) + if (include_curvature) { b0xcv.z += I * b0xcv.x; + } I = 0.0; // I disappears from metric } } @@ -325,10 +328,12 @@ class ELMpb : public PhysicsModel { ////////////////////////////////////////////////////////////// // NORMALISE QUANTITIES - if (mesh->get(Bbar, "bmag")) // Typical magnetic field + if (mesh->get(Bbar, "bmag")) { // Typical magnetic field Bbar = 1.0; - if (mesh->get(Lbar, "rmag")) // Typical length scale + } + if (mesh->get(Lbar, "rmag")) { // Typical length scale Lbar = 1.0; + } Va = sqrt(Bbar * Bbar / (MU0 * density * Mi)); @@ -343,8 +348,9 @@ class ELMpb : public PhysicsModel { output.write(" dnorm = {:e}\n", dnorm); output.write(" Resistivity\n"); - if (eHall) + if (eHall) { output.write(" delta_i = {:e} AA = {:e} \n", delta_i, AA); + } if (vac_lund > 0.0) { output.write(" Vacuum Tau_R = {:e} s eta = {:e} Ohm m\n", vac_lund * Tbar, @@ -584,8 +590,9 @@ class ELMpb : public PhysicsModel { + b0xGrad_dot_Grad(P0, Psi)); // electron parallel pressure } - if (diamag_phi0) + if (diamag_phi0) { ddt(Psi) -= b0xGrad_dot_Grad(phi0, Psi); // Equilibrium flow + } if (diamag_grad_t) { // grad_par(T_e) correction @@ -613,8 +620,9 @@ class ELMpb : public PhysicsModel { // Parallel current term ddt(U) -= SQ(B0) * Grad_parP(Jpar, CELL_CENTRE); // b dot grad j - if (diamag_phi0) + if (diamag_phi0) { ddt(U) -= b0xGrad_dot_Grad(phi0, U); // Equilibrium flow + } if (nonlinear) { ddt(U) -= bracket(phi, U, bm_exb) * B0; // Advection @@ -622,8 +630,9 @@ class ELMpb : public PhysicsModel { // Viscosity terms - if (viscos_perp > 0.0) + if (viscos_perp > 0.0) { ddt(U) += viscos_perp * Delp2(U); // Perpendicular viscosity + } ddt(U) -= 10 * (SQ(SQ(coords->dx)) * D4DX4(U) + SQ(SQ(coords->dz)) * D4DZ4(U)); @@ -632,15 +641,18 @@ class ELMpb : public PhysicsModel { ddt(P) = -b0xGrad_dot_Grad(phi, P0); - if (diamag_phi0) + if (diamag_phi0) { ddt(P) -= b0xGrad_dot_Grad(phi0, P); // Equilibrium flow + } - if (nonlinear) + if (nonlinear) { ddt(P) -= bracket(phi, P, bm_exb) * B0; // Advection + } // Parallel diffusion terms - if (diffusion_par > 0.0) + if (diffusion_par > 0.0) { ddt(P) += diffusion_par * Grad2_par2(P); // Parallel diffusion + } ddt(P) -= 10 * (SQ(SQ(coords->dx)) * D4DX4(P) + SQ(SQ(coords->dz)) * D4DZ4(P)); @@ -661,8 +673,9 @@ class ELMpb : public PhysicsModel { //ddt(Vpar) = -0.5*Grad_parP(P + P0, CELL_YLOW); ddt(Vpar) = -0.5 * Grad_par_LtoC(P + P0); - if (nonlinear) + if (nonlinear) { ddt(Vpar) -= bracket(phi, Vpar, bm_exb) * B0; // Advection + } } if (filter_z) { diff --git a/tests/MMS/spatial/diffusion/diffusion.cxx b/tests/MMS/spatial/diffusion/diffusion.cxx index 3fe493dd28..45e516751a 100644 --- a/tests/MMS/spatial/diffusion/diffusion.cxx +++ b/tests/MMS/spatial/diffusion/diffusion.cxx @@ -65,14 +65,17 @@ class Diffusion : public PhysicsModel { ddt(N) = 0.0; - if (Dx > 0.0) + if (Dx > 0.0) { ddt(N) += Dx * D2DX2(N); + } - if (Dy > 0.0) + if (Dy > 0.0) { ddt(N) += Dy * D2DY2(N); + } - if (Dz > 0.0) + if (Dz > 0.0) { ddt(N) += Dz * D2DZ2(N); + } return 0; } diff --git a/tests/MMS/tokamak/tokamak.cxx b/tests/MMS/tokamak/tokamak.cxx index 2e4006d12e..a8bf4b685e 100644 --- a/tests/MMS/tokamak/tokamak.cxx +++ b/tests/MMS/tokamak/tokamak.cxx @@ -76,8 +76,9 @@ class TokamakMMS : public PhysicsModel { } BoutReal sbp = 1.0; // Sign of Bp - if (min(Bpxy, true) < 0.0) + if (min(Bpxy, true) < 0.0) { sbp = -1.0; + } coords->g11 = SQ(Rxy * Bpxy); coords->g22 = 1.0 / SQ(hthe); diff --git a/tests/integrated/test-cyclic/test_cyclic.cxx b/tests/integrated/test-cyclic/test_cyclic.cxx index 81d75d1f85..0f48a1b706 100644 --- a/tests/integrated/test-cyclic/test_cyclic.cxx +++ b/tests/integrated/test-cyclic/test_cyclic.cxx @@ -63,8 +63,9 @@ int main(int argc, char** argv) { rhs(s, i) = a(s, i) * xm + b(s, i) * x(s, i) + c(s, i) * x(s, i + 1); } - for (i = 1; i < n - 1; i++) + for (i = 1; i < n - 1; i++) { rhs(s, i) = a(s, i) * x(s, i - 1) + b(s, i) * x(s, i) + c(s, i) * x(s, i + 1); + } if ((mype == (npe - 1)) && !periodic) { rhs(s, i) = a(s, i) * x(s, i - 1) + b(s, i) * x(s, i); @@ -110,8 +111,9 @@ int main(int argc, char** argv) { output << "******* Cyclic test case: "; if (allpassed) { output << "PASSED" << endl; - } else + } else { output << "FAILED" << endl; + } MPI_Barrier(BoutComm::get()); diff --git a/tests/integrated/test-drift-instability/2fluid.cxx b/tests/integrated/test-drift-instability/2fluid.cxx index 1a5e637b21..89105e970c 100644 --- a/tests/integrated/test-drift-instability/2fluid.cxx +++ b/tests/integrated/test-drift-instability/2fluid.cxx @@ -129,8 +129,9 @@ class TwoFluid : public PhysicsModel { (globalOptions->getSection("Ti"))->get("evolve", evolve_ti, true); (globalOptions->getSection("Ajpar"))->get("evolve", evolve_ajpar, true); - if (ZeroElMass) + if (ZeroElMass) { evolve_ajpar = false; // Don't need ajpar - calculated from ohm's law + } /*************** INITIALIZE LAPLACIAN SOLVERS ********/ phi_solver = Laplacian::create(globalOptions->getSection("phisolver")); @@ -162,13 +163,15 @@ class TwoFluid : public PhysicsModel { if (nu_perp < 1.e-10) { mui_hat = (3. / 10.) * nuiix / wci; - } else + } else { mui_hat = nu_perp; + } if (estatic) { beta_p = 1.e-29; - } else + } else { beta_p = 4.03e-11 * Ni_x * Te_x / bmag / bmag; + } Vi_x = wci * rho_s; @@ -240,22 +243,25 @@ class TwoFluid : public PhysicsModel { solver->add(rho, "rho"); comms.add(rho); output.write("rho\n"); - } else + } else { initial_profile("rho", rho); + } if (evolve_ni) { solver->add(Ni, "Ni"); comms.add(Ni); output.write("ni\n"); - } else + } else { initial_profile("Ni", Ni); + } if (evolve_te) { solver->add(Te, "Te"); comms.add(Te); output.write("te\n"); - } else + } else { initial_profile("Te", Te); + } if (evolve_ajpar) { solver->add(Ajpar, "Ajpar"); @@ -272,15 +278,17 @@ class TwoFluid : public PhysicsModel { solver->add(Vi, "Vi"); comms.add(Vi); output.write("vi\n"); - } else + } else { initial_profile("Vi", Vi); + } if (evolve_ti) { solver->add(Ti, "Ti"); comms.add(Ti); output.write("ti\n"); - } else + } else { initial_profile("Ti", Ti); + } // Set boundary conditions jpar.setBoundary("jpar"); diff --git a/tests/integrated/test-globalfield/test_globalfield.cxx b/tests/integrated/test-globalfield/test_globalfield.cxx index c093064af2..545a53b5ac 100644 --- a/tests/integrated/test-globalfield/test_globalfield.cxx +++ b/tests/integrated/test-globalfield/test_globalfield.cxx @@ -41,13 +41,14 @@ int Test_globalfield::init(bool UNUSED(restarting)) { if (gX.dataIsLocal()) { // Data is on this processor bool gather_pass = true; - for (int x = 0; x < gX.xSize(); x++) + for (int x = 0; x < gX.xSize(); x++) { for (int y = 0; y < gX.ySize(); y++) { if ((ROUND(gX(x, y)) != x) || (ROUND(gY(x, y)) != y)) { output.write("{:d}, {:d} : {:e}, {:e}\n", x, y, gX(x, y), gY(x, y)); gather_pass = false; } } + } output << "2D GATHER TEST: " << gather_pass << endl; } @@ -56,7 +57,7 @@ int Test_globalfield::init(bool UNUSED(restarting)) { Field2D scatY = gY.scatter(); bool scatter_pass = true; - for (int x = mesh->xstart; x <= mesh->xend; x++) + for (int x = mesh->xstart; x <= mesh->xend; x++) { for (int y = mesh->ystart; y <= mesh->yend; y++) { if ((localX(x, y) != scatX(x, y)) || (localY(x, y) != scatY(x, y))) { output.write("{:d}, {:d} : ({:e}, {:e}) ({:e}, {:e})", x, y, localX(x, y), @@ -64,6 +65,7 @@ int Test_globalfield::init(bool UNUSED(restarting)) { scatter_pass = false; } } + } output << "2D SCATTER TEST: " << scatter_pass << endl; ///////////////////////////////////////////////////////////// @@ -75,12 +77,14 @@ int Test_globalfield::init(bool UNUSED(restarting)) { localX3D.allocate(); localY3D.allocate(); - for (int x = 0; x < mesh->LocalNx; x++) - for (int y = 0; y < mesh->LocalNy; y++) + for (int x = 0; x < mesh->LocalNx; x++) { + for (int y = 0; y < mesh->LocalNy; y++) { for (int z = 0; z < mesh->LocalNz; z++) { localX3D(x, y, z) = mesh->getGlobalXIndex(x) + z; localY3D(x, y, z) = mesh->getGlobalYIndex(y - mesh->ystart) + z; } + } + } // Gather onto one processor (0 by default) GlobalField3D gX3D(mesh), gY3D(mesh); @@ -91,8 +95,8 @@ int Test_globalfield::init(bool UNUSED(restarting)) { if (gX3D.dataIsLocal()) { // Data is on this processor bool gather_pass3D = true; - for (int x = 0; x < gX3D.xSize(); x++) - for (int y = 0; y < gX3D.ySize(); y++) + for (int x = 0; x < gX3D.xSize(); x++) { + for (int y = 0; y < gX3D.ySize(); y++) { for (int z = 0; z < gX3D.zSize(); z++) { if ((ROUND(gX3D(x, y, z)) != x + z) || (ROUND(gY3D(x, y, z)) != y + z)) { output.write("{:d}, {:d}, {:d} : {:e}, {:e}\n", x, y, z, gX3D(x, y, z), @@ -100,6 +104,8 @@ int Test_globalfield::init(bool UNUSED(restarting)) { gather_pass3D = false; } } + } + } output << "3D GATHER TEST: " << gather_pass3D << endl; } @@ -108,8 +114,8 @@ int Test_globalfield::init(bool UNUSED(restarting)) { Field3D scatY3D = gY3D.scatter(); bool scatter_pass3D = true; - for (int x = mesh->xstart; x <= mesh->xend; x++) - for (int y = mesh->ystart; y <= mesh->yend; y++) + for (int x = mesh->xstart; x <= mesh->xend; x++) { + for (int y = mesh->ystart; y <= mesh->yend; y++) { for (int z = 0; z < mesh->LocalNz; z++) { if ((localX3D(x, y, z) != scatX3D(x, y, z)) || (localY3D(x, y, z) != scatY3D(x, y, z))) { @@ -119,6 +125,8 @@ int Test_globalfield::init(bool UNUSED(restarting)) { scatter_pass3D = false; } } + } + } output << "2D SCATTER TEST: " << scatter_pass3D << endl; return 1; // Signal an error, so quits diff --git a/tests/integrated/test-laplacexy/loadmetric.cxx b/tests/integrated/test-laplacexy/loadmetric.cxx index 53749679df..6d8afad750 100644 --- a/tests/integrated/test-laplacexy/loadmetric.cxx +++ b/tests/integrated/test-laplacexy/loadmetric.cxx @@ -45,8 +45,9 @@ void LoadMetric(BoutReal Lnorm, BoutReal Bnorm) { } BoutReal sbp = 1.0; // Sign of Bp - if (min(Bpxy, true) < 0.0) + if (min(Bpxy, true) < 0.0) { sbp = -1.0; + } coords->g11 = pow(Rxy * Bpxy, 2); coords->g22 = 1.0 / pow(hthe, 2); diff --git a/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx b/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx index 383af21a4c..2b03f78049 100644 --- a/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx +++ b/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx @@ -172,15 +172,19 @@ int main(int argc, char** argv) { // make field to pass in boundary conditions Field3D x0 = 0.; - if (mesh->firstX()) - for (int k = 0; k < mesh->LocalNz; k++) + if (mesh->firstX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xstart - 1, mesh->ystart, k) = 0.5 * (f3(mesh->xstart - 1, mesh->ystart, k) + f3(mesh->xstart, mesh->ystart, k)); - if (mesh->lastX()) - for (int k = 0; k < mesh->LocalNz; k++) + } + } + if (mesh->lastX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xend + 1, mesh->ystart, k) = 0.5 * (f3(mesh->xend + 1, mesh->ystart, k) + f3(mesh->xend, mesh->ystart, k)); + } + } try { sol3 = invert->solve(sliceXZ(b3, mesh->ystart), sliceXZ(x0, mesh->ystart)); @@ -233,18 +237,22 @@ int main(int argc, char** argv) { // make field to pass in boundary conditions x0 = 0.; - if (mesh->firstX()) - for (int k = 0; k < mesh->LocalNz; k++) + if (mesh->firstX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xstart - 1, mesh->ystart, k) = (f4(mesh->xstart, mesh->ystart, k) - f4(mesh->xstart - 1, mesh->ystart, k)) / mesh->getCoordinates()->dx(mesh->xstart, mesh->ystart, k) / sqrt(mesh->getCoordinates()->g_11(mesh->xstart, mesh->ystart, k)); - if (mesh->lastX()) - for (int k = 0; k < mesh->LocalNz; k++) + } + } + if (mesh->lastX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xend + 1, mesh->ystart, k) = (f4(mesh->xend + 1, mesh->ystart, k) - f4(mesh->xend, mesh->ystart, k)) / mesh->getCoordinates()->dx(mesh->xend, mesh->ystart, k) / sqrt(mesh->getCoordinates()->g_11(mesh->xend, mesh->ystart, k)); + } + } try { sol4 = invert->solve(sliceXZ(b4, mesh->ystart), sliceXZ(x0, mesh->ystart)); @@ -302,10 +310,13 @@ BoutReal max_error_at_ystart(const Field3D& error) { BoutReal local_max_error = error(mesh->xstart, mesh->ystart, 0); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jz = 0; jz < mesh->LocalNz; jz++) - if (local_max_error < error(jx, mesh->ystart, jz)) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jz = 0; jz < mesh->LocalNz; jz++) { + if (local_max_error < error(jx, mesh->ystart, jz)) { local_max_error = error(jx, mesh->ystart, jz); + } + } + } BoutReal max_error; diff --git a/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx b/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx index 29d33d9cf6..07a403e2e2 100644 --- a/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx +++ b/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx @@ -174,15 +174,19 @@ int main(int argc, char** argv) { // make field to pass in boundary conditions Field3D x0 = 0.; - if (mesh->firstX()) - for (int k = 0; k < mesh->LocalNz; k++) + if (mesh->firstX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xstart - 1, mesh->ystart, k) = 0.5 * (f3(mesh->xstart - 1, mesh->ystart, k) + f3(mesh->xstart, mesh->ystart, k)); - if (mesh->lastX()) - for (int k = 0; k < mesh->LocalNz; k++) + } + } + if (mesh->lastX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xend + 1, mesh->ystart, k) = 0.5 * (f3(mesh->xend + 1, mesh->ystart, k) + f3(mesh->xend, mesh->ystart, k)); + } + } try { sol3 = invert.solve(b3, x0); @@ -237,18 +241,22 @@ int main(int argc, char** argv) { // make field to pass in boundary conditions x0 = 0.; - if (mesh->firstX()) - for (int k = 0; k < mesh->LocalNz; k++) + if (mesh->firstX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xstart - 1, mesh->ystart, k) = (f4(mesh->xstart, mesh->ystart, k) - f4(mesh->xstart - 1, mesh->ystart, k)) / mesh->getCoordinates()->dx(mesh->xstart, mesh->ystart, k) / sqrt(mesh->getCoordinates()->g_11(mesh->xstart, mesh->ystart, k)); - if (mesh->lastX()) - for (int k = 0; k < mesh->LocalNz; k++) + } + } + if (mesh->lastX()) { + for (int k = 0; k < mesh->LocalNz; k++) { x0(mesh->xend + 1, mesh->ystart, k) = (f4(mesh->xend + 1, mesh->ystart, k) - f4(mesh->xend, mesh->ystart, k)) / mesh->getCoordinates()->dx(mesh->xend, mesh->ystart, k) / sqrt(mesh->getCoordinates()->g_11(mesh->xend, mesh->ystart, k)); + } + } try { sol4 = invert.solve(b4, x0); @@ -306,10 +314,13 @@ BoutReal max_error_at_ystart(const Field3D& error) { const auto* mesh = error.getMesh(); BoutReal local_max_error = error(mesh->xstart, mesh->ystart, 0); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jz = 0; jz < mesh->LocalNz; jz++) - if (local_max_error < error(jx, mesh->ystart, jz)) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jz = 0; jz < mesh->LocalNz; jz++) { + if (local_max_error < error(jx, mesh->ystart, jz)) { local_max_error = error(jx, mesh->ystart, jz); + } + } + } BoutReal max_error; diff --git a/tests/integrated/test-petsc_laplace/test_petsc_laplace.cxx b/tests/integrated/test-petsc_laplace/test_petsc_laplace.cxx index c491db96fb..bfd394194f 100644 --- a/tests/integrated/test-petsc_laplace/test_petsc_laplace.cxx +++ b/tests/integrated/test-petsc_laplace/test_petsc_laplace.cxx @@ -61,8 +61,8 @@ int main(int argc, char** argv) { p = 0.39503274; q = 0.20974396; f1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -80,9 +80,11 @@ int main(int argc, char** argv) { ; ASSERT0(finite(f1(jx, jy, jz))); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -100,9 +102,12 @@ int main(int argc, char** argv) { * (z - q)))); //make the gradients zero at both x-boundaries ASSERT0(finite(f1(jx, jy, jz))); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -120,23 +125,28 @@ int main(int argc, char** argv) { * (z - q)))); //make the gradients zero at both x-boundaries ASSERT0(finite(f1(jx, jy, jz))); } + } + } + } f1.applyBoundary("neumann"); p = 0.512547; q = 0.30908712; d1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d1(jx, jy, jz) = 1. + 0.2 * exp(-50. * pow(x - p, 2) / 4.) * sin(2. * PI * (z - q) * 3.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -144,9 +154,12 @@ int main(int argc, char** argv) { 1. + 0.2 * exp(-50. * pow(x - p, 2) / 4.) * sin(2. * PI * (z - q) * 3.); // d1(jx, jy, jz) = d1(jx+1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -154,21 +167,26 @@ int main(int argc, char** argv) { 1. + 0.2 * exp(-50. * pow(x - p, 2) / 4.) * sin(2. * PI * (z - q) * 3.); // d1(jx, jy, jz) = d1(jx-1, jy, jz); } + } + } + } p = 0.18439023; q = 0.401089473; c1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c1(jx, jy, jz) = 1. + 0.15 * exp(-50. * pow(x - p, 2) * 2.) * sin(2. * PI * (z - q) * 2.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -176,9 +194,12 @@ int main(int argc, char** argv) { 1. + 0.15 * exp(-50. * pow(x - p, 2) * 2.) * sin(2. * PI * (z - q) * 2.); // c1(jx, jy, jz) = c1(jx+1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -186,21 +207,26 @@ int main(int argc, char** argv) { 1. + 0.15 * exp(-50. * pow(x - p, 2) * 2.) * sin(2. * PI * (z - q) * 2.); // c1(jx, jy, jz) = c1(jx-1, jy, jz); } + } + } + } p = 0.612547; q = 0.30908712; a1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a1(jx, jy, jz) = -1. + 0.1 * exp(-50. * pow(x - p, 2) * 2.5) * sin(2. * PI * (z - q) * 7.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -208,9 +234,12 @@ int main(int argc, char** argv) { -1. + 0.1 * exp(-50. * pow(x - p, 2) * 2.5) * sin(2. * PI * (z - q) * 7.); // a1(jx, jy, jz) = a1(jx+1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -218,6 +247,9 @@ int main(int argc, char** argv) { -1. + 0.1 * exp(-50. * pow(x - p, 2) * 2.5) * sin(2. * PI * (z - q) * 7.); // a1(jx, jy, jz) = a1(jx-1, jy, jz); } + } + } + } checkData(f1); checkData(a1); @@ -228,18 +260,24 @@ int main(int argc, char** argv) { b1 = d1 * Delp2(f1) + Grad_perp(c1) * Grad_perp(f1) / c1 + a1 * f1; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b1(jx, jy, jz) = b1(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b1(jx, jy, jz) = b1(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -332,18 +370,24 @@ int main(int argc, char** argv) { c3 = DC(c1); d3 = DC(d1); b3 = d3 * Delp2(f1) + Grad_perp(c3) * Grad_perp(f1) / c3 + a3 * f1; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b3(jx, jy, jz) = b3(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b3(jx, jy, jz) = b3(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -421,8 +465,8 @@ int main(int argc, char** argv) { p = 0.623901; q = 0.01209489; f5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -439,9 +483,11 @@ int main(int argc, char** argv) { * (z - q)))) //make the gradients zero at both x-boundaries ; } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -458,9 +504,12 @@ int main(int argc, char** argv) { 2. * PI * (z - q)))); //make the gradients zero at both x-boundaries } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -477,106 +526,139 @@ int main(int argc, char** argv) { 2. * PI * (z - q)))); //make the gradients zero at both x-boundaries } + } + } + } p = 0.63298589; q = 0.889237890; d5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d5(jx, jy, jz) = 1. + p * cos(2. * PI * x) * sin(2. * PI * (z - q) * 3.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d5(jx, jy, jz) = 1. + p * cos(2. * PI * x) * sin(2. * PI * (z - q) * 3.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d5(jx, jy, jz) = 1. + p * cos(2. * PI * x) * sin(2. * PI * (z - q) * 3.); } + } + } + } p = 0.160983834; q = 0.73050121087; c5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c5(jx, jy, jz) = 1. + p * cos(2. * PI * x * 5) * sin(2. * PI * (z - q) * 2.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c5(jx, jy, jz) = 1. + p * cos(2. * PI * x * 5) * sin(2. * PI * (z - q) * 2.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c5(jx, jy, jz) = 1. + p * cos(2. * PI * x * 5) * sin(2. * PI * (z - q) * 2.); } + } + } + } p = 0.5378950; q = 0.2805870; a5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a5(jx, jy, jz) = -1. + p * cos(2. * PI * x * 2.) * sin(2. * PI * (z - q) * 7.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a5(jx, jy, jz) = -1. + p * cos(2. * PI * x * 2.) * sin(2. * PI * (z - q) * 7.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a5(jx, jy, jz) = -1. + p * cos(2. * PI * x * 2.) * sin(2. * PI * (z - q) * 7.); } + } + } + } f5.applyBoundary("neumann"); mesh->communicate(f5, a5, c5, d5); b5 = d5 * Delp2(f5) + Grad_perp(c5) * Grad_perp(f5) / c5 + a5 * f5; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b5(jx, jy, jz) = b5(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b5(jx, jy, jz) = b5(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -668,18 +750,24 @@ int main(int argc, char** argv) { c7 = DC(c5); d7 = DC(d5); b7 = d7 * Delp2(f5) + Grad_perp(c7) * Grad_perp(f5) / c7 + a7 * f5; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b7(jx, jy, jz) = b7(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b7(jx, jy, jz) = b7(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -766,10 +854,13 @@ BoutReal max_error_at_ystart(const Field3D& error) { const auto* mesh = error.getMesh(); BoutReal local_max_error = error(mesh->xstart, mesh->ystart, 0); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jz = 0; jz < mesh->LocalNz; jz++) - if (local_max_error < error(jx, mesh->ystart, jz)) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jz = 0; jz < mesh->LocalNz; jz++) { + if (local_max_error < error(jx, mesh->ystart, jz)) { local_max_error = error(jx, mesh->ystart, jz); + } + } + } BoutReal max_error; diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx b/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx index d44b7f7809..7646b915a7 100644 --- a/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx +++ b/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx @@ -61,8 +61,8 @@ int main(int argc, char** argv) { p = 0.39503274; q = 0.20974396; f1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -79,9 +79,11 @@ int main(int argc, char** argv) { * (z - q)))) //make the gradients zero at both x-boundaries ; } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -98,9 +100,12 @@ int main(int argc, char** argv) { 2. * PI * (z - q)))); //make the gradients zero at both x-boundaries } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -117,12 +122,15 @@ int main(int argc, char** argv) { 2. * PI * (z - q)))); //make the gradients zero at both x-boundaries } + } + } + } p = 0.512547; q = 0.30908712; d1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -130,9 +138,11 @@ int main(int argc, char** argv) { 1.e-7 * (1. + 0.2 * exp(-50. * pow(x - p, 2) / 4.) * sin(2. * PI * (z - q) * 3.)); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -141,9 +151,12 @@ int main(int argc, char** argv) { * (1. + 0.2 * exp(-50. * pow(x - p, 2) / 4.) * sin(2. * PI * (z - q) * 3.)); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -152,12 +165,15 @@ int main(int argc, char** argv) { * (1. + 0.2 * exp(-50. * pow(x - p, 2) / 4.) * sin(2. * PI * (z - q) * 3.)); } + } + } + } p = 0.18439023; q = 0.401089473; c1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -165,9 +181,11 @@ int main(int argc, char** argv) { + 1.e-6 * 0.15 * exp(-50. * pow(x - p, 2) * 2.) * sin(2. * PI * (z - q) * 2.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -175,9 +193,12 @@ int main(int argc, char** argv) { + 1.e-6 * 0.15 * exp(-50. * pow(x - p, 2) * 2.) * sin(2. * PI * (z - q) * 2.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -185,54 +206,71 @@ int main(int argc, char** argv) { + 1.e-6 * 0.15 * exp(-50. * pow(x - p, 2) * 2.) * sin(2. * PI * (z - q) * 2.); } + } + } + } p = 0.612547; q = 0.30908712; a1.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a1(jx, jy, jz) = -1. + 0.1 * exp(-50. * pow(x - p, 2) * 2.5) * sin(2. * PI * (z - q) * 7.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a1(jx, jy, jz) = -1. + 0.1 * exp(-50. * pow(x - p, 2) * 2.5) * sin(2. * PI * (z - q) * 7.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a1(jx, jy, jz) = -1. + 0.1 * exp(-50. * pow(x - p, 2) * 2.5) * sin(2. * PI * (z - q) * 7.); } + } + } + } mesh->communicate(f1, a1, c1, d1); f1.setBoundary("neumann"); b1 = d1 * Delp2(f1) + Grad_perp(c1) * Grad_perp(f1) / c1 + a1 * f1; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b1(jx, jy, jz) = b1(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b1(jx, jy, jz) = b1(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -330,18 +368,24 @@ int main(int argc, char** argv) { c3 = DC(c1); d3 = DC(d1); b3 = d3 * Delp2(f1) + Grad_perp(c3) * Grad_perp(f1) / c3 + a3 * f1; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b3(jx, jy, jz) = b3(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b3(jx, jy, jz) = b3(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -422,8 +466,8 @@ int main(int argc, char** argv) { p = 0.623901; q = 0.01209489; f5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -440,9 +484,11 @@ int main(int argc, char** argv) { * (z - q)))) //make the gradients zero at both x-boundaries ; } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -459,9 +505,12 @@ int main(int argc, char** argv) { 2. * PI * (z - q)))); //make the gradients zero at both x-boundaries } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; @@ -478,111 +527,144 @@ int main(int argc, char** argv) { 2. * PI * (z - q)))); //make the gradients zero at both x-boundaries } + } + } + } p = 0.63298589; q = 0.889237890; d5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d5(jx, jy, jz) = 1.e-7 * (1. + p * cos(2. * PI * x) * sin(2. * PI * (z - q) * 3.)); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d5(jx, jy, jz) = 1.e-7 * (1. + p * cos(2. * PI * x) * sin(2. * PI * (z - q) * 3.)); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; d5(jx, jy, jz) = 1.e-7 * (1. + p * cos(2. * PI * x) * sin(2. * PI * (z - q) * 3.)); } + } + } + } p = 0.160983834; q = 0.73050121087; c5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c5(jx, jy, jz) = 1. + 1.e-6 * p * cos(2. * PI * x * 5) * sin(2. * PI * (z - q) * 2.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c5(jx, jy, jz) = 1. + 1.e-6 * p * cos(2. * PI * x * 5) * sin(2. * PI * (z - q) * 2.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; c5(jx, jy, jz) = 1. + 1.e-6 * p * cos(2. * PI * x * 5) * sin(2. * PI * (z - q) * 2.); } + } + } + } p = 0.5378950; q = 0.2805870; a5.allocate(); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a5(jx, jy, jz) = -1. + p * cos(2. * PI * x * 2.) * sin(2. * PI * (z - q) * 7.); } - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a5(jx, jy, jz) = -1. + p * cos(2. * PI * x * 2.) * sin(2. * PI * (z - q) * 7.); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal x = BoutReal(mesh->getGlobalXIndex(jx) - mesh->xstart) / nx; BoutReal z = BoutReal(jz) / nz; a5(jx, jy, jz) = -1. + p * cos(2. * PI * x * 2.) * sin(2. * PI * (z - q) * 7.); } + } + } + } mesh->communicate(f5, a5, c5, d5); b5 = d5 * Delp2(f5) + Grad_perp(c5) * Grad_perp(f5) / c5 + a5 * f5; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b5(jx, jy, jz) = b5(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b5(jx, jy, jz) = b5(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -677,18 +759,24 @@ int main(int argc, char** argv) { c7 = DC(c5); d7 = DC(d5); b7 = d7 * Delp2(f5) + Grad_perp(c7) * Grad_perp(f5) / c7 + a7 * f5; - if (mesh->firstX()) - for (int jx = mesh->xstart - 1; jx >= 0; jx--) - for (int jy = 0; jy < mesh->LocalNy; jy++) + if (mesh->firstX()) { + for (int jx = mesh->xstart - 1; jx >= 0; jx--) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b7(jx, jy, jz) = b7(jx + 1, jy, jz); } - if (mesh->lastX()) - for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) - for (int jy = 0; jy < mesh->LocalNy; jy++) + } + } + } + if (mesh->lastX()) { + for (int jx = mesh->xend + 1; jx < mesh->LocalNx; jx++) { + for (int jy = 0; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { b7(jx, jy, jz) = b7(jx - 1, jy, jz); } + } + } + } invert->setInnerBoundaryFlags(INVERT_AC_GRAD); invert->setOuterBoundaryFlags(INVERT_AC_GRAD); @@ -775,11 +863,13 @@ BoutReal max_error_at_ystart(const Field3D& error) { const auto* mesh = error.getMesh(); BoutReal local_max_error = error(mesh->xstart, mesh->ystart, 0); - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) - for (int jz = 0; jz < mesh->LocalNz; jz++) + for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { + for (int jz = 0; jz < mesh->LocalNz; jz++) { if (local_max_error < error(jx, mesh->ystart, jz)) { local_max_error = error(jx, mesh->ystart, jz); } + } + } BoutReal max_error; diff --git a/tests/integrated/test-region-iterator/test_region_iterator.cxx b/tests/integrated/test-region-iterator/test_region_iterator.cxx index 3656984679..db35c288d1 100644 --- a/tests/integrated/test-region-iterator/test_region_iterator.cxx +++ b/tests/integrated/test-region-iterator/test_region_iterator.cxx @@ -28,18 +28,22 @@ int Test_region_iterator::init(bool UNUSED(restarting)) { //Check expected results int nerr = 0; for (const auto& i : a.getRegion(RGN_ALL)) { - if (a[i] != 3.0) + if (a[i] != 3.0) { nerr++; + } } - if (nerr != 0) + if (nerr != 0) { throw BoutException("Unexpected values found in 'a', count {:d}", nerr); + } nerr = 0; for (const auto& i : b.getRegion(RGN_ALL)) { - if (b[i] != c[i]) + if (b[i] != c[i]) { nerr++; + } } - if (nerr != 0) + if (nerr != 0) { throw BoutException("Unexpected values found in 'b', count {:d}", nerr); + } Field3D d = 1.0, e = 1.0, f = 2.0; BOUT_FOR(i, d.getRegion("RGN_NOBNDRY")) { @@ -54,18 +58,22 @@ int Test_region_iterator::init(bool UNUSED(restarting)) { + 2 * mesh->ystart * (mesh->LocalNx - mesh->xstart * 2)) * mesh->LocalNz; for (const auto& i : d.getRegion(RGN_ALL)) { - if (d[i] != 3.0) + if (d[i] != 3.0) { nerr++; + } } - if (nerr != nerrExpected) + if (nerr != nerrExpected) { throw BoutException("Unexpected values found in 'd', count {:d}", nerr); + } nerr = 0; for (const auto& i : e.getRegion(RGN_ALL)) { - if (e[i] != f[i]) + if (e[i] != f[i]) { nerr++; + } } - if (nerr != nerrExpected) + if (nerr != nerrExpected) { throw BoutException("Unexpected values found in 'e', count {:d}", nerr); + } SOLVE_FOR(n); return 0; diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index 4fd1124679..692d561c59 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -67,13 +67,17 @@ def verify(f1, f2): v1[0, 0] = v1[0, -1] = v1[-1, 0] = v1[-1, -1] = 0.0 v2[0, 0] = v2[0, -1] = v2[-1, 0] = v2[-1, -1] = 0.0 - if not np.allclose(v1, v2, equal_nan=True): - err = "" - dimensions = [range(x) for x in v1.shape] - for i in itertools.product(*dimensions): - if v1[i] != v2[i]: - err += "{}: {} != {}\n".format(i, v1[i], v2[i]) - raise RuntimeError("data mismatch in ", v, err, v1, v2) + if v1.dtype.char in "SU": + if v1 != v2: + raise RuntimeError("data mismatch in ", v, v1, v2) + else: + if not np.allclose(v1, v2, equal_nan=True): + err = "" + dimensions = [range(x) for x in v1.shape] + for i in itertools.product(*dimensions): + if v1[i] != v2[i]: + err += "{}: {} != {}\n".format(i, v1[i], v2[i]) + raise RuntimeError("data mismatch in ", v, err, v1, v2) parser = argparse.ArgumentParser(description="Test the bout-squashoutput wrapper") diff --git a/tests/integrated/test-yupdown-weights/test_yupdown_weights.cxx b/tests/integrated/test-yupdown-weights/test_yupdown_weights.cxx index 187f8910f5..22d1fb9e07 100644 --- a/tests/integrated/test-yupdown-weights/test_yupdown_weights.cxx +++ b/tests/integrated/test-yupdown-weights/test_yupdown_weights.cxx @@ -7,10 +7,13 @@ Field3D DDY_yud(const Field3D& f) { Field3D result{0.0}; const auto* mesh = f.getMesh(); - for (int i = 0; i < mesh->LocalNx; i++) - for (int j = mesh->ystart; j <= mesh->yend; j++) - for (int k = 0; k < mesh->LocalNz; k++) + for (int i = 0; i < mesh->LocalNx; i++) { + for (int j = mesh->ystart; j <= mesh->yend; j++) { + for (int k = 0; k < mesh->LocalNz; k++) { result(i, j, k) = 0.5 * (f.yup()(i, j + 1, k) - f.ydown()(i, j - 1, k)); + } + } + } return result; } diff --git a/tests/integrated/test-yupdown/test_yupdown.cxx b/tests/integrated/test-yupdown/test_yupdown.cxx index 1ad87007fe..e5889411ad 100644 --- a/tests/integrated/test-yupdown/test_yupdown.cxx +++ b/tests/integrated/test-yupdown/test_yupdown.cxx @@ -5,10 +5,13 @@ const Field3D DDY_aligned(const Field3D& f) { Field3D result = emptyFrom(f); const auto* mesh = f.getMesh(); - for (int i = 0; i < mesh->LocalNx; i++) - for (int j = mesh->ystart; j <= mesh->yend; j++) - for (int k = 0; k < mesh->LocalNz; k++) + for (int i = 0; i < mesh->LocalNx; i++) { + for (int j = mesh->ystart; j <= mesh->yend; j++) { + for (int k = 0; k < mesh->LocalNz; k++) { result(i, j, k) = 0.5 * (f(i, j + 1, k) - f(i, j - 1, k)); + } + } + } return result; } diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 92abe408ac..c0fd4a1e1f 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -108,7 +108,7 @@ add_test(NAME serial_tests COMMAND serial_tests --gtest_brief=1) set_target_properties(serial_tests PROPERTIES FOLDER tests/unit) add_dependencies(build-check-unit-tests serial_tests) -if (BOUT_USE_CUDA) +if (BOUT_HAS_CUDA) set_source_files_properties(${serial_tests_source} PROPERTIES LANGUAGE CUDA ) set_target_properties(serial_tests PROPERTIES CUDA_STANDARD 14) endif () diff --git a/tests/unit/field/test_field2d.cxx b/tests/unit/field/test_field2d.cxx index 6de672b8b0..3e745b16d0 100644 --- a/tests/unit/field/test_field2d.cxx +++ b/tests/unit/field/test_field2d.cxx @@ -758,7 +758,7 @@ TEST_F(Field2DTest, ConstIndexingInd3D) { EXPECT_DOUBLE_EQ(field2[ind], 10); } -#if CHECK > 2 && !BOUT_USE_CUDA +#if CHECK > 2 && !BOUT_HAS_CUDA TEST_F(Field2DTest, CheckNotEmpty) { Field2D field; @@ -858,8 +858,9 @@ TEST_F(Field2DTest, InvalidateGuards) { sum = 0; for (const auto& i : field) { - if (!finite(field[i])) + if (!finite(field[i])) { sum++; + } } EXPECT_EQ(sum, nbndry); } diff --git a/tests/unit/field/test_field3d.cxx b/tests/unit/field/test_field3d.cxx index ef8eda111a..18ffaa3ab7 100644 --- a/tests/unit/field/test_field3d.cxx +++ b/tests/unit/field/test_field3d.cxx @@ -1216,8 +1216,9 @@ TEST_F(Field3DTest, InvalidateGuards) { sum = 0; for (const auto& i : field) { - if (!finite(field[i])) + if (!finite(field[i])) { sum++; + } } EXPECT_EQ(sum, nbndry); } diff --git a/tests/unit/field/test_field_factory.cxx b/tests/unit/field/test_field_factory.cxx index 5652f43388..c0d17915a4 100644 --- a/tests/unit/field/test_field_factory.cxx +++ b/tests/unit/field/test_field_factory.cxx @@ -856,7 +856,7 @@ class MockParallelTransform : public ParallelTransform { void calcParallelSlices(Field3D&) override {} - bool canToFromFieldAligned() override { return allow_transform; } + bool canToFromFieldAligned() const override { return allow_transform; } bool requiresTwistShift(bool, YDirectionType) override { return false; } diff --git a/tests/unit/field/test_fieldperp.cxx b/tests/unit/field/test_fieldperp.cxx index 957ea3b494..a765475482 100644 --- a/tests/unit/field/test_fieldperp.cxx +++ b/tests/unit/field/test_fieldperp.cxx @@ -854,8 +854,9 @@ TEST_F(FieldPerpTest, InvalidateGuards) { sum = 0; for (const auto& i : field) { - if (!finite(field[i])) + if (!finite(field[i])) { sum++; + } } EXPECT_EQ(sum, nbndry); } diff --git a/tests/unit/include/bout/test_array.cxx b/tests/unit/include/bout/test_array.cxx index f8b485ba9f..21be6fe8a5 100644 --- a/tests/unit/include/bout/test_array.cxx +++ b/tests/unit/include/bout/test_array.cxx @@ -243,7 +243,7 @@ TEST_F(ArrayTest, Assignment) { EXPECT_FALSE(b.unique()); } -#if CHECK > 2 && !BOUT_USE_CUDA +#if CHECK > 2 && !BOUT_HAS_CUDA TEST_F(ArrayTest, OutOfBoundsThrow) { Array a(34); EXPECT_NO_THROW(a[33] = 1.0); diff --git a/tests/unit/include/bout/test_hypre_interface.cxx b/tests/unit/include/bout/test_hypre_interface.cxx index 554af1a7ca..b7a7c2c50c 100644 --- a/tests/unit/include/bout/test_hypre_interface.cxx +++ b/tests/unit/include/bout/test_hypre_interface.cxx @@ -96,7 +96,7 @@ TYPED_TEST(HypreVectorTest, Assemble) { // HYPRE_IJVectorGetValues when using CUDA requires indices and values use device // compatible memory -#if BOUT_USE_CUDA && defined(__CUDACC__) +#if BOUT_HAS_CUDA && defined(__CUDACC__) HYPRE_BigInt* um_i; HYPRE_Complex* um_actual; cudaMallocManaged(&um_i, sizeof(HYPRE_BigInt)); diff --git a/tests/unit/include/bout/test_macro_for_each.cxx b/tests/unit/include/bout/test_macro_for_each.cxx index 5312e0cb63..88ef7f4085 100644 --- a/tests/unit/include/bout/test_macro_for_each.cxx +++ b/tests/unit/include/bout/test_macro_for_each.cxx @@ -42,8 +42,11 @@ TEST(MacroForEachTest, NoBraces) { int a = 0; // Only the first expansion is disabled + // This is really confusing, and clang-format would fix this, to skip all + // clang-format off if (false) MACRO_FOR_EACH(INC, a, a, a); + // clang-format on EXPECT_EQ(a, 2); } diff --git a/tools/archiving/pdb2cdf/pdb2cdf.cxx b/tools/archiving/pdb2cdf/pdb2cdf.cxx index dc59ff13b4..ac8bc85de6 100644 --- a/tools/archiving/pdb2cdf/pdb2cdf.cxx +++ b/tools/archiving/pdb2cdf/pdb2cdf.cxx @@ -112,8 +112,9 @@ int main(int argc, char** argv) { if (maxdims < 4) { dimlist = dimlist3d; - } else + } else { dimlist = dimlist4d; + } if (maxdims > 4) { fprintf(stderr, "ERROR: Can only handle up to 4D variables\n"); @@ -174,8 +175,9 @@ int main(int argc, char** argv) { if ((dimlist[d].min == min) && (dimlist[d].max == max)) { if (lastdim == -1) { printf("[%s", dimlist[d].label); - } else + } else { printf(",%s", dimlist[d].label); + } vardim[nd] = d; lastdim = d; break; @@ -193,11 +195,13 @@ int main(int argc, char** argv) { dims = dims->next; } - if (!gotdims) + if (!gotdims) { continue; // Skip this variable + } - if (lastdim != -1) + if (lastdim != -1) { printf("] (%d elements) ", varsize); + } // Now know number of dimensions nd, and a list of dimension indices vardim diff --git a/tools/pylib/_boutpp_build/CMakeLists.txt b/tools/pylib/_boutpp_build/CMakeLists.txt index 7ceae04f0e..6b88986a28 100644 --- a/tools/pylib/_boutpp_build/CMakeLists.txt +++ b/tools/pylib/_boutpp_build/CMakeLists.txt @@ -3,7 +3,7 @@ macro(bout_python_maybe_error VAR NAME) if (NOT ${VAR}) set(_error_msg "${NAME} is required for the Python interface") - if (NOT "${BOUT_ENABLE_PYTHON}" STREQUAL "MAYBE") + if (NOT "${BOUT_ENABLE_PYTHON}" STREQUAL "AUTO") message(FATAL_ERROR ${_error_msg}) else() message(WARNING ${_error_msg}) @@ -49,7 +49,7 @@ if (NOT ${PYTHON_WORKING} EQUAL 0) endif() # No errors? We can build the interface! -if ("${BOUT_ENABLE_PYTHON}" STREQUAL "MAYBE") +if ("${BOUT_ENABLE_PYTHON}" STREQUAL "AUTO") set(BOUT_ENABLE_PYTHON ON PARENT_SCOPE) endif() diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 3eabbbdbd8..15dbc84e31 100644 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -6,6 +6,7 @@ import subprocess # corelib import re # corelib import pathlib # corelib +import contextlib # corelib try: import packaging.tags # packaging @@ -27,13 +28,20 @@ def getversion(): """ global version if version is None: - _bout_previous_version = "v5.0.0" - _bout_next_version = "5.0.1" + with contextlib.suppress(KeyError): + # 0. Check whether version is set via environment variable + version = os.environ["BOUT_PRETEND_VERSION"] + return version + + _bout_previous_version = "v5.1.0" + _bout_next_version = "v5.2.0" try: try: + # 1. Check whether we are at a tag version = run2("git describe --exact-match --tags HEAD").strip() except subprocess.CalledProcessError: + # 2. default mode, try to derive version from previous tag tmp = run2( f"git describe --tags --match={_bout_previous_version}" ).strip() @@ -48,8 +56,22 @@ def getversion(): with open("_version.txt", "w") as f: f.write(version + "\n") except subprocess.CalledProcessError: - with open("_version.txt") as f: - version = f.read().strip() + try: + # 3. Check whether there is a _version - e.g. we have a tarball + with open("_version.txt") as f: + version = f.read().strip() + except FileNotFoundError: + # 4. Maybe not released yet, but version already bumped? + # Things are messy here, so always assume useLocalVersion + try: + # 4.1 us proper hash + hash = "g" + run2('git log -n 1 --pretty=format:"%h"') + except subprocess.CalledProcessError: + # 4.2 fallback + hash = "unknown" + version = _bout_previous_version + ".rc+" + hash + with open("_version.txt", "w") as f: + f.write(version + "\n") return version @@ -132,7 +154,7 @@ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): run( "cmake -S . -B _wheel_build/ -DBOUT_ENABLE_PYTHON=ON" + f" -DCMAKE_INSTALL_PREFIX={prefix} -DCMAKE_INSTALL_LIBDIR={prefix}" - + f" -DCMAKE_INSTALL_PYTHON_SITEARCH={trueprefix} -DCMAKE_INSTALL_RPATH=\$ORIGIN" + + f" -DCMAKE_INSTALL_PYTHON_SITEARCH={trueprefix} -DCMAKE_INSTALL_RPATH=$ORIGIN" + opts ) run(f"cmake --build _wheel_build/ -j {os.cpu_count()}") @@ -152,6 +174,7 @@ def build_sdist(sdist_directory, config_settings=None): print(config_settings, sdist_directory) enable_gz = True enable_xz = False + external = {"fmt", "mpark.variant"} if config_settings is not None: global useLocalVersion, pkgname for k, v in config_settings.items(): @@ -166,6 +189,10 @@ def build_sdist(sdist_directory, config_settings=None): enable_xz = True else: raise ValueError(f"unknown option {v} for {k}") + if k == "dist": + enable_xz = True + pkgname = "BOUT++" + external.add("googletest") if k == "useLocalVersion": useLocalVersion = False if k == "nightly": @@ -175,7 +202,7 @@ def build_sdist(sdist_directory, config_settings=None): fname = f"{prefix}.tar" run(f"git archive HEAD --prefix {prefix}/ -o {sdist_directory}/{fname}") _, tmp = tempfile.mkstemp(suffix=".tar") - for ext in "fmt", "mpark.variant": + for ext in sorted(external): run( f"git archive --remote=externalpackages/{ext} HEAD --prefix {prefix}/externalpackages/{ext}/ --format=tar > {tmp}" ) @@ -275,22 +302,70 @@ def parse(fn): def nightly(): + """ + Build the python sdist for upload to boutpp-nightly. + """ return build_sdist(os.getcwd() + "/dist/", dict(nightly=True)) def sdist(): + """ + Build the python sdist + """ return build_sdist(os.getcwd() + "/dist/") def wheel(): + """ + Build the python binary wheel + """ return build_wheel(os.getcwd() + "/dist/") +def dist(): + """ + Build an archive for BOUT++ release + """ + return build_sdist(os.getcwd(), config_settings=dict(dist=True)) + + +def help(): + """ + Print this help + """ + table = [] + for k, v in todos.items(): + try: + doc = v.__doc__.strip() + doc = " : " + doc + except: + doc = "" + table.append((k, doc)) + maxkey = max([len(k) for k, _ in table]) + fmt = f" %-{maxkey}s%s" + print(f"{sys.argv[0]} [command] [command]") + for row in table: + print(fmt % row) + + +todos = dict( + nightly=nightly, + sdist=sdist, + wheel=wheel, + dist=dist, + version=lambda: print(getversion()), + help=help, +) +todos.update( + { + "--help": help, + "-?": help, + "-h": help, + } +) + if __name__ == "__main__": import sys - todos = dict( - nightly=nightly, sdist=sdist, wheel=wheel, version=lambda: print(getversion()) - ) for todo in sys.argv[1:]: todos[todo]() diff --git a/tools/pylib/_boutpp_build/boutpp_openmpi_compat.hxx b/tools/pylib/_boutpp_build/boutpp_openmpi_compat.hxx index 890cf3770d..f17cf5bf54 100644 --- a/tools/pylib/_boutpp_build/boutpp_openmpi_compat.hxx +++ b/tools/pylib/_boutpp_build/boutpp_openmpi_compat.hxx @@ -101,24 +101,30 @@ static void PyMPI_OPENMPI_dlopen_libmpi(void) { #endif #if defined(OMPI_MAJOR_VERSION) #if OMPI_MAJOR_VERSION == 3 - if (!handle) + if (!handle) { handle = dlopen("libmpi.40.dylib", mode); + } #elif OMPI_MAJOR_VERSION == 2 - if (!handle) + if (!handle) { handle = dlopen("libmpi.20.dylib", mode); + } #elif OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION >= 10 - if (!handle) + if (!handle) { handle = dlopen("libmpi.12.dylib", mode); + } #elif OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION >= 6 - if (!handle) + if (!handle) { handle = dlopen("libmpi.1.dylib", mode); + } #elif OMPI_MAJOR_VERSION == 1 - if (!handle) + if (!handle) { handle = dlopen("libmpi.0.dylib", mode); + } #endif #endif - if (!handle) + if (!handle) { handle = dlopen("libmpi.dylib", mode); + } #else /* GNU/Linux and others */ #ifdef RTLD_NOLOAD @@ -126,31 +132,40 @@ static void PyMPI_OPENMPI_dlopen_libmpi(void) { #endif #if defined(OMPI_MAJOR_VERSION) #if OMPI_MAJOR_VERSION >= 10 /* IBM Spectrum MPI */ - if (!handle) + if (!handle) { handle = dlopen("libmpi_ibm.so.2", mode); - if (!handle) + } + if (!handle) { handle = dlopen("libmpi_ibm.so.1", mode); - if (!handle) + } + if (!handle) { handle = dlopen("libmpi_ibm.so", mode); + } #elif OMPI_MAJOR_VERSION == 3 - if (!handle) + if (!handle) { handle = dlopen("libmpi.so.40", mode); + } #elif OMPI_MAJOR_VERSION == 2 - if (!handle) + if (!handle) { handle = dlopen("libmpi.so.20", mode); + } #elif OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION >= 10 - if (!handle) + if (!handle) { handle = dlopen("libmpi.so.12", mode); + } #elif OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION >= 6 - if (!handle) + if (!handle) { handle = dlopen("libmpi.so.1", mode); + } #elif OMPI_MAJOR_VERSION == 1 - if (!handle) + if (!handle) { handle = dlopen("libmpi.so.0", mode); + } #endif #endif - if (!handle) + if (!handle) { handle = dlopen("libmpi.so", mode); + } #endif } diff --git a/tools/pylib/boutconfig/__init__.py.cin b/tools/pylib/boutconfig/__init__.py.cin index 9a386c6742..d031d599b5 100644 --- a/tools/pylib/boutconfig/__init__.py.cin +++ b/tools/pylib/boutconfig/__init__.py.cin @@ -3,19 +3,18 @@ """ # Created by cmake _yesno = {"TRUE": True, "ON": True, "FALSE": False, "OFF": False} -_iyesno = {True: "yes", False: "no"} config = { "cc": "@CMAKE_C_COMPILER@", "cxx": "@CMAKE_CXX_COMPILER@", "ld": "@CMAKE_CXX_COMPILER@", "checks": "@BOUT_CHECK_LEVEL@", - "cflags": "@BOUT_CFLAGS@", - "libs": "@BOUT_LIBS@", + "cflags": "@CONFIG_CFLAGS@", + "libs": "@CONFIG_LIBS@", "version": "@BOUT_VERSION@", "git": "@BOUT_REVISION@", "idlpath": "@IDLCONFIGPATH@", - "pythonpath": "@BOUT_PYTHONPATH@", + "pythonpath": "@PYTHONCONFIGPATH@", "has_netcdf": "@BOUT_HAS_NETCDF@", "has_legacy_netcdf": "@BOUT_HAS_LEGACY_NETCDF@", "has_pnetcdf": "OFF", @@ -34,15 +33,25 @@ config = { "metric_type": "@BOUT_METRIC_TYPE@", } +for k, v in config.items(): + config[k] = ( + v.replace( + "${BOUT_INCLUDE_PATH}", "@BOUT_INCLUDE_PATH@" + ) + .replace( + "${MPARK_VARIANT_INCLUDE_PATH}", "@MPARK_VARIANT_INCLUDE_PATH@" + ) + .replace( + "${FMT_INCLUDE_PATH}", "@FMT_INCLUDE_PATH@" + ) + ) -@property -def has(): - """Get a dict of the enabled features""" - _has = {} - for k in config: - if k.startswith("has_"): - _has[k[4:]] = _yesno[config[k].upper()] - return _has + +"""Get a dict of the enabled features""" +has = {} +for k in config: + if k.startswith("has_"): + has[k[4:]] = _yesno[config[k].upper()] def isMetric2D(): diff --git a/tools/pylib/boutconfig/__init__.py.in b/tools/pylib/boutconfig/__init__.py.in index 71fa3faf74..db8a529b20 100644 --- a/tools/pylib/boutconfig/__init__.py.in +++ b/tools/pylib/boutconfig/__init__.py.in @@ -2,7 +2,7 @@ """ -_yesno = {'"yes"': True, '"no"': False} +_yesno = {'"yes"': True, '"no"': False, "yes": True, "no": False} _vars = dict( BOUT_LIB_PATH="@BOUT_LIB_PATH@", @@ -48,15 +48,11 @@ for k, v in config.items(): v = v.replace(f"${e}", s) config[k] = v - -@property -def has(): - """Get a dict of the enabled features""" - _has = {} - for k in config: - if k.startswith("has_"): - _has[k[4:]] = _yesno[config[k]] - return _has +"""Get a dict of the enabled features""" +has = {} +for k in config: + if k.startswith("has_"): + has[k[4:]] = _yesno[config[k]] def isMetric2D(): diff --git a/tools/tokamak_grids/coils/coils.cxx b/tools/tokamak_grids/coils/coils.cxx index 64e6f436ef..caf7084387 100644 --- a/tools/tokamak_grids/coils/coils.cxx +++ b/tools/tokamak_grids/coils/coils.cxx @@ -104,8 +104,9 @@ const Point AfromLine(Point start, Point end, double current, Point pos) { integral += 1. / d; } else if (i % 2 == 1) { integral += 4. / d; - } else + } else { integral += 2. / d; + } integral *= h / 3.; } } while (abs((integral - last) / (integral + last)) > 1.e-3); @@ -116,8 +117,9 @@ const Point AfromLine(Point start, Point end, double current, Point pos) { const Point AfromCoil(vector corners, double current, Point pos) { Point A; - for (int i = 0; i < corners.size(); i++) + for (int i = 0; i < corners.size(); i++) { A += AfromLine(corners[i], corners[(i + 1) % corners.size()], current, pos); + } return A; } @@ -129,8 +131,9 @@ double** matrix(int nx, int ny) { double** m; m = new double*[nx]; m[0] = new double[nx * ny]; - for (int i = 1; i < nx; i++) + for (int i = 1; i < nx; i++) { m[i] = m[i - 1] + ny; + } return m; } @@ -211,17 +214,19 @@ int main(int argc, char** argv) { int nx, ny; double** Rxy = readMatrix(dataFile, "Rxy", nx, ny); - if (!Rxy) + if (!Rxy) { return 1; + } double** Zxy = readMatrix(dataFile, "Zxy", nx, ny); - if (!Zxy) + if (!Zxy) { return 1; + } int nz = 16; // Number of points to use in Z // Loop over the grid points - for (int x = 0; x < nx; x++) - for (int y = 0; y < ny; y++) + for (int x = 0; x < nx; x++) { + for (int y = 0; y < ny; y++) { for (int z = 0; z < nz; z++) { double phi = 2. * PI * ((double)z) / ((double)nz); @@ -230,6 +235,8 @@ int main(int argc, char** argv) { // Calculate A } + } + } return 0; }