From e5157adbbd31921c3597b004b557f22f5cc99f78 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 29 Apr 2024 10:45:27 +0200 Subject: [PATCH 001/259] Fix bad merge --- include/bout/utils.hxx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/bout/utils.hxx b/include/bout/utils.hxx index 12f438c7d3..e965c5d433 100644 --- a/include/bout/utils.hxx +++ b/include/bout/utils.hxx @@ -369,14 +369,6 @@ public: return data[i.ind]; } - T& operator[](Ind3D i) { - // ny and nz are private :-( - // ASSERT2(i.nz == n3); - // ASSERT2(i.ny == n2); - ASSERT2(0 <= i.ind && i.ind < n1 * n2 * n3); - return data[i.ind]; - } - Tensor& operator=(const T& val) { for (auto& i : data) { i = val; From 25667e4f8bd6eca17219a3ed3225b6d86c62bd8a Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 30 May 2024 15:18:11 +0200 Subject: [PATCH 002/259] Update docs --- manual/sphinx/user_docs/boundary_options.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/manual/sphinx/user_docs/boundary_options.rst b/manual/sphinx/user_docs/boundary_options.rst index 57c6658891..a3cdf0078b 100644 --- a/manual/sphinx/user_docs/boundary_options.rst +++ b/manual/sphinx/user_docs/boundary_options.rst @@ -147,8 +147,10 @@ shifted``, see :ref:`sec-shifted-metric`), the recommended method is to apply boundary conditions directly to the ``yup`` and ``ydown`` parallel slices. This can be done by setting ``bndry_par_yup`` and ``bndry_par_ydown``, or ``bndry_par_all`` to set both at once. The -possible values are ``parallel_dirichlet``, ``parallel_dirichlet_O3`` -and ``parallel_neumann``. The stencils used are the same as for the +possible values are ``parallel_dirichlet_o1``, +``parallel_dirichlet_o2``, ``parallel_dirichlet_o3`` +and ``parallel_neumann_o1``, ``parallel_neumann_o2``, +``parallel_neumann_o3``. The stencils used are the same as for the standard boundary conditions without the ``parallel_`` prefix, but are applied directly to parallel slices. The boundary condition can only be applied after the parallel slices are calculated, which is usually @@ -168,7 +170,7 @@ For example, for an evolving variable ``f``, put a section in the [f] bndry_xin = dirichlet bndry_xout = dirichlet - bndry_par_all = parallel_neumann + bndry_par_all = parallel_neumann_o2 bndry_ydown = none bndry_yup = none @@ -278,7 +280,7 @@ cells of the base variable. For example, for an evolving variable [f] bndry_xin = dirichlet bndry_xout = dirichlet - bndry_par_all = parallel_dirichlet + bndry_par_all = parallel_dirichlet_o2 bndry_ydown = none bndry_yup = none @@ -289,7 +291,7 @@ communication, while the perpendicular ones before: f.applyBoundary(); mesh->communicate(f); - f.applyParallelBoundary("parallel_neumann"); + f.applyParallelBoundary("parallel_neumann_o2"); Note that during grid generation care has to be taken to ensure that there are no "short" connection lengths. Otherwise it can happen that for a point on a From 1c31c299ce4f2c8de6bb6a3922bc556b0421e6cc Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 30 May 2024 15:18:19 +0200 Subject: [PATCH 003/259] Update test --- tests/integrated/test-fci-mpi/fci_mpi.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-fci-mpi/fci_mpi.cxx b/tests/integrated/test-fci-mpi/fci_mpi.cxx index f4c26adc96..94520dd4a6 100644 --- a/tests/integrated/test-fci-mpi/fci_mpi.cxx +++ b/tests/integrated/test-fci-mpi/fci_mpi.cxx @@ -20,7 +20,7 @@ int main(int argc, char** argv) { Options::getRoot(), mesh)}; // options->get(fmt::format("input_{:d}:boundary_perp", i), temp_str, s"free_o3"); mesh->communicate(input); - input.applyParallelBoundary("parallel_neumann"); + input.applyParallelBoundary("parallel_neumann_o2"); for (int slice = -mesh->ystart; slice <= mesh->ystart; ++slice) { if (slice != 0) { Field3D tmp{0.}; From b4ebb73d275b46541b2708515e0bf7f07b13ae5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:34:27 +0000 Subject: [PATCH 004/259] Update numpy requirement from ~=2.0.0 to ~=2.1.1 Updates the requirements on [numpy](https://github.com/numpy/numpy) to permit the latest version. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst) - [Commits](https://github.com/numpy/numpy/compare/v2.0.0...v2.1.1) --- updated-dependencies: - dependency-name: numpy dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bc3d31de2b..a6e578ff69 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Jinja2~=3.1.4 -numpy~=2.0.0 +numpy~=2.1.1 scipy>=1.11.0 netcdf4~=1.7.1 matplotlib>=3.7.0 From 58d2b3aa4f571c686ed4949fda88ed31ca095e0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:27:53 +0000 Subject: [PATCH 005/259] Bump externalpackages/googletest from `0953a17` to `6dae7eb` Bumps [externalpackages/googletest](https://github.com/google/googletest) from `0953a17` to `6dae7eb`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/0953a17a4281fc26831da647ad3fcd5e21e6473b...6dae7eb4a5c3a169f3e298392bff4680224aa94a) --- updated-dependencies: - dependency-name: externalpackages/googletest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index 0953a17a42..6dae7eb4a5 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit 0953a17a4281fc26831da647ad3fcd5e21e6473b +Subproject commit 6dae7eb4a5c3a169f3e298392bff4680224aa94a From d36debf2b1e960fef22da44ab17c81a9bd016e1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:12:09 +0000 Subject: [PATCH 006/259] Update numpy requirement from ~=2.1.1 to ~=2.1.2 Updates the requirements on [numpy](https://github.com/numpy/numpy) to permit the latest version. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst) - [Commits](https://github.com/numpy/numpy/compare/v2.1.1...v2.1.2) --- updated-dependencies: - dependency-name: numpy dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a6e578ff69..3fe0712381 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Jinja2~=3.1.4 -numpy~=2.1.1 +numpy~=2.1.2 scipy>=1.11.0 netcdf4~=1.7.1 matplotlib>=3.7.0 From 94962f13ff0f2fd7e400f775e05714c748ba1b41 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Oct 2024 13:49:03 +0200 Subject: [PATCH 007/259] master branch will be 5.1.2 not 5.2.0 --- CMakeLists.txt | 2 +- tools/pylib/_boutpp_build/backend.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c2a26a07b..60d34e1ad7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ endif() # Set the version here, strip any extra tags to use in `project` # We try to use git to get a full description, inspired by setuptools_scm set(_bout_previous_version "5.1.1") -set(_bout_next_version "5.2.0") +set(_bout_next_version "5.1.2") execute_process( COMMAND "git" describe --tags --match=v${_bout_previous_version} COMMAND sed -e s/${_bout_previous_version}-/${_bout_next_version}.dev/ -e s/-/+/ diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index e89f37bb42..23e60fc583 100644 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -34,7 +34,7 @@ def getversion(): return version _bout_previous_version = "v5.1.1" - _bout_next_version = "v5.2.0" + _bout_next_version = "v5.1.2" try: try: From 2435b00f1c404efa809c55c8f3c2337f68570ba5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:43:01 +0000 Subject: [PATCH 008/259] Bump externalpackages/googletest from `6dae7eb` to `d144031` Bumps [externalpackages/googletest](https://github.com/google/googletest) from `6dae7eb` to `d144031`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/6dae7eb4a5c3a169f3e298392bff4680224aa94a...d144031940543e15423a25ae5a8a74141044862f) --- updated-dependencies: - dependency-name: externalpackages/googletest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index 6dae7eb4a5..d144031940 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit 6dae7eb4a5c3a169f3e298392bff4680224aa94a +Subproject commit d144031940543e15423a25ae5a8a74141044862f From 6206d88ab5beef5099cc56e853b05cb73fda66d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:21:55 +0000 Subject: [PATCH 009/259] Bump ZedThree/clang-tidy-review from 0.19.0 to 0.20.1 Bumps [ZedThree/clang-tidy-review](https://github.com/zedthree/clang-tidy-review) from 0.19.0 to 0.20.1. - [Release notes](https://github.com/zedthree/clang-tidy-review/releases) - [Changelog](https://github.com/ZedThree/clang-tidy-review/blob/master/CHANGELOG.md) - [Commits](https://github.com/zedthree/clang-tidy-review/compare/v0.19.0...v0.20.1) --- updated-dependencies: - dependency-name: ZedThree/clang-tidy-review dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/clang-tidy-review.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 4cdec88c83..b2f9bd7573 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.19.0 + uses: ZedThree/clang-tidy-review@v0.20.1 id: review with: build_dir: build @@ -46,4 +46,4 @@ jobs: -DBOUT_UPDATE_GIT_SUBMODULE=OFF - name: Upload clang-tidy fixes - uses: ZedThree/clang-tidy-review/upload@v0.19.0 + uses: ZedThree/clang-tidy-review/upload@v0.20.1 From 67a282fb23f9fea0035ba43811754ed7cb9957b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:21:58 +0000 Subject: [PATCH 010/259] Bump codecov/codecov-action from 4 to 5 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7ca76cc7aa..c316ba4db1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -218,7 +218,7 @@ jobs: - name: Upload coverage if: ${{ matrix.config.name == 'Coverage' }} - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 Fedora: # This is its own job as it doesn't use most of the steps of the From c9318740652d2a61351270e3ff8b86a9cf4a78f7 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 26 Nov 2024 10:00:17 +0100 Subject: [PATCH 011/259] Use PEP 625 compatible archive name --- tools/pylib/_boutpp_build/backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 23e60fc583..1fba557cdc 100644 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -198,7 +198,7 @@ def build_sdist(sdist_directory, config_settings=None): if k == "nightly": useLocalVersion = False pkgname = "boutpp-nightly" - prefix = f"{pkgname}-{getversion()}" + prefix = f"{pkgname.replace('-', '_')}-{getversion()}" fname = f"{prefix}.tar" run(f"git archive HEAD --prefix {prefix}/ -o {sdist_directory}/{fname}") _, tmp = tempfile.mkstemp(suffix=".tar") From 0f2630aa2be8d9ce4b3fe496fc541757617574e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 19:35:15 +0000 Subject: [PATCH 012/259] Update numpy requirement from ~=2.1.2 to ~=2.2.1 Updates the requirements on [numpy](https://github.com/numpy/numpy) to permit the latest version. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst) - [Commits](https://github.com/numpy/numpy/compare/v2.1.2...v2.2.1) --- updated-dependencies: - dependency-name: numpy dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3fe0712381..e7bd77a1c4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Jinja2~=3.1.4 -numpy~=2.1.2 +numpy~=2.2.1 scipy>=1.11.0 netcdf4~=1.7.1 matplotlib>=3.7.0 From d3ced6f10e5ee7a8fcee53fda89dffd9be4fa6b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 19:10:18 +0000 Subject: [PATCH 013/259] Bump externalpackages/googletest from `d144031` to `504ea69` Bumps [externalpackages/googletest](https://github.com/google/googletest) from `d144031` to `504ea69`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/d144031940543e15423a25ae5a8a74141044862f...504ea69cf7e9947be54f808a09b7b08988e84b5f) --- updated-dependencies: - dependency-name: externalpackages/googletest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index d144031940..504ea69cf7 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit d144031940543e15423a25ae5a8a74141044862f +Subproject commit 504ea69cf7e9947be54f808a09b7b08988e84b5f From e047a677bca5a26f894e60470591bcd2b9477d10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 19:50:11 +0000 Subject: [PATCH 014/259] Bump externalpackages/googletest from `504ea69` to `2b6b042` Bumps [externalpackages/googletest](https://github.com/google/googletest) from `504ea69` to `2b6b042`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/504ea69cf7e9947be54f808a09b7b08988e84b5f...2b6b042a77446ff322cd7522ca068d9f2a21c1d1) --- updated-dependencies: - dependency-name: externalpackages/googletest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index 504ea69cf7..2b6b042a77 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit 504ea69cf7e9947be54f808a09b7b08988e84b5f +Subproject commit 2b6b042a77446ff322cd7522ca068d9f2a21c1d1 From c2344046a767145c19c8b8d8cc6d6dd34d352ecc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 19:18:09 +0000 Subject: [PATCH 015/259] Bump externalpackages/boutdata from `e458cf0` to `0aaef41` Bumps [externalpackages/boutdata](https://github.com/boutproject/boutdata) from `e458cf0` to `0aaef41`. - [Release notes](https://github.com/boutproject/boutdata/releases) - [Commits](https://github.com/boutproject/boutdata/compare/e458cf0cf2af6ff68db91da39ef3e15a7e9e6b3d...0aaef417af092882ac295c4d84e4532e4a10e01f) --- updated-dependencies: - dependency-name: externalpackages/boutdata dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/boutdata | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/boutdata b/externalpackages/boutdata index e458cf0cf2..0aaef417af 160000 --- a/externalpackages/boutdata +++ b/externalpackages/boutdata @@ -1 +1 @@ -Subproject commit e458cf0cf2af6ff68db91da39ef3e15a7e9e6b3d +Subproject commit 0aaef417af092882ac295c4d84e4532e4a10e01f From 0e328fc4f2e4d3e8242fda37230f87118b0c847a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 19:56:15 +0000 Subject: [PATCH 016/259] Update pygithub requirement from ~=2.4 to ~=2.6 Updates the requirements on [pygithub](https://github.com/pygithub/pygithub) to permit the latest version. - [Release notes](https://github.com/pygithub/pygithub/releases) - [Changelog](https://github.com/PyGithub/PyGithub/blob/main/doc/changes.rst) - [Commits](https://github.com/pygithub/pygithub/compare/v2.4.0...v2.6.0) --- updated-dependencies: - dependency-name: pygithub dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements_maint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_maint.txt b/requirements_maint.txt index 9f4ddc3699..e6ba00ce48 100644 --- a/requirements_maint.txt +++ b/requirements_maint.txt @@ -1,3 +1,3 @@ -pygithub~=2.4 +pygithub~=2.6 ruamel-yaml~=0.18 Unidecode~=1.3 From bfc8ed87892cab19dbcb7c2a9021b563be8e000b Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 7 Jan 2025 11:06:30 +0100 Subject: [PATCH 017/259] CI: Install zoidberg and new versions --- requirements.txt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index e7bd77a1c4..52d3076d58 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,9 @@ -Jinja2~=3.1.4 -numpy~=2.2.1 -scipy>=1.11.0 -netcdf4~=1.7.1 +Jinja2>=3.1.4 +numpy>=2.0.0 +scipy>=1.14.1 +netcdf4>=1.7.1 matplotlib>=3.7.0 -Cython~=3.0.0 -boututils~=0.2.1 -boutdata~=0.2.1 +Cython>=3.0.0 +boututils>=0.2.1 +boutdata>=0.2.1 +zoidberg>=0.2.2 From 33067dd40f96e91085b51a9dc49b5379216c53e8 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 7 Jan 2025 13:13:15 +0100 Subject: [PATCH 018/259] DEBUG: monkey patch zoidberg --- tests/MMS/spatial/fci/runtest | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 3db54a3870..fd6e0899d8 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -74,6 +74,16 @@ for nslice in nslices: # Create the grid grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) # Make and write maps + from scipy.interpolate import RectBivariateSpline as RBS + + def myRBS(a, b, c): + mx, my = c.shape + kx = max(mx - 1, 1) + kx = min(kx, 3) + print(c.shape, kx) + return RBS(a, b, c, kx=kx) + + zb.poloidal_grid.RectBivariateSpline = myRBS maps = zb.make_maps(grid, field, nslice=nslice, quiet=True) zb.write_maps( grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True From 0416ba3cb43d0a16b38d79b740751203a5080ccc Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 7 Jan 2025 13:58:17 +0100 Subject: [PATCH 019/259] Specify MXG=1 --- tests/MMS/spatial/fci/runtest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index fd6e0899d8..a588c6800a 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -61,7 +61,7 @@ for nslice in nslices: # Note that the Bz and Bzprime parameters here must be the same as in mms.py field = zb.field.Slab(Bz=0.05, Bzprime=0.1) # Create rectangular poloidal grids - poloidal_grid = zb.poloidal_grid.RectangularPoloidalGrid(nx, n, 0.1, 1.0) + poloidal_grid = zb.poloidal_grid.RectangularPoloidalGrid(nx, n, 0.1, 1.0, MXG=1) # Set the ylength and y locations ylength = 10.0 @@ -84,7 +84,7 @@ for nslice in nslices: return RBS(a, b, c, kx=kx) zb.poloidal_grid.RectBivariateSpline = myRBS - maps = zb.make_maps(grid, field, nslice=nslice, quiet=True) + maps = zb.make_maps(grid, field, nslice=nslice, quiet=True, MXG=1) zb.write_maps( grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True ) From bea060e4cb687f797ae42473a46631e09f004ef4 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 7 Jan 2025 17:05:02 +0100 Subject: [PATCH 020/259] Remove debug statement --- tests/MMS/spatial/fci/runtest | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index a588c6800a..1b7b74a867 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -80,7 +80,6 @@ for nslice in nslices: mx, my = c.shape kx = max(mx - 1, 1) kx = min(kx, 3) - print(c.shape, kx) return RBS(a, b, c, kx=kx) zb.poloidal_grid.RectBivariateSpline = myRBS From a1df60915efe150902c1858f7e3b5b21ff749c3d Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 7 Jan 2025 17:05:11 +0100 Subject: [PATCH 021/259] Remove python2 compat --- tests/MMS/spatial/fci/runtest | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 1b7b74a867..b5ca2db5c5 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -6,9 +6,6 @@ # Cores: 2 # requires: zoidberg -from __future__ import division -from __future__ import print_function - from boututils.run_wrapper import build_and_log, launch_safe from boutdata.collect import collect import boutconfig as conf From b6a91b81979c0b5fc3addf1eb99dd9d33e3b21d0 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 8 Jan 2025 09:26:26 +0100 Subject: [PATCH 022/259] CI: Try limiting multithreading --- .ci_fedora.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.ci_fedora.sh b/.ci_fedora.sh index 974a23a362..77e7f45055 100755 --- a/.ci_fedora.sh +++ b/.ci_fedora.sh @@ -59,7 +59,11 @@ else export OMPI_MCA_rmaps_base_oversubscribe=yes export PRTE_MCA_rmaps_default_mapping_policy=:oversubscribe export TRAVIS=true + # Try limiting openmp threads export FLEXIBLAS=NETLIB + export MKL_NUM_THREADS=1 + export NUMEXPR_NUM_THREADS=1 + export OMP_NUM_THREADS=1 cd cd BOUT-dev echo "starting configure" From 05f030c771b00f8bc6b3d17680c41f2847e8c7bd Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:13:59 +0000 Subject: [PATCH 023/259] Apply black changes --- tests/integrated/test_suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test_suite b/tests/integrated/test_suite index 307a8d84b3..77ad7882c4 100755 --- a/tests/integrated/test_suite +++ b/tests/integrated/test_suite @@ -188,7 +188,7 @@ class Test(threading.Thread): self.output += "\n(It is likely that a timeout occured)" else: # ❌ Failed - print("\u274C", end="") # No newline + print("\u274c", end="") # No newline print(" %7.3f s" % (time.time() - self.local.start_time), flush=True) def _cost(self): From 8132089ec8154036b827712192ff6182900e5109 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 3 Mar 2022 15:51:50 +0100 Subject: [PATCH 024/259] Always use python3 --- cmake/FindCython.cmake | 2 +- cmake/FindNumpy.cmake | 16 ++++++++-------- manual/sphinx/conf.py | 2 +- tools/pylib/_boutpp_build/CMakeLists.txt | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cmake/FindCython.cmake b/cmake/FindCython.cmake index 76f43480d9..3b98cde89e 100644 --- a/cmake/FindCython.cmake +++ b/cmake/FindCython.cmake @@ -10,7 +10,7 @@ # CYTHON_FOUND - true if Cython was found # CYTHON_VERSION - Cython version -execute_process(COMMAND ${Python_EXECUTABLE} -c "import cython ; print(cython.__version__)" +execute_process(COMMAND ${Python3_EXECUTABLE} -c "import cython ; print(cython.__version__)" RESULT_VARIABLE _cython_runs OUTPUT_VARIABLE CYTHON_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/cmake/FindNumpy.cmake b/cmake/FindNumpy.cmake index 201bc19221..250eff5959 100644 --- a/cmake/FindNumpy.cmake +++ b/cmake/FindNumpy.cmake @@ -12,32 +12,32 @@ # Numpy_INCLUDE_DIR -find_package(Python 3.6 COMPONENTS Interpreter Development) +find_package(Python3 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}) +if (NOT Python3_FOUND) + message(STATUS "Could not find numpy as python3 was not found. Maybe the developement package is missing?") + set(Numpy_FOUND ${Python3_FOUND}) return() endif() if (NOT Numpy_FOUND) - execute_process(COMMAND ${Python_EXECUTABLE} -c "import numpy ; print(numpy.__version__)" + execute_process(COMMAND ${Python3_EXECUTABLE} -c "import numpy ; print(numpy.__version__)" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE Numpy_VERSION ) - execute_process(COMMAND ${Python_EXECUTABLE} -c "import numpy ; print(numpy.get_include())" + execute_process(COMMAND ${Python3_EXECUTABLE} -c "import numpy ; print(numpy.get_include())" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _numpy_include_dirs ) endif() if (Numpy_DEBUG) - message(STATUS "Looking for numpy headers in: ${_numpy_include_dirs} ${PYTHON_INCLUDE_DIR}") + message(STATUS "Looking for numpy headers in: ${_numpy_include_dirs} ${Python3_INCLUDE_DIRS}") endif() find_path(Numpy_INCLUDE_DIR numpy/arrayobject.h - PATHS "${_numpy_include_dirs}" "${PYTHON_INCLUDE_DIR}" + PATHS "${_numpy_include_dirs}" "${Python3_INCLUDE_DIRS}" PATH_SUFFIXES numpy/core/include ) diff --git a/manual/sphinx/conf.py b/manual/sphinx/conf.py index 5adf3c3633..55d059feba 100755 --- a/manual/sphinx/conf.py +++ b/manual/sphinx/conf.py @@ -88,7 +88,7 @@ def __getattr__(cls, name): + " -DBOUT_UPDATE_GIT_SUBMODULE=OFF" + " -DBOUT_TESTS=OFF" + " -DBOUT_ALLOW_INSOURCE_BUILD=ON" - + f" -DPython_ROOT_DIR={pydir}" + + f" -DPython3_ROOT_DIR={pydir}" + f" -Dmpark_variant_DIR={pwd}/externalpackages/mpark.variant/" + f" -Dfmt_DIR={pwd}/externalpackages/fmt/" ) diff --git a/tools/pylib/_boutpp_build/CMakeLists.txt b/tools/pylib/_boutpp_build/CMakeLists.txt index 6b88986a28..3be2a5d2aa 100644 --- a/tools/pylib/_boutpp_build/CMakeLists.txt +++ b/tools/pylib/_boutpp_build/CMakeLists.txt @@ -25,7 +25,7 @@ bout_python_maybe_error(${Cython_FOUND} Cython) find_package(Bash) bout_python_maybe_error(${Bash_FOUND} Bash) -execute_process(COMMAND ${Python_EXECUTABLE} -c "import jinja2" +execute_process(COMMAND ${Python3_EXECUTABLE} -c "import jinja2" RESULT_VARIABLE jinja2_FOUND) if (jinja2_FOUND EQUAL 0) # We have jinja2 - all good @@ -33,7 +33,7 @@ else() bout_python_maybe_error(OFF jinja2) endif() -execute_process(COMMAND ${Python_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX')[:-3])" +execute_process(COMMAND ${Python3_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX')[:-3])" RESULT_VARIABLE PYTHON_WORKING OUTPUT_VARIABLE PYTHON_EXT_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE @@ -73,7 +73,7 @@ foreach(file IN LISTS files) #message(FATAL_ERROR "${gen} ${src}/${file}.jinja") add_custom_command(OUTPUT ${gen} COMMAND ${CMAKE_COMMAND} -E make_directory ${tar} - COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${tar}/..:\${PYTHONPATH} ${Python_EXECUTABLE} generate.py ${file}.jinja ${gen} + COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${tar}/..:\${PYTHONPATH} ${Python3_EXECUTABLE} generate.py ${file}.jinja ${gen} DEPENDS ${src}/${file}.jinja DEPENDS ${src}/helper.py DEPENDS ${src}/resolve_enum_inv.pyx.jinja @@ -93,8 +93,7 @@ endforeach() add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libboutpp.cpp COMMAND ${CMAKE_COMMAND} -E copy boutpp.pyx libboutpp.pyx - COMMAND ${Python_EXECUTABLE} -m cython libboutpp.pyx --cplus -3 -X binding=True -X embedsignature=True - COMMENT "Cythonizing python interface" + COMMAND ${Python3_EXECUTABLE} -m cython libboutpp.pyx --cplus -3 -X binding=True -X embedsignature=True WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${boutpp_depends} ) @@ -120,5 +119,6 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/boutpp.py DESTINATION ${CMAKE_INSTALL_PYTHON_SITEARCH}/boutpp/ RENAME __init__.py ) + target_link_libraries(boutpp${PYTHON_EXT_SUFFIX} bout++) -target_include_directories(boutpp${PYTHON_EXT_SUFFIX} PRIVATE $ ${Numpy_INCLUDE_DIRS} ${Python_INCLUDE_DIRS}) +target_include_directories(boutpp${PYTHON_EXT_SUFFIX} PRIVATE $ ${Numpy_INCLUDE_DIRS} ${Python3_INCLUDE_DIRS}) From 401319b0653b775fa6caf97844c21574b11e62c5 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 22 Mar 2024 12:43:51 +0100 Subject: [PATCH 025/259] expose setConditionallyUsed --- tools/pylib/_boutpp_build/bout_options.pxd | 1 + tools/pylib/_boutpp_build/boutpp.pyx.jinja | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/pylib/_boutpp_build/bout_options.pxd b/tools/pylib/_boutpp_build/bout_options.pxd index ba5e64c8e3..c4de2a9d37 100644 --- a/tools/pylib/_boutpp_build/bout_options.pxd +++ b/tools/pylib/_boutpp_build/bout_options.pxd @@ -52,6 +52,7 @@ cdef extern from "bout/options.hxx": void get(string, double&, double) void get(string, bool&, bool) void cleanCache() + void setConditionallyUsed() cdef extern from "bout/optionsreader.hxx": diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index 657e2f28c1..ae4d9212a8 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -1209,8 +1209,9 @@ def finalise(): else: for ourClass in ourClasses: if isinstance(obj, ourClass): - ourClass.__boutpp_dealloc(obj) - break + if hasattr(ourClass, "__boutpp_dealloc"): + ourClass.__boutpp_dealloc(obj) + break del objects # Actually finalise if wasInit: @@ -1715,6 +1716,15 @@ cdef class Options: opt.get(key, ret_str, default_) return ret_str.decode() + def setConditionallyUsed(self): + """Set the attribute "conditionally used" to be true for \p options + and all its children/sections, causing `Options::getUnused` to + assume those options have been used. This is useful to ignore + options when checking for typos etc. + """ + cdef c.Options* opt = self.cobj + opt.setConditionallyUsed() + def __dealloc__(self): self.__boutpp_dealloc() From b1251bb281977c138c24ba2425da94c1679ec786 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 22 Mar 2024 12:46:01 +0100 Subject: [PATCH 026/259] Ensure errors in solve and rhs are catchable Fixes GH#2890 --- tools/pylib/_boutpp_build/boutcpp.pxd.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutcpp.pxd.jinja b/tools/pylib/_boutpp_build/boutcpp.pxd.jinja index c94fd14a17..dafdd51c5f 100644 --- a/tools/pylib/_boutpp_build/boutcpp.pxd.jinja +++ b/tools/pylib/_boutpp_build/boutcpp.pxd.jinja @@ -148,10 +148,10 @@ cdef extern from "bout/physicsmodel.hxx": ctypedef void (*Method)(void *param, void *user_data) cdef extern from "helper.h": cppclass PythonModel(PhysicsModel): - int rhs(double t) + int rhs(double t) except +raise_bout_py_error void pyinit() void free() - void solve() + void solve() except +raise_bout_py_error Solver * getSolver() void set_rhs_func(PythonModelCallback*) void set_init_func(PythonModelCallback*) From d619adf26b7134ad7f4dd7396beb6db8d832bcc4 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 25 Mar 2024 09:29:16 +0100 Subject: [PATCH 027/259] Do not use python preserved __ prefix --- tools/pylib/_boutpp_build/boutpp.pyx.jinja | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index ae4d9212a8..de01748b6f 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -583,9 +583,9 @@ cdef class {{ field.field_type }}: {% endfor %} def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.isSelfOwned and self.cobj != NULL: del self.cobj self.cobj = NULL @@ -645,9 +645,9 @@ cdef class {{ vec }}: def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.isSelfOwned and self.cobj != NULL: del self.cobj self.cobj=NULL @@ -742,9 +742,9 @@ cdef class Mesh: return msh def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.cobj and self.isSelfOwned: del self.cobj self.cobj = NULL @@ -850,9 +850,9 @@ cdef class Coordinates: {% endfor %} def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.cobj and self.isSelfOwned: del self.cobj self.cobj = NULL @@ -931,9 +931,9 @@ cdef class FieldFactory: checkInit() cobj=< c.FieldFactory*>0 def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.cobj != NULL: del self.cobj self.cobj = NULL @@ -965,9 +965,9 @@ cdef class PythonModelCallback: self.cobj = new c.PythonModelCallback(callback, method) def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.cobj: del self.cobj self.cobj = NULL @@ -1037,12 +1037,12 @@ cdef class PhysicsModelBase(object): self.cmodel.set_init_func(self.callbackinit) def __dealloc__(self): - if hasattr(self, "__boutpp_dealloc"): - self.__boutpp_dealloc() + if hasattr(self, "_boutpp_dealloc"): + self._boutpp_dealloc() else: - PhysicsModelBase.__boutpp_dealloc(self) + PhysicsModelBase._boutpp_dealloc(self) - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.cmodel != 0: self.cmodel.free() del self.cmodel @@ -1123,8 +1123,8 @@ class PhysicsModel(PhysicsModelBase): def __dealloc__(self): super(PhysicsModel,self).__dealloc__() - def __boutpp_dealloc(self): - super(PhysicsModel,self).__boutpp_dealloc() + def _boutpp_dealloc(self): + super(PhysicsModel,self)._boutpp_dealloc() cdef extern from "bout/bout.hxx": int BoutInitialise(int&, char **&) except +raise_bout_py_error @@ -1204,13 +1204,13 @@ def finalise(): PythonModelCallback) for obj in objects: if isinstance(obj, ourClasses): - if hasattr(obj, "__boutpp_dealloc"): - obj.__boutpp_dealloc() + if hasattr(obj, "_boutpp_dealloc"): + obj._boutpp_dealloc() else: for ourClass in ourClasses: if isinstance(obj, ourClass): - if hasattr(ourClass, "__boutpp_dealloc"): - ourClass.__boutpp_dealloc(obj) + if hasattr(ourClass, "_boutpp_dealloc"): + ourClass._boutpp_dealloc(obj) break del objects # Actually finalise @@ -1726,9 +1726,9 @@ cdef class Options: opt.setConditionallyUsed() def __dealloc__(self): - self.__boutpp_dealloc() + self._boutpp_dealloc() - def __boutpp_dealloc(self): + def _boutpp_dealloc(self): if self.isSelfOwned and self.cobj != NULL: del self.cobj self.cobj = NULL From c5789dafb9c5a8b04ec17c74b5a3caa2feb785fe Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 12 Dec 2024 15:42:13 +0100 Subject: [PATCH 028/259] make backend executable --- tools/pylib/_boutpp_build/backend.py | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 tools/pylib/_boutpp_build/backend.py diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py old mode 100644 new mode 100755 index 1fba557cdc..02aeb22b7e --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -1,3 +1,5 @@ +#!/bin/python3 + import os # corelib import glob # corelib import hashlib # corelib From e6a02c6b0a464c0bddc049d63ec78fef731cf835 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 12 Dec 2024 15:41:53 +0100 Subject: [PATCH 029/259] Print the help if an invalid argument is given --- tools/pylib/_boutpp_build/backend.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 02aeb22b7e..b367a4bdf8 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -370,4 +370,7 @@ def help(): import sys for todo in sys.argv[1:]: + if todo not in todos: + help() + sys.exit(1) todos[todo]() From fd25df7bd95cf670ded169285b442a2b110ec0b2 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 12 Dec 2024 15:41:18 +0100 Subject: [PATCH 030/259] Make printVersion a function This ensures we have documentation for it --- tools/pylib/_boutpp_build/backend.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index b367a4bdf8..0c1e611a2f 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -350,12 +350,19 @@ def help(): print(fmt % row) +def printVersion(): + """ + print the version + """ + print(getversion()) + + todos = dict( nightly=nightly, sdist=sdist, wheel=wheel, dist=dist, - version=lambda: print(getversion()), + version=printVersion, help=help, ) todos.update( From 4b078626b16a2f57e1ec07a85755f12b9eecda83 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 10 Dec 2024 10:52:40 +0100 Subject: [PATCH 031/259] Add delay to python interface This is to ensure that all MPI routines are called before MPI_Finalise is called. Resolves: gh#3041 --- tools/pylib/_boutpp_build/boutpp.pyx.jinja | 149 +++++++++++---------- 1 file changed, 81 insertions(+), 68 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index de01748b6f..6ffecd3596 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -16,11 +16,49 @@ from cython.operator import dereference as deref import numbers import sys import gc +from time import sleep size_t = np.uint cdef extern from "boutexception_helper.hxx": - cdef void raise_bout_py_error() + cdef void raise_bout_py_error() + +cdef class BOUTppBase: + """ + Base class that provides some mechanism for deallocation + """ + cdef c.bool _is_freed + cdef c.bool _is_init + def __cinit__(self, c.bool init=True): + self._is_freed = False + self._is_init = init + + def _boutpp_dealloc(self): + self._is_freed = True + + def _boutpp_wait_freed(self): + while not self._is_freed: + sleep(0.001) + +{% macro dealloc(self=False, uniquePtr=False) %} + def __dealloc__(self): + self._boutpp_dealloc() + + def _boutpp_dealloc(self): +{% if self %} + if self.isSelfOwned and self.cobj != NULL: +{% else %} + if self.cobj != NULL: +{% endif %} +{% if uniquePtr %} + self.cobj.release() +{% else %} + del self.cobj + self.cobj = NULL +{% endif %} + super()._boutpp_dealloc() +{% endmacro %} + {% for field in fields %} cdef extern from "helper.h": @@ -60,7 +98,7 @@ cdef {{ field.field_type }} {{ field.fdd }}FromPtr(c.{{ field.field_type }}* i): f.isSelfOwned = False return f -cdef class {{ field.field_type }}: +cdef class {{ field.field_type }}(BOUTppBase): """ The {{ field.field_type }} class """ @@ -228,6 +266,7 @@ cdef class {{ field.field_type }}: if obj: self.cobj = obj.cobj self.isSelfOwned=True + super().__cinit__() def set(self, data, ignoreDataType=False): """ @@ -582,23 +621,18 @@ cdef class {{ field.field_type }}: self.cobj.{{ boundaryMethod }}() {% endfor %} - def __dealloc__(self): - self._boutpp_dealloc() - - def _boutpp_dealloc(self): - if self.isSelfOwned and self.cobj != NULL: - del self.cobj - self.cobj = NULL +{{ dealloc(True) }} @property def shape(self): return {{ field.makelist("self.cobj.getN$d()") }} {% endfor %} + {% for vec in vecs %} cdef extern from "helper.h": c.{{ vec.field }} c_mul_{{ vec }}_{{ vec }}(c.{{ vec }} *, c.{{ vec }} *) except + -cdef class {{ vec }}: +cdef class {{ vec }}(BOUTppBase): """ {{ vec }} class @@ -642,16 +676,7 @@ cdef class {{ vec }}: {% endfor %} return data_ - - - def __dealloc__(self): - self._boutpp_dealloc() - - def _boutpp_dealloc(self): - if self.isSelfOwned and self.cobj != NULL: - del self.cobj - self.cobj=NULL - +{{ dealloc(True) }} cdef {{ vec }} {{ vec.vdd }}FromObj(c.{{ vec }} i): v={{ vec }}() @@ -667,7 +692,7 @@ cdef extern from "helper.h": c.Field3D c_Grad_perp_dot_Grad_perp(c.Field3D,c.Field3D); void c_mesh_normalise(c.Mesh* , double) -cdef class Mesh: +cdef class Mesh(BOUTppBase): """ Mesh class @@ -741,13 +766,7 @@ cdef class Mesh: msh.isSelfOwned = False return msh - def __dealloc__(self): - self._boutpp_dealloc() - - def _boutpp_dealloc(self): - if self.cobj and self.isSelfOwned: - del self.cobj - self.cobj = NULL +{{ dealloc(True) }} cdef getFactory(self): """ @@ -822,7 +841,7 @@ cdef Coordinates coordsFromPtr(c.Coordinates * obj): coords.isSelfOwned = False return coords -cdef class Coordinates: +cdef class Coordinates(BOUTppBase): """ Contains information about geometry, such as metric tensors """ @@ -849,15 +868,9 @@ cdef class Coordinates: self.{{f}} = {{ metric_field.fdd }}FromPtr(&self.cobj.{{f}}) {% endfor %} - def __dealloc__(self): - self._boutpp_dealloc() - - def _boutpp_dealloc(self): - if self.cobj and self.isSelfOwned: - del self.cobj - self.cobj = NULL +{{ dealloc(True) }} -cdef class Laplacian: +cdef class Laplacian(BOUTppBase): """ Laplacian inversion solver @@ -867,7 +880,7 @@ cdef class Laplacian: """ cdef unique_ptr[c.Laplacian] cobj cdef c.bool isSelfOwned - def __init__(self,section=None): + def __init__(self, section=None): """ Initialiase a Laplacian solver @@ -882,7 +895,8 @@ cdef class Laplacian: else: self.cobj = c.Laplacian.create(NULL) self.isSelfOwned = True - def solve(self,Field3D x, Field3D guess): + + def solve(self, Field3D x, Field3D guess): """ Calculate the Laplacian inversion @@ -925,18 +939,15 @@ cdef class Laplacian: deref(self.cobj).setCoef{{ coeff }}({{ coeff }}.cobj[0]) {% endfor %} -cdef class FieldFactory: +{{ dealloc(True, uniquePtr=True) }} + +cdef class FieldFactory(BOUTppBase): cdef c.FieldFactory * cobj def __init__(self): checkInit() cobj=< c.FieldFactory*>0 - def __dealloc__(self): - self._boutpp_dealloc() - def _boutpp_dealloc(self): - if self.cobj != NULL: - del self.cobj - self.cobj = NULL +{{ dealloc() }} cdef void callback(void * parameter, void * method) with gil: cdef double time = (parameter)[0] @@ -953,7 +964,7 @@ cdef void callback(void * parameter, void * method) with gil: ctypedef void (*Method)(void *param) -cdef class PythonModelCallback: +cdef class PythonModelCallback(BOUTppBase): """Needed for callbacks from C++ to python""" cdef c.PythonModelCallback * cobj @@ -963,21 +974,16 @@ cdef class PythonModelCallback: # "method" :: The effective method passed by the Python user checkInit() self.cobj = new c.PythonModelCallback(callback, method) + self.__cinit__() - def __dealloc__(self): - self._boutpp_dealloc() - - def _boutpp_dealloc(self): - if self.cobj: - del self.cobj - self.cobj = NULL +{{ dealloc() }} cpdef void execute(self, parameter): # "parameter" :: The parameter to be passed to the "method" self.cobj.cy_execute(parameter) -cdef class PhysicsModelBase(object): +cdef class PhysicsModelBase(BOUTppBase): """The PhysicsModelBase in python - better use the PhysicsModel class""" cdef c.PythonModel * cmodel cdef c.PythonModelCallback * callback @@ -1049,6 +1055,7 @@ cdef class PhysicsModelBase(object): del self.callback del self.callbackinit self.cmodel = 0 + super()._boutpp_dealloc() class PhysicsModel(PhysicsModelBase): """ @@ -1121,10 +1128,10 @@ class PhysicsModel(PhysicsModelBase): pass def __dealloc__(self): - super(PhysicsModel,self).__dealloc__() + super().__dealloc__() def _boutpp_dealloc(self): - super(PhysicsModel,self)._boutpp_dealloc() + super()._boutpp_dealloc() cdef extern from "bout/bout.hxx": int BoutInitialise(int&, char **&) except +raise_bout_py_error @@ -1199,9 +1206,11 @@ def finalise(): wasInit = _isInit _isInit = False objects = gc.get_objects() - ourClasses = (Coordinates, Field2D, Field3D, Mesh, Options, - PhysicsModel, PhysicsModelBase, Vector2D, Vector3D, - PythonModelCallback) + ourClasses = ( + Field2D, Field3D, Vector2D, Vector3D, Mesh, Coordinates, + Laplacian, FieldFactory, PythonModelCallback, PhysicsModel, + PhysicsModelBase, PythonModelCallback, Options, BOUTppBase, + ) for obj in objects: if isinstance(obj, ourClasses): if hasattr(obj, "_boutpp_dealloc"): @@ -1212,6 +1221,16 @@ def finalise(): if hasattr(ourClass, "_boutpp_dealloc"): ourClass._boutpp_dealloc(obj) break + for obj in objects: + if isinstance(obj, ourClasses): + if hasattr(obj, "_boutpp_wait_dealloc"): + obj._boutpp_wait_dealloc() + else: + for ourClass in ourClasses: + if isinstance(obj, ourClass): + if hasattr(ourClass, "_boutpp_wait_dealloc"): + ourClass._boutpp_wait_dealloc(obj) + break del objects # Actually finalise if wasInit: @@ -1522,7 +1541,7 @@ def setOption(name, value, source="PyInterface", force=False): root = Options.root() root.set(name, value, source, force) -cdef class Options: +cdef class Options(BOUTppBase): """ The Options class """ @@ -1725,13 +1744,7 @@ cdef class Options: cdef c.Options* opt = self.cobj opt.setConditionallyUsed() - def __dealloc__(self): - self._boutpp_dealloc() - - def _boutpp_dealloc(self): - if self.isSelfOwned and self.cobj != NULL: - del self.cobj - self.cobj = NULL +{{ dealloc(True) }} def writeDefaultOutputFile(options: Options): From ec45eb5ca4a1f62edb4634496a3f7954e8a65f83 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 10 Dec 2024 11:12:59 +0100 Subject: [PATCH 032/259] Allow abitrary arguments to base __cinit__ --- tools/pylib/_boutpp_build/boutpp.pyx.jinja | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index 6ffecd3596..639d4ea4dd 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -28,10 +28,8 @@ cdef class BOUTppBase: Base class that provides some mechanism for deallocation """ cdef c.bool _is_freed - cdef c.bool _is_init - def __cinit__(self, c.bool init=True): + def __cinit__(self, *args, **kwargs): self._is_freed = False - self._is_init = init def _boutpp_dealloc(self): self._is_freed = True From 536bd2403962043ef5cf0281c7cc5d1fbdb7a557 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 10 Dec 2024 11:15:08 +0100 Subject: [PATCH 033/259] cinit is always called, do not need to call it --- tools/pylib/_boutpp_build/boutpp.pyx.jinja | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index 639d4ea4dd..083dae4688 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -259,12 +259,11 @@ cdef class {{ field.field_type }}(BOUTppBase): f.setAll(data, ignoreDataType=ignoreDataType) return f - def __cinit__(self,{{ field.field_type }} obj=None): + def __cinit__(self, {{ field.field_type }} obj=None): self.cobj = NULL if obj: self.cobj = obj.cobj - self.isSelfOwned=True - super().__cinit__() + self.isSelfOwned = True def set(self, data, ignoreDataType=False): """ From 8daff5b139c9bb3e0e2ec5757f256155795f59a0 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 12 Dec 2024 15:37:58 +0100 Subject: [PATCH 034/259] Use generated code, to avoid having to deal with inheritance --- tools/pylib/_boutpp_build/boutpp.pyx.jinja | 239 +++++++++------------ 1 file changed, 105 insertions(+), 134 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index 083dae4688..3ae6dfc47d 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -23,38 +23,52 @@ size_t = np.uint cdef extern from "boutexception_helper.hxx": cdef void raise_bout_py_error() -cdef class BOUTppBase: - """ - Base class that provides some mechanism for deallocation - """ - cdef c.bool _is_freed - def __cinit__(self, *args, **kwargs): - self._is_freed = False - - def _boutpp_dealloc(self): - self._is_freed = True - +{% macro wait() %} def _boutpp_wait_freed(self): while not self._is_freed: sleep(0.001) +{% endmacro %} -{% macro dealloc(self=False, uniquePtr=False) %} +{% macro dealloc(extra_dealloc='', uniquePtr=False) %} def __dealloc__(self): self._boutpp_dealloc() def _boutpp_dealloc(self): -{% if self %} +{{ extra_dealloc | indent(width=8) }} if self.isSelfOwned and self.cobj != NULL: -{% else %} - if self.cobj != NULL: -{% endif %} {% if uniquePtr %} self.cobj.release() {% else %} del self.cobj self.cobj = NULL {% endif %} - super()._boutpp_dealloc() + +{{ wait() }} +{% endmacro %} + +{% macro class(name, init="", extra_dealloc="", defaultSO=True, data="", uniquePtr=False, init_args="*args, **kwargs", + comment="") %} +cdef class {{ name }}{{ "(" ~ base ~ ")" if base else "" }}: + """ +{% if comment %} +{{ comment | indent }} +{% else %} + The {{ name }} class +{% endif %} + """ + cdef {{ "unique_ptr[c." ~ name ~ "]" if uniquePtr else "c." ~ name ~ "* " }} cobj + cdef c.bool isSelfOwned + cdef c.bool _is_freed + {{ data | indent }} + def __cinit__(self, {{ init_args}}): + self._is_freed = False +{% if not uniquePtr and cobj %} + self.isSelfOwned = {{ defaultSO }} + self.cobj = NULL +{% endif %} +{{ init | indent(width=8) }} + +{{ dealloc(extra_dealloc=extra_dealloc, uniquePtr=uniquePtr) }} {% endmacro %} {% for field in fields %} @@ -96,12 +110,8 @@ cdef {{ field.field_type }} {{ field.fdd }}FromPtr(c.{{ field.field_type }}* i): f.isSelfOwned = False return f -cdef class {{ field.field_type }}(BOUTppBase): - """ - The {{ field.field_type }} class - """ - cdef c.{{ field.field_type }} * cobj - cdef c.bool isSelfOwned + +{{ class(field.field_type) }} @classmethod def fromMesh(cls, mesh=None): @@ -259,12 +269,6 @@ cdef class {{ field.field_type }}(BOUTppBase): f.setAll(data, ignoreDataType=ignoreDataType) return f - def __cinit__(self, {{ field.field_type }} obj=None): - self.cobj = NULL - if obj: - self.cobj = obj.cobj - self.isSelfOwned = True - def set(self, data, ignoreDataType=False): """ Set all data of the {{ field.field_type }} @@ -400,7 +404,7 @@ cdef class {{ field.field_type }}(BOUTppBase): Returns ------- - {{ field.field_type }} + {{ field.field_type }} exponential of the field to the power of the exponential """ if other is not None: @@ -618,7 +622,6 @@ cdef class {{ field.field_type }}(BOUTppBase): self.cobj.{{ boundaryMethod }}() {% endfor %} -{{ dealloc(True) }} @property def shape(self): @@ -629,14 +632,8 @@ cdef class {{ field.field_type }}(BOUTppBase): cdef extern from "helper.h": c.{{ vec.field }} c_mul_{{ vec }}_{{ vec }}(c.{{ vec }} *, c.{{ vec }} *) except + -cdef class {{ vec }}(BOUTppBase): - """ - {{ vec }} class +{{ class(vec) }} - A vector of {{ vec.field }} - """ - cdef c.{{ vec }} * cobj - cdef c.bool isSelfOwned {% for d in "xyz" %} @property def {{ d }}(self): @@ -673,8 +670,6 @@ cdef class {{ vec }}(BOUTppBase): {% endfor %} return data_ -{{ dealloc(True) }} - cdef {{ vec }} {{ vec.vdd }}FromObj(c.{{ vec }} i): v={{ vec }}() v.cobj = new c.{{ vec }}( i) @@ -689,19 +684,18 @@ cdef extern from "helper.h": c.Field3D c_Grad_perp_dot_Grad_perp(c.Field3D,c.Field3D); void c_mesh_normalise(c.Mesh* , double) -cdef class Mesh(BOUTppBase): - """ - Mesh class - Contains information about geometry. - It contains also the coordinates and is responsible for taking deriavtives. - """ - cdef c.Mesh * cobj; - cdef c.bool isSelfOwned - cdef double isNormalised - cdef FieldFactory factory - cdef Coordinates _coords - cdef options +{{ class("Mesh", comment=""" +Mesh class + +Contains information about geometry. +It contains also the coordinates and is responsible for taking deriavtives. +""", data=""" +cdef double isNormalised +cdef FieldFactory factory +cdef Coordinates _coords +cdef options +""") }} def __init__(self, create=True, section=None, options=None): """ @@ -723,7 +717,7 @@ cdef class Mesh(BOUTppBase): global Options object is used. """ checkInit() - self.cobj=0 + self.cobj = 0 cdef c.string tmp cdef c.Options * opt = NULL self.isSelfOwned = False @@ -763,8 +757,6 @@ cdef class Mesh(BOUTppBase): msh.isSelfOwned = False return msh -{{ dealloc(True) }} - cdef getFactory(self): """ Get the FieldFactory of the mesh @@ -835,48 +827,36 @@ cdef Coordinates coordsFromPtr(c.Coordinates * obj): coords = Coordinates() coords.cobj = obj coords._setmembers() - coords.isSelfOwned = False return coords -cdef class Coordinates(BOUTppBase): - """ - Contains information about geometry, such as metric tensors - """ - cdef c.Coordinates * cobj - cdef c.bool isSelfOwned - cdef public {{ metric_field }} dx, dy, dz - cdef public {{ metric_field }} J - cdef public {{ metric_field }} Bxy - cdef public {{ metric_field }} g11, g22, g33, g12, g13, g23 - cdef public {{ metric_field }} g_11, g_22, g_33, g_12, g_13, g_23 - cdef public {{ metric_field }} G1_11, G1_22, G1_33, G1_12, G1_13, G1_23 - cdef public {{ metric_field }} G2_11, G2_22, G2_33, G2_12, G2_13, G2_23 - cdef public {{ metric_field }} G3_11, G3_22, G3_33, G3_12, G3_13, G3_23 - cdef public {{ metric_field }} G1, G2, G3 - cdef public {{ metric_field }} ShiftTorsion - cdef public {{ metric_field }} IntShiftTorsion - - def __init__(self): - self.cobj = NULL - self.isSelfOwned = False +{% set data %} +cdef public {{ metric_field }} dx, dy, dz +cdef public {{ metric_field }} J +cdef public {{ metric_field }} Bxy +cdef public {{ metric_field }} g11, g22, g33, g12, g13, g23 +cdef public {{ metric_field }} g_11, g_22, g_33, g_12, g_13, g_23 +cdef public {{ metric_field }} G1_11, G1_22, G1_33, G1_12, G1_13, G1_23 +cdef public {{ metric_field }} G2_11, G2_22, G2_33, G2_12, G2_13, G2_23 +cdef public {{ metric_field }} G3_11, G3_22, G3_33, G3_12, G3_13, G3_23 +cdef public {{ metric_field }} G1, G2, G3 +cdef public {{ metric_field }} ShiftTorsion +cdef public {{ metric_field }} IntShiftTorsion +{% endset %} +{{ class("Coordinates", comment="Contains information about geometry, such as metric tensors", data=data, defaultSO=False) }} def _setmembers(self): {% for f in "dx", "dy", "dz", "J", "Bxy", "g11", "g22", "g33", "g12", "g13", "g23", "g_11", "g_22", "g_33", "g_12", "g_13", "g_23", "G1_11", "G1_22", "G1_33", "G1_12", "G1_13", "G1_23", "G2_11", "G2_22", "G2_33", "G2_12", "G2_13", "G2_23", "G3_11", "G3_22", "G3_33", "G3_12", "G3_13", "G3_23", "G1", "G2", "G3", "ShiftTorsion", "IntShiftTorsion" %} self.{{f}} = {{ metric_field.fdd }}FromPtr(&self.cobj.{{f}}) {% endfor %} -{{ dealloc(True) }} +{{ class("Laplacian", comment=""" +Laplacian inversion solver -cdef class Laplacian(BOUTppBase): - """ - Laplacian inversion solver +Compute the Laplacian inversion of objects. - Compute the Laplacian inversion of objects. +Equation solved is: d\\nabla^2_\\perp x + (1/c1)\\nabla_perp c2\\cdot\\nabla_\\perp x + ex\\nabla_x x + ez\\nabla_z x + a x = b +""", uniquePtr=True) }} - Equation solved is: d\\nabla^2_\\perp x + (1/c1)\\nabla_perp c2\\cdot\\nabla_\\perp x + ex\\nabla_x x + ez\\nabla_z x + a x = b - """ - cdef unique_ptr[c.Laplacian] cobj - cdef c.bool isSelfOwned def __init__(self, section=None): """ Initialiase a Laplacian solver @@ -936,15 +916,8 @@ cdef class Laplacian(BOUTppBase): deref(self.cobj).setCoef{{ coeff }}({{ coeff }}.cobj[0]) {% endfor %} -{{ dealloc(True, uniquePtr=True) }} -cdef class FieldFactory(BOUTppBase): - cdef c.FieldFactory * cobj - def __init__(self): - checkInit() - cobj=< c.FieldFactory*>0 - -{{ dealloc() }} +{{ class("FieldFactory", defaultSO=False) }} cdef void callback(void * parameter, void * method) with gil: cdef double time = (parameter)[0] @@ -961,14 +934,20 @@ cdef void callback(void * parameter, void * method) with gil: ctypedef void (*Method)(void *param) -cdef class PythonModelCallback(BOUTppBase): - """Needed for callbacks from C++ to python""" +cdef class PythonModelCallback: + """ + Needed for callbacks from C++ to python + """ cdef c.PythonModelCallback * cobj + cdef c.bool _is_freed + cdef c.bool isSelfOwned def __cinit__(self, method): # "callback" :: The pattern/converter method to fire a Python # object method from C typed infos # "method" :: The effective method passed by the Python user + self._is_freed = False + self.isSelfOwned = True checkInit() self.cobj = new c.PythonModelCallback(callback, method) self.__cinit__() @@ -980,18 +959,24 @@ cdef class PythonModelCallback(BOUTppBase): self.cobj.cy_execute(parameter) -cdef class PhysicsModelBase(BOUTppBase): +cdef class PhysicsModelBase: """The PhysicsModelBase in python - better use the PhysicsModel class""" cdef c.PythonModel * cmodel cdef c.PythonModelCallback * callback cdef c.PythonModelCallback * callbackinit cdef c.bool _done_pyinit - def __init__(self): + cdef c.bool _is_freed + cdef c.bool isSelfOwned + + def __cinit__(self): checkInit() - self.cmodel = new c.PythonModel() - self.callback= 0 - self.callbackinit= 0 + self.cmodel = new c.PythonModel() + self.callback = NULL + self.callbackinit = NULL self._done_pyinit = False + self._is_freed = False + self.isSelfOwned = True + def solve(self): if self._done_pyinit == False: self._done_pyinit = True @@ -1011,7 +996,7 @@ cdef class PhysicsModelBase(BOUTppBase): f3d = (kwargs[key]).cobj self.cmodel.getSolver().add(f3d[0],tmp) - def setRhs(self,rhs): + def setRhs(self, rhs): """ set the rhs function to be called @@ -1020,7 +1005,7 @@ cdef class PhysicsModelBase(BOUTppBase): rhs : function Must not be a method, and must accept an double (time) as argument """ - if self.callback != 0: + if self.callback != NULL: del self.callback self.callback = new c.PythonModelCallback(callback, rhs) self.cmodel.set_rhs_func(self.callback) @@ -1046,13 +1031,16 @@ cdef class PhysicsModelBase(BOUTppBase): PhysicsModelBase._boutpp_dealloc(self) def _boutpp_dealloc(self): - if self.cmodel != 0: + if self.cmodel != NULL: self.cmodel.free() del self.cmodel del self.callback del self.callbackinit self.cmodel = 0 - super()._boutpp_dealloc() + self._is_freed = True + +{{ wait() }} + class PhysicsModel(PhysicsModelBase): """ @@ -1081,18 +1069,11 @@ class PhysicsModel(PhysicsModelBase): model.solve() """ - def __init__(self): - super(PhysicsModel,self).__init__() - self._super_is_initialised=True def solve(self): """ Call the solver. This makes sure that self.init(restart) and self.rhs(time) are called from the solver. """ - try: - self._super_is_initialised - except: - raise RuntimeError("PhysicsModel is not initialized") def _rhs(time): self.rhs(time) self.myrhs=_rhs @@ -1102,6 +1083,7 @@ class PhysicsModel(PhysicsModelBase): self.myinit=_init self.setInit(self.myinit) super(PhysicsModel,self).solve() + def solve_for(self,*args,**kwargs): """ Add Field3D's to be solved for. @@ -1113,11 +1095,8 @@ class PhysicsModel(PhysicsModelBase): kwargs : dictionary of Field2D or Field3D Keys must be strings, and value of dict must be the Field3D which should be evolved. """ - try: - self._super_is_initialised - except: - raise RuntimeError("PhysicsModel is not initialized") super(PhysicsModel,self).solve_for(*args,**kwargs) + def init(self,restart): """ This can be overwritten to do model specific initialization @@ -1206,7 +1185,7 @@ def finalise(): ourClasses = ( Field2D, Field3D, Vector2D, Vector3D, Mesh, Coordinates, Laplacian, FieldFactory, PythonModelCallback, PhysicsModel, - PhysicsModelBase, PythonModelCallback, Options, BOUTppBase, + PhysicsModelBase, PythonModelCallback, Options, ) for obj in objects: if isinstance(obj, ourClasses): @@ -1220,14 +1199,16 @@ def finalise(): break for obj in objects: if isinstance(obj, ourClasses): - if hasattr(obj, "_boutpp_wait_dealloc"): - obj._boutpp_wait_dealloc() + if hasattr(obj, "_boutpp_wait_freed"): + obj._boutpp_wait_freed() else: for ourClass in ourClasses: if isinstance(obj, ourClass): - if hasattr(ourClass, "_boutpp_wait_dealloc"): - ourClass._boutpp_wait_dealloc(obj) + if hasattr(ourClass, "_boutpp_wait_freed"): + ourClass._boutpp_wait_freed(obj) break + else: + print(f"{obj} of type {ourClass} cannot wait!") del objects # Actually finalise if wasInit: @@ -1538,12 +1519,7 @@ def setOption(name, value, source="PyInterface", force=False): root = Options.root() root.set(name, value, source, force) -cdef class Options(BOUTppBase): - """ - The Options class - """ - cdef c.Options * cobj - cdef c.bool isSelfOwned +{{ class("Options") }} def __init__(self, **kwargs): """Construct an Options from keywords or dict""" @@ -1595,13 +1571,11 @@ cdef class Options(BOUTppBase): The Options object """ checkInit() - opt = Options("") - opt.cobj = new c.Options() - opt.isSelfOwned = True + opt = Options() cdef char * file_ file__ = file.encode() file_ = file__ - c.OptionsReader.getInstance().read(opt.cobj, "%s", file_) + c.OptionsReader.getInstance().read(opt.cobj, file_) return opt @staticmethod @@ -1741,9 +1715,6 @@ cdef class Options(BOUTppBase): cdef c.Options* opt = self.cobj opt.setConditionallyUsed() -{{ dealloc(True) }} - - def writeDefaultOutputFile(options: Options): c.writeDefaultOutputFile(deref(options.cobj)) From 74134842766f7f53c54c13db61287412e628b5c3 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 12 Dec 2024 15:40:52 +0100 Subject: [PATCH 035/259] Track references in boutpp The list from gc was incomplete. Using a custom weakref list ensures we can free all objects before MPI_Finalize is called. This reverts 0e4314c449581, which was not working as it relied on the same, incomplete, list of objects. Resolves: gh#3041 --- tools/pylib/_boutpp_build/boutpp.pyx.jinja | 66 +++++++++------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index 3ae6dfc47d..d6f0601f1c 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -15,20 +15,16 @@ from libcpp.memory cimport unique_ptr from cython.operator import dereference as deref import numbers import sys -import gc from time import sleep +import weakref + +_allobjects = [] size_t = np.uint cdef extern from "boutexception_helper.hxx": cdef void raise_bout_py_error() -{% macro wait() %} - def _boutpp_wait_freed(self): - while not self._is_freed: - sleep(0.001) -{% endmacro %} - {% macro dealloc(extra_dealloc='', uniquePtr=False) %} def __dealloc__(self): self._boutpp_dealloc() @@ -43,7 +39,6 @@ cdef extern from "boutexception_helper.hxx": self.cobj = NULL {% endif %} -{{ wait() }} {% endmacro %} {% macro class(name, init="", extra_dealloc="", defaultSO=True, data="", uniquePtr=False, init_args="*args, **kwargs", @@ -58,10 +53,11 @@ cdef class {{ name }}{{ "(" ~ base ~ ")" if base else "" }}: """ cdef {{ "unique_ptr[c." ~ name ~ "]" if uniquePtr else "c." ~ name ~ "* " }} cobj cdef c.bool isSelfOwned - cdef c.bool _is_freed + cdef object __weakref__ {{ data | indent }} def __cinit__(self, {{ init_args}}): - self._is_freed = False + global _allobjects + _allobjects.append(weakref.ref(self)) {% if not uniquePtr and cobj %} self.isSelfOwned = {{ defaultSO }} self.cobj = NULL @@ -939,14 +935,15 @@ cdef class PythonModelCallback: Needed for callbacks from C++ to python """ cdef c.PythonModelCallback * cobj - cdef c.bool _is_freed cdef c.bool isSelfOwned + cdef object __weakref__ def __cinit__(self, method): # "callback" :: The pattern/converter method to fire a Python # object method from C typed infos # "method" :: The effective method passed by the Python user - self._is_freed = False + global _allobjects + _allobjects.append(weakref.ref(self)) self.isSelfOwned = True checkInit() self.cobj = new c.PythonModelCallback(callback, method) @@ -965,16 +962,17 @@ cdef class PhysicsModelBase: cdef c.PythonModelCallback * callback cdef c.PythonModelCallback * callbackinit cdef c.bool _done_pyinit - cdef c.bool _is_freed cdef c.bool isSelfOwned + cdef object __weakref__ def __cinit__(self): checkInit() + global _allobjects + _allobjects.append(weakref.ref(self)) self.cmodel = new c.PythonModel() self.callback = NULL self.callbackinit = NULL self._done_pyinit = False - self._is_freed = False self.isSelfOwned = True def solve(self): @@ -1037,9 +1035,6 @@ cdef class PhysicsModelBase: del self.callback del self.callbackinit self.cmodel = 0 - self._is_freed = True - -{{ wait() }} class PhysicsModel(PhysicsModelBase): @@ -1181,34 +1176,25 @@ def finalise(): global _isInit wasInit = _isInit _isInit = False - objects = gc.get_objects() + objects = _allobjects #gc.get_objects() ourClasses = ( Field2D, Field3D, Vector2D, Vector3D, Mesh, Coordinates, Laplacian, FieldFactory, PythonModelCallback, PhysicsModel, PhysicsModelBase, PythonModelCallback, Options, ) - for obj in objects: - if isinstance(obj, ourClasses): - if hasattr(obj, "_boutpp_dealloc"): - obj._boutpp_dealloc() - else: - for ourClass in ourClasses: - if isinstance(obj, ourClass): - if hasattr(ourClass, "_boutpp_dealloc"): - ourClass._boutpp_dealloc(obj) - break - for obj in objects: - if isinstance(obj, ourClasses): - if hasattr(obj, "_boutpp_wait_freed"): - obj._boutpp_wait_freed() - else: - for ourClass in ourClasses: - if isinstance(obj, ourClass): - if hasattr(ourClass, "_boutpp_wait_freed"): - ourClass._boutpp_wait_freed(obj) - break - else: - print(f"{obj} of type {ourClass} cannot wait!") + for objr in objects: + obj = objr() + if obj is None: + continue + if hasattr(obj, "_boutpp_dealloc"): + obj._boutpp_dealloc() + else: + for ourClass in ourClasses: + if isinstance(obj, ourClass): + if hasattr(ourClass, "_boutpp_dealloc"): + ourClass._boutpp_dealloc(obj) + break + del objects # Actually finalise if wasInit: From cb083c0bda420c49fb7dacc3b0c4eaaa3f7644b2 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:08:22 +0000 Subject: [PATCH 036/259] Apply black changes --- tests/integrated/test_suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test_suite b/tests/integrated/test_suite index 307a8d84b3..77ad7882c4 100755 --- a/tests/integrated/test_suite +++ b/tests/integrated/test_suite @@ -188,7 +188,7 @@ class Test(threading.Thread): self.output += "\n(It is likely that a timeout occured)" else: # ❌ Failed - print("\u274C", end="") # No newline + print("\u274c", end="") # No newline print(" %7.3f s" % (time.time() - self.local.start_time), flush=True) def _cost(self): From d38a8f1af24cbe57a40fb7a889cbb257e81b2896 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 20:22:11 +0000 Subject: [PATCH 037/259] Bump ZedThree/clang-tidy-review from 0.20.1 to 0.21.0 Bumps [ZedThree/clang-tidy-review](https://github.com/zedthree/clang-tidy-review) from 0.20.1 to 0.21.0. - [Release notes](https://github.com/zedthree/clang-tidy-review/releases) - [Changelog](https://github.com/ZedThree/clang-tidy-review/blob/master/CHANGELOG.md) - [Commits](https://github.com/zedthree/clang-tidy-review/compare/v0.20.1...v0.21.0) --- updated-dependencies: - dependency-name: ZedThree/clang-tidy-review dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/clang-tidy-review.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index b2f9bd7573..9746075b1a 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.20.1 + uses: ZedThree/clang-tidy-review@v0.21.0 id: review with: build_dir: build @@ -46,4 +46,4 @@ jobs: -DBOUT_UPDATE_GIT_SUBMODULE=OFF - name: Upload clang-tidy fixes - uses: ZedThree/clang-tidy-review/upload@v0.20.1 + uses: ZedThree/clang-tidy-review/upload@v0.21.0 From 7253298aad03d70ca50ce3d439fad8c79b191ce8 Mon Sep 17 00:00:00 2001 From: Tom Body <116750897+tbody-cfs@users.noreply.github.com> Date: Wed, 16 Apr 2025 20:27:18 -0400 Subject: [PATCH 038/259] Update CMakeLists.txt Address #2945 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60d34e1ad7..9dc804d50f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ message(STATUS "Configuring BOUT++ version ${BOUT_FULL_VERSION}") project(BOUT++ DESCRIPTION "Fluid PDE solver framework" VERSION ${BOUT_CMAKE_ACCEPTABLE_VERSION} - LANGUAGES CXX) + LANGUAGES C CXX) include(CMakeDependentOption) From 3c3aca61377e8c7576c912a5bb9597c5768103d0 Mon Sep 17 00:00:00 2001 From: Tom Body Date: Fri, 18 Apr 2025 16:18:09 +0000 Subject: [PATCH 039/259] Move enable C to NetCDF --- cmake/FindnetCDF.cmake | 1 + cmake/SetupBOUTThirdParty.cmake | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindnetCDF.cmake b/cmake/FindnetCDF.cmake index 393c57549b..361095954e 100644 --- a/cmake/FindnetCDF.cmake +++ b/cmake/FindnetCDF.cmake @@ -32,6 +32,7 @@ if (NOT netCDF_ROOT AND EXISTS "${BOUT_USE_NETCDF}") set(netCDF_ROOT "${BOUT_USE_NETCDF}") endif() +enable_language(C) find_package(netCDF QUIET CONFIG) if (netCDF_FOUND) diff --git a/cmake/SetupBOUTThirdParty.cmake b/cmake/SetupBOUTThirdParty.cmake index 43067ad9e0..65be28334b 100644 --- a/cmake/SetupBOUTThirdParty.cmake +++ b/cmake/SetupBOUTThirdParty.cmake @@ -254,7 +254,6 @@ if (BOUT_USE_SUNDIALS) FetchContent_MakeAvailable(sundials) message(STATUS "SUNDIALS done configuring") else() - enable_language(C) find_package(SUNDIALS REQUIRED) if (SUNDIALS_VERSION VERSION_LESS 4.0.0) message(FATAL_ERROR "SUNDIALS_VERSION 4.0.0 or newer is required. Found version ${SUNDIALS_VERSION}.") From 2c9b3e2432a4e35f74c7aec02ebc218577118e71 Mon Sep 17 00:00:00 2001 From: Tom Body Date: Fri, 18 Apr 2025 17:36:08 +0000 Subject: [PATCH 040/259] Remove top-level C --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9dc804d50f..60d34e1ad7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ message(STATUS "Configuring BOUT++ version ${BOUT_FULL_VERSION}") project(BOUT++ DESCRIPTION "Fluid PDE solver framework" VERSION ${BOUT_CMAKE_ACCEPTABLE_VERSION} - LANGUAGES C CXX) + LANGUAGES CXX) include(CMakeDependentOption) From 36c17409858bf90538a829d49a992f4211f947a0 Mon Sep 17 00:00:00 2001 From: Tom Body Date: Fri, 18 Apr 2025 18:47:12 +0000 Subject: [PATCH 041/259] Add back in C language for SUNDIALS --- cmake/SetupBOUTThirdParty.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/SetupBOUTThirdParty.cmake b/cmake/SetupBOUTThirdParty.cmake index 65be28334b..eefe513a3d 100644 --- a/cmake/SetupBOUTThirdParty.cmake +++ b/cmake/SetupBOUTThirdParty.cmake @@ -233,6 +233,7 @@ option(BOUT_DOWNLOAD_SUNDIALS "Download and build SUNDIALS" OFF) cmake_dependent_option(BOUT_USE_SUNDIALS "Enable support for SUNDIALS time solvers" OFF "NOT BOUT_DOWNLOAD_SUNDIALS" ON) if (BOUT_USE_SUNDIALS) + enable_language(C) if (BOUT_DOWNLOAD_SUNDIALS) message(STATUS "Downloading and configuring SUNDIALS") include(FetchContent) From 1552269fcf65b722f5dc8175d93950ff8fa19028 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:43:02 +0000 Subject: [PATCH 042/259] Bump externalpackages/googletest from `2b6b042` to `bac6a8f` Bumps [externalpackages/googletest](https://github.com/google/googletest) from `2b6b042` to `bac6a8f`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/2b6b042a77446ff322cd7522ca068d9f2a21c1d1...bac6a8fd8a729eef0d1b2d1a4625f4de62c60220) --- updated-dependencies: - dependency-name: externalpackages/googletest dependency-version: bac6a8fd8a729eef0d1b2d1a4625f4de62c60220 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index 2b6b042a77..bac6a8fd8a 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit 2b6b042a77446ff322cd7522ca068d9f2a21c1d1 +Subproject commit bac6a8fd8a729eef0d1b2d1a4625f4de62c60220 From 96cdee5b83aadc64304d1024ec84767e8e7c182b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:41:43 +0000 Subject: [PATCH 043/259] Bump externalpackages/boutdata from `0aaef41` to `a7a372d` Bumps [externalpackages/boutdata](https://github.com/boutproject/boutdata) from `0aaef41` to `a7a372d`. - [Release notes](https://github.com/boutproject/boutdata/releases) - [Commits](https://github.com/boutproject/boutdata/compare/0aaef417af092882ac295c4d84e4532e4a10e01f...a7a372d5de7594cbe16381a3a82289ddaa58b6e7) --- updated-dependencies: - dependency-name: externalpackages/boutdata dependency-version: a7a372d5de7594cbe16381a3a82289ddaa58b6e7 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/boutdata | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/boutdata b/externalpackages/boutdata index 0aaef417af..a7a372d5de 160000 --- a/externalpackages/boutdata +++ b/externalpackages/boutdata @@ -1 +1 @@ -Subproject commit 0aaef417af092882ac295c4d84e4532e4a10e01f +Subproject commit a7a372d5de7594cbe16381a3a82289ddaa58b6e7 From dd8e5ebca19c8fe38b2ad2cd6a9981ee85eac18f Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 30 Oct 2024 13:39:04 +0000 Subject: [PATCH 044/259] Replace deprecated `boututils.file_import` --- examples/elm-pb/Python/2dprofile.py | 5 +++-- examples/elm-pb/Python/plotcollapse.py | 7 +++++-- examples/elm-pb/Python/post.py | 5 +++-- examples/elm-pb/Python/read_elmsize.py | 5 +++-- examples/elm-pb/Python/sprofiles.py | 9 +++++---- examples/elm-pb/Python/volume_int.py | 14 ++++++++------ tests/integrated/test-drift-instability/runtest | 8 ++++---- 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/examples/elm-pb/Python/2dprofile.py b/examples/elm-pb/Python/2dprofile.py index ea430a0fe1..5bb01972f9 100644 --- a/examples/elm-pb/Python/2dprofile.py +++ b/examples/elm-pb/Python/2dprofile.py @@ -3,10 +3,11 @@ from past.utils import old_div import numpy as np import matplotlib.pyplot as plt -from boututils.file_import import file_import +from boututils.datafile import DataFile from matplotlib.ticker import FixedFormatter, FormatStrFormatter, AutoLocator, AutoMinorLocator -g = file_import("./cbm18_dens8.grid_nx68ny64.nc") +with DataFile("./cbm18_dens8.grid_nx68ny64.nc") as f: + g = {v: f.read(v) for v in f.keys()} majorLocator = AutoLocator() majorFormatter = FormatStrFormatter('%3.0e') diff --git a/examples/elm-pb/Python/plotcollapse.py b/examples/elm-pb/Python/plotcollapse.py index 49858ae37e..ee64ca381f 100755 --- a/examples/elm-pb/Python/plotcollapse.py +++ b/examples/elm-pb/Python/plotcollapse.py @@ -5,9 +5,10 @@ import matplotlib.pyplot as plt import numpy as np from boututils.moment_xyzt import moment_xyzt -from boututils.file_import import file_import +from boututils.datafile import DataFile from boutdata.collect import collect import os +from pathlib import Path #Dynamic matplotlib settings from matplotlib import rcParams @@ -17,8 +18,10 @@ if not os.path.exists('image'): os.makedirs('image') +filename = Path(__file__).with_name("cbm18_dens8.grid_nx68ny64.nc") +with DataFile(str(filename)) as f: + g = {v: f.read(v) for v in f.keys()} -g = file_import(os.path.dirname(os.path.realpath(__file__))+'/../cbm18_dens8.grid_nx68ny64.nc') psi = old_div((g['psixy'][:, 32] - g['psi_axis']), (g['psi_bndry'] - g['psi_axis'])) path = './data' diff --git a/examples/elm-pb/Python/post.py b/examples/elm-pb/Python/post.py index 2c2d3e2bde..9bb67347f0 100644 --- a/examples/elm-pb/Python/post.py +++ b/examples/elm-pb/Python/post.py @@ -5,7 +5,7 @@ from __future__ import division from past.utils import old_div import numpy as np -from boututils.file_import import file_import +from boututils.datafile import DataFile from boutdata.collect import collect from pylab import plot, show, figure, xlabel, ylabel, annotate, xlim, ylim from boututils.moment_xyzt import moment_xyzt @@ -23,7 +23,8 @@ gfile='./cbm18_dens8.grid_nx68ny64.nc' -g = file_import(gfile) +with DataFile(gfile) as f: + g = {v: f.read(v) for v in f.keys()} Dphi0 = collect("Dphi0", path=path0) diff --git a/examples/elm-pb/Python/read_elmsize.py b/examples/elm-pb/Python/read_elmsize.py index b2ce7674a6..fcd3d24e53 100644 --- a/examples/elm-pb/Python/read_elmsize.py +++ b/examples/elm-pb/Python/read_elmsize.py @@ -1,6 +1,6 @@ from boutdata.collect import collect from boututils.moment_xyzt import moment_xyzt -from boututils.file_import import file_import +from boututils.datafile import DataFile from pylab import save, figure, plot, title, xlabel, ylabel, show, tight_layout from elm_size import elm_size @@ -19,7 +19,8 @@ # te0=collect('te0', path=path) # save('te0.idl.dat', te0) -gfile=file_import('./cbm18_dens8.grid_nx68ny64.nc') +with DataFile("./cbm18_dens8.grid_nx68ny64.nc") as f: + gfile = {v: f.read(v) for v in f.keys()} p=collect('P', path=path) save('p.dat', p) diff --git a/examples/elm-pb/Python/sprofiles.py b/examples/elm-pb/Python/sprofiles.py index f118bce23c..9d8eea48de 100644 --- a/examples/elm-pb/Python/sprofiles.py +++ b/examples/elm-pb/Python/sprofiles.py @@ -3,17 +3,18 @@ from builtins import range from past.utils import old_div import numpy as np -from boututils.file_import import file_import +from boututils.datafile import DataFile from boututils.surface_average import surface_average from boutdata.collect import collect from pylab import plot, show, xlabel, ylabel, figure, legend, gca -path='./data' +path = "./data" -gfile='../cbm18_dens8.grid_nx68ny64.nc' +gfile = "../cbm18_dens8.grid_nx68ny64.nc" -g = file_import(gfile) +with DataFile(gfile) as f: + g = {v: f.read(v) for v in f.keys()} var=collect("P", path=path) diff --git a/examples/elm-pb/Python/volume_int.py b/examples/elm-pb/Python/volume_int.py index 38775d37e0..e858f156d7 100644 --- a/examples/elm-pb/Python/volume_int.py +++ b/examples/elm-pb/Python/volume_int.py @@ -1,18 +1,20 @@ from __future__ import print_function -from boututils.file_import import file_import +from boututils.datafile import DataFile from boututils.volume_integral import volume_integral from boutdata.collect import collect + # Integrate over a volume -path='./data/' +path = "./data/" -gfile='./cbm18_dens8.grid_nx68ny64.nc' +gfile = "./cbm18_dens8.grid_nx68ny64.nc" -g = file_import(gfile) +with DataFile(gfile) as f: + g = {v: f.read(v) for v in f.keys()} -var=collect("P", path=path) +var = collect("P", path=path) -sol=volume_integral(var, g) +sol = volume_integral(var, g) print(sol) diff --git a/tests/integrated/test-drift-instability/runtest b/tests/integrated/test-drift-instability/runtest index e8ddddc11d..85aa8ea1f3 100755 --- a/tests/integrated/test-drift-instability/runtest +++ b/tests/integrated/test-drift-instability/runtest @@ -7,8 +7,8 @@ # Requires: not metric_3d from boututils.run_wrapper import build_and_log, shell, launch_safe -from boututils.file_import import file_import from boututils.calculus import deriv +from boututils.datafile import DataFile from boututils.linear_regression import linear_regression from boutdata.collect import collect @@ -94,6 +94,9 @@ def run_zeff_case(zeff): ny = dims[2] nz = dims[3] + with DataFile("uedge.grd_std.cdl") as f: + grid = {v: f.read(v) for v in f.keys()} + # Calculate geometric and physical quantities lZeta = 1e2 * zmax * 2 * np.pi * grid["R0"] # toroidal range [cm] lbNorm = lZeta * ( @@ -211,9 +214,6 @@ if __name__ == "__main__": build_and_log("resistive drift instability test") - # Import the grid file - grid = file_import("uedge.grd_std.cdl") - return_code = 0 for zeff in args.Zeff_list: success = run_zeff_case(zeff) From 862f7fd2cbd3cea70875d8564ca9b0ed406a9c9c Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 26 Jun 2025 10:53:25 +0200 Subject: [PATCH 045/259] Introduce Field3DParallel Field3DParallel enforces that parallel derivatives can be taken. This means for FCI, parallel fields are present. It also ensures that if an operation is taken on such a field, the parallel fields are retained. This replaces part of fci-automagic, that always retained parallel fields on operations. --- include/bout/field3d.hxx | 47 +- src/field/field3d.cxx | 10 + src/field/gen_fieldops.jinja | 53 +- src/field/gen_fieldops.py | 26 +- src/field/generated_fieldops.cxx | 1004 +++++++++++++++++++++++------- 5 files changed, 868 insertions(+), 272 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 0643efbe0a..a8f2c183ae 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -525,7 +525,7 @@ public: bool allowCalcParallelSlices{true}; -private: +protected: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null int nx{-1}, ny{-1}, nz{-1}; @@ -699,4 +699,49 @@ inline Field3D copy(const Field3D& f) { return result; } +class Field3DParallel: public Field3D +{ + public: + template + Field3DParallel(Types... args): Field3D(&args ...) { + ensureFieldAligned(); + } + Field3DParallel(Field3D&& f3d): Field3D(std::move(f3d)) { + ensureFieldAligned(); + } + Field3DParallel(const Field3D& f3d): Field3D(f3d) { + ensureFieldAligned(); + } + // Explicitly needed, as DirectionTypes is sometimes constructed from a + // brace enclosed list + Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}, + std::optional regionID = {}) : + Field3D(localmesh, location_in, directions_in, regionID) { + ensureFieldAligned(); + } + Field3DParallel(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}) : + Field3D(std::move(data), localmesh, location, directions_in) { + ensureFieldAligned(); + } + + Field3DParallel& operator*=(const Field3D&); + Field3DParallel& operator/=(const Field3D&); + Field3DParallel& operator+=(const Field3D&); + Field3DParallel& operator-=(const Field3D&); + Field3DParallel& operator*=(const Field3DParallel&); + Field3DParallel& operator/=(const Field3DParallel&); + Field3DParallel& operator+=(const Field3DParallel&); + Field3DParallel& operator-=(const Field3DParallel&); + Field3DParallel& operator*=(BoutReal); + Field3DParallel& operator/=(BoutReal); + Field3DParallel& operator+=(BoutReal); + Field3DParallel& operator-=(BoutReal); +private: + void ensureFieldAligned(); +}; + #endif /* BOUT_FIELD3D_H */ diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 74a6f0853c..0c6cefd1cb 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -957,3 +957,13 @@ Options* Field3D::track(const BoutReal& change, std::string operation) { } return nullptr; } + +void Field3DParallel::ensureFieldAligned() { + if (isFci()) { + ASSERT2(hasParallelSlices()); + } else { + if (getDirectionY() != YDirectionType::Aligned) { + *this = toFieldAligned(*this); + } + } +} diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index 88e877c197..15f85c9ea4 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -8,44 +8,40 @@ checkData({{lhs.name}}); checkData({{rhs.name}}); - {% if out == "Field3D" %} - {% if lhs == rhs == "Field3D" %} + {% if out.region_type == "3D" %} + {% if lhs.region_type == rhs.region_type == "3D" %} {{out.name}}.setRegion({{lhs.name}}.getMesh()->getCommonRegion({{lhs.name}}.getRegionID(), {{rhs.name}}.getRegionID())); -#if BOUT_USE_FCI_AUTOMAGIC - if ({{lhs.name}}.isFci() and {{lhs.name}}.hasParallelSlices() and {{rhs.name}}.hasParallelSlices()) { + {% if out == "Field3DParallel" %} + if ({{lhs.name}}.isFci()) { {{out.name}}.splitParallelSlices(); - for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { + for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { {{out.name}}.yup(i) = {{lhs.name}}.yup(i) {{operator}} {{rhs.name}}.yup(i); {{out.name}}.ydown(i) = {{lhs.name}}.ydown(i) {{operator}} {{rhs.name}}.ydown(i); } } -#endif - {% elif lhs == "Field3D" %} + {% endif %} + {% elif lhs.region_type == "3D" %} {{out.name}}.setRegion({{lhs.name}}.getRegionID()); - {% if rhs == "BoutReal" %} -#if BOUT_USE_FCI_AUTOMAGIC - if ({{lhs.name}}.isFci() and {{lhs.name}}.hasParallelSlices()) { + {% if rhs == "BoutReal" and out == "Field3DParallel" %} + if ({{lhs.name}}.isFci()) { {{out.name}}.splitParallelSlices(); for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { {{out.name}}.yup(i) = {{lhs.name}}.yup(i) {{operator}} {{rhs.name}}; {{out.name}}.ydown(i) = {{lhs.name}}.ydown(i) {{operator}} {{rhs.name}}; } } -#endif {% endif %} - {% elif rhs == "Field3D" %} + {% elif rhs.region_type == "3D" %} {{out.name}}.setRegion({{rhs.name}}.getRegionID()); - {% if lhs == "BoutReal" %} -#if BOUT_USE_FCI_AUTOMAGIC - if ({{rhs.name}}.isFci() and {{rhs.name}}.hasParallelSlices()) { + {% if lhs == "BoutReal" and rhs == "Field3DParallel" %} + if ({{rhs.name}}.isFci()) { {{out.name}}.splitParallelSlices(); for (size_t i{0} ; i < {{rhs.name}}.numberParallelSlices() ; ++i) { {{out.name}}.yup(i) = {{lhs.name}} {{operator}} {{rhs.name}}.yup(i); {{out.name}}.ydown(i) = {{lhs.name}} {{operator}} {{rhs.name}}.ydown(i); } } -#endif {% endif %} {% endif %} {% endif %} @@ -110,29 +106,26 @@ ASSERT1_FIELDS_COMPATIBLE(*this, rhs); {% endif %} - {% if (lhs == "Field3D") %} - // Delete existing parallel slices. We don't copy parallel slices, so any + {% if lhs == "Field3D" %} + // Delete existing parallel slices. We don't update parallel slices, so any // that currently exist will be incorrect. - {% if (rhs == "Field3D" or rhs == "BoutReal") %} -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices() {% if rhs == "Field3D" %} and {{rhs.name}}.hasParallelSlices() {% endif %}) { + clearParallelSlices(); + {% endif %} + {% if lhs == "Field3DParallel" and (rhs.region_type == "3D" or rhs == "BoutReal") %} + if (this->isFci()) { for (size_t i{0} ; i < yup_fields.size() ; ++i) { yup(i) {{operator}}= {{rhs.name}}{% if rhs == "Field3D" %}.yup(i){% endif %}; ydown(i) {{operator}}= {{rhs.name}}{% if rhs == "Field3D" %}.ydown(i){% endif %}; } - } else -#endif - {% endif %} - { + } else { clearParallelSlices(); } - {% endif %} checkData(*this); checkData({{rhs.name}}); - {% if lhs == rhs == "Field3D" %} - regionID = fieldmesh->getCommonRegion(regionID, {{rhs.name}}.regionID); + {% if lhs.region_type == rhs.region_type == "3D" %} + regionID = fieldmesh->getCommonRegion(regionID, {{rhs.name}}.getRegionID()); {% endif %} @@ -176,7 +169,7 @@ } {% endif %} - {% if lhs == "Field3D" %} + {% if lhs.region_type == "3D" %} track(rhs, "operator{{operator}}="); {% endif %} #if BOUT_USE_TRACK @@ -186,7 +179,7 @@ checkData(*this); } else { - {% if lhs == "Field3D" %} + {% if lhs.region_type == "3D" %} track(rhs, "operator{{operator}}="); {% endif %} (*this) = (*this) {{operator}} {{rhs.name}}; diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 29631ff7aa..4ae8bf8a23 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -104,7 +104,7 @@ def __init__( self.mixed_base_ind_var = mixed_base_ind_var # Note region_type isn't actually used currently but # may be useful in future. - if self.field_type == "Field3D": + if "Field3D" in self.field_type: self.region_type = "3D" elif self.field_type == "Field2D": self.region_type = "2D" @@ -184,6 +184,8 @@ def returnType(f1, f2): return copy(f1) elif f1 == "FieldPerp" or f2 == "FieldPerp": return copy(fieldPerp) + elif f1 == "Field3DParallel" or f2 == "Field3DParallel": + return copy(field3DPar) else: return copy(field3D) @@ -227,6 +229,13 @@ def returnType(f1, f2): jz_var=jz_var, mixed_base_ind_var=mixed_base_ind_var, ) + field3DPar = Field( + "Field3DParallel", + ["x", "y", "z"], + index_var=index_var, + jz_var=jz_var, + mixed_base_ind_var=mixed_base_ind_var, + ) field2D = Field( "Field2D", ["x", "y"], @@ -249,7 +258,8 @@ def returnType(f1, f2): mixed_base_ind_var=mixed_base_ind_var, ) - fields = [field3D, field2D, fieldPerp, boutreal] + fields = (field3D, field2D, fieldPerp, boutreal) + fields2 = (field3D, field3DPar, boutreal) with smart_open(args.filename, "w") as f: f.write(header) @@ -259,10 +269,16 @@ def returnType(f1, f2): template = env.get_template("gen_fieldops.jinja") - for lhs, rhs in itertools.product(fields, fields): - # We don't have to define BoutReal BoutReal operations - if lhs == rhs == "BoutReal": + # We don't have to define BoutReal BoutReal operations + done = [(boutreal, boutreal)] + for lhs, rhs in itertools.chain( + itertools.product(fields, fields), + itertools.product((field3D, field3DPar, boutreal), (field3D, field3DPar)), + ): + if (lhs, rhs) in done: continue + done.append((lhs, rhs)) + rhs = copy(rhs) lhs = copy(lhs) diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 75d2ede82d..7b742b7e43 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -15,15 +15,6 @@ Field3D operator*(const Field3D& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) * rhs.yup(i); - result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] * rhs[index]; @@ -43,24 +34,13 @@ Field3D& Field3D::operator*=(const Field3D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices() and rhs.hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) *= rhs.yup(i); - ydown(i) *= rhs.ydown(i); - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); - regionID = fieldmesh->getCommonRegion(regionID, rhs.regionID); + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } @@ -87,15 +67,6 @@ Field3D operator/(const Field3D& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) / rhs.yup(i); - result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] / rhs[index]; @@ -115,24 +86,13 @@ Field3D& Field3D::operator/=(const Field3D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices() and rhs.hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) /= rhs.yup(i); - ydown(i) /= rhs.ydown(i); - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); - regionID = fieldmesh->getCommonRegion(regionID, rhs.regionID); + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } @@ -159,15 +119,6 @@ Field3D operator+(const Field3D& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) + rhs.yup(i); - result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] + rhs[index]; @@ -187,24 +138,13 @@ Field3D& Field3D::operator+=(const Field3D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices() and rhs.hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) += rhs.yup(i); - ydown(i) += rhs.ydown(i); - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); - regionID = fieldmesh->getCommonRegion(regionID, rhs.regionID); + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } @@ -231,15 +171,6 @@ Field3D operator-(const Field3D& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) - rhs.yup(i); - result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] - rhs[index]; @@ -259,24 +190,13 @@ Field3D& Field3D::operator-=(const Field3D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices() and rhs.hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) -= rhs.yup(i); - ydown(i) -= rhs.ydown(i); - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); - regionID = fieldmesh->getCommonRegion(regionID, rhs.regionID); + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } @@ -327,10 +247,9 @@ Field3D& Field3D::operator*=(const Field2D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any + // Delete existing parallel slices. We don't update parallel slices, so any // that currently exist will be incorrect. - { clearParallelSlices(); } - + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -389,10 +308,9 @@ Field3D& Field3D::operator/=(const Field2D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any + // Delete existing parallel slices. We don't update parallel slices, so any // that currently exist will be incorrect. - { clearParallelSlices(); } - + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -451,10 +369,9 @@ Field3D& Field3D::operator+=(const Field2D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any + // Delete existing parallel slices. We don't update parallel slices, so any // that currently exist will be incorrect. - { clearParallelSlices(); } - + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -512,10 +429,9 @@ Field3D& Field3D::operator-=(const Field2D& rhs) { if (data.unique()) { ASSERT1_FIELDS_COMPATIBLE(*this, rhs); - // Delete existing parallel slices. We don't copy parallel slices, so any + // Delete existing parallel slices. We don't update parallel slices, so any // that currently exist will be incorrect. - { clearParallelSlices(); } - + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -640,15 +556,6 @@ Field3D operator*(const Field3D& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) * rhs; - result.ydown(i) = lhs.ydown(i) * rhs; - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] * rhs; @@ -667,20 +574,9 @@ Field3D& Field3D::operator*=(const BoutReal rhs) { // otherwise just call the non-inplace version if (data.unique()) { - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) *= rhs; - ydown(i) *= rhs; - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -708,15 +604,6 @@ Field3D operator/(const Field3D& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) / rhs; - result.ydown(i) = lhs.ydown(i) / rhs; - } - } -#endif const auto tmp = 1.0 / rhs; BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { @@ -736,20 +623,9 @@ Field3D& Field3D::operator/=(const BoutReal rhs) { // otherwise just call the non-inplace version if (data.unique()) { - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) /= rhs; - ydown(i) /= rhs; - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -778,15 +654,6 @@ Field3D operator+(const Field3D& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) + rhs; - result.ydown(i) = lhs.ydown(i) + rhs; - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] + rhs; @@ -805,20 +672,9 @@ Field3D& Field3D::operator+=(const BoutReal rhs) { // otherwise just call the non-inplace version if (data.unique()) { - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) += rhs; - ydown(i) += rhs; - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -846,15 +702,6 @@ Field3D operator-(const Field3D& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (lhs.isFci() and lhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs.yup(i) - rhs; - result.ydown(i) = lhs.ydown(i) - rhs; - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs[index] - rhs; @@ -873,20 +720,9 @@ Field3D& Field3D::operator-=(const BoutReal rhs) { // otherwise just call the non-inplace version if (data.unique()) { - // Delete existing parallel slices. We don't copy parallel slices, so any -// that currently exist will be incorrect. -#if BOUT_USE_FCI_AUTOMAGIC - if (this->isFci() and this->hasParallelSlices()) { - for (size_t i{0}; i < yup_fields.size(); ++i) { - yup(i) -= rhs; - ydown(i) -= rhs; - } - } else -#endif - { - clearParallelSlices(); - } - + // Delete existing parallel slices. We don't update parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); checkData(*this); checkData(rhs); @@ -2209,15 +2045,6 @@ Field3D operator*(const BoutReal lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (rhs.isFci() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs * rhs.yup(i); - result.ydown(i) = lhs * rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs * rhs[index]; @@ -2238,15 +2065,6 @@ Field3D operator/(const BoutReal lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (rhs.isFci() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs / rhs.yup(i); - result.ydown(i) = lhs / rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs / rhs[index]; @@ -2267,15 +2085,6 @@ Field3D operator+(const BoutReal lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (rhs.isFci() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs + rhs.yup(i); - result.ydown(i) = lhs + rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs + rhs[index]; @@ -2296,15 +2105,6 @@ Field3D operator-(const BoutReal lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); -#if BOUT_USE_FCI_AUTOMAGIC - if (rhs.isFci() and rhs.hasParallelSlices()) { - result.splitParallelSlices(); - for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { - result.yup(i) = lhs - rhs.yup(i); - result.ydown(i) = lhs - rhs.ydown(i); - } - } -#endif BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { result[index] = lhs - rhs[index]; @@ -2460,3 +2260,735 @@ FieldPerp operator-(const BoutReal lhs, const FieldPerp& rhs) { checkData(result); return result; } + +// Provide the C++ wrapper for multiplication of Field3D and Field3DParallel +Field3DParallel operator*(const Field3D& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) * rhs.yup(i); + result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] * rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for division of Field3D and Field3DParallel +Field3DParallel operator/(const Field3D& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) / rhs.yup(i); + result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] / rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for addition of Field3D and Field3DParallel +Field3DParallel operator+(const Field3D& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) + rhs.yup(i); + result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] + rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for subtraction of Field3D and Field3DParallel +Field3DParallel operator-(const Field3D& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) - rhs.yup(i); + result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] - rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for multiplication of Field3DParallel and Field3D +Field3DParallel operator*(const Field3DParallel& lhs, const Field3D& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) * rhs.yup(i); + result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] * rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by multiplication with Field3D +Field3DParallel& Field3DParallel::operator*=(const Field3D& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) *= rhs.yup(i); + ydown(i) *= rhs.ydown(i); + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } + + track(rhs, "operator*="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator*="); + (*this) = (*this) * rhs; + } + return *this; +} + +// Provide the C++ wrapper for division of Field3DParallel and Field3D +Field3DParallel operator/(const Field3DParallel& lhs, const Field3D& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) / rhs.yup(i); + result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] / rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by division with Field3D +Field3DParallel& Field3DParallel::operator/=(const Field3D& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) /= rhs.yup(i); + ydown(i) /= rhs.ydown(i); + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } + + track(rhs, "operator/="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator/="); + (*this) = (*this) / rhs; + } + return *this; +} + +// Provide the C++ wrapper for addition of Field3DParallel and Field3D +Field3DParallel operator+(const Field3DParallel& lhs, const Field3D& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) + rhs.yup(i); + result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] + rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by addition with Field3D +Field3DParallel& Field3DParallel::operator+=(const Field3D& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) += rhs.yup(i); + ydown(i) += rhs.ydown(i); + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } + + track(rhs, "operator+="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator+="); + (*this) = (*this) + rhs; + } + return *this; +} + +// Provide the C++ wrapper for subtraction of Field3DParallel and Field3D +Field3DParallel operator-(const Field3DParallel& lhs, const Field3D& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) - rhs.yup(i); + result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] - rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by subtraction with Field3D +Field3DParallel& Field3DParallel::operator-=(const Field3D& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) -= rhs.yup(i); + ydown(i) -= rhs.ydown(i); + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } + + track(rhs, "operator-="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator-="); + (*this) = (*this) - rhs; + } + return *this; +} + +// Provide the C++ wrapper for multiplication of Field3DParallel and Field3DParallel +Field3DParallel operator*(const Field3DParallel& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) * rhs.yup(i); + result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] * rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by multiplication with Field3DParallel +Field3DParallel& Field3DParallel::operator*=(const Field3DParallel& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) *= rhs; + ydown(i) *= rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs[index]; } + + track(rhs, "operator*="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator*="); + (*this) = (*this) * rhs; + } + return *this; +} + +// Provide the C++ wrapper for division of Field3DParallel and Field3DParallel +Field3DParallel operator/(const Field3DParallel& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) / rhs.yup(i); + result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] / rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by division with Field3DParallel +Field3DParallel& Field3DParallel::operator/=(const Field3DParallel& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) /= rhs; + ydown(i) /= rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs[index]; } + + track(rhs, "operator/="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator/="); + (*this) = (*this) / rhs; + } + return *this; +} + +// Provide the C++ wrapper for addition of Field3DParallel and Field3DParallel +Field3DParallel operator+(const Field3DParallel& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) + rhs.yup(i); + result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] + rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by addition with Field3DParallel +Field3DParallel& Field3DParallel::operator+=(const Field3DParallel& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) += rhs; + ydown(i) += rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs[index]; } + + track(rhs, "operator+="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator+="); + (*this) = (*this) + rhs; + } + return *this; +} + +// Provide the C++ wrapper for subtraction of Field3DParallel and Field3DParallel +Field3DParallel operator-(const Field3DParallel& lhs, const Field3DParallel& rhs) { + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) - rhs.yup(i); + result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] - rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by subtraction with Field3DParallel +Field3DParallel& Field3DParallel::operator-=(const Field3DParallel& rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) -= rhs; + ydown(i) -= rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + regionID = fieldmesh->getCommonRegion(regionID, rhs.getRegionID()); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs[index]; } + + track(rhs, "operator-="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, rhs.name); +#endif + + checkData(*this); + + } else { + track(rhs, "operator-="); + (*this) = (*this) - rhs; + } + return *this; +} + +// Provide the C++ wrapper for multiplication of BoutReal and Field3DParallel +Field3DParallel operator*(const BoutReal lhs, const Field3DParallel& rhs) { + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(rhs.getRegionID()); + if (rhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs * rhs.yup(i); + result.ydown(i) = lhs * rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs * rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", "BR", rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for division of BoutReal and Field3DParallel +Field3DParallel operator/(const BoutReal lhs, const Field3DParallel& rhs) { + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(rhs.getRegionID()); + if (rhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs / rhs.yup(i); + result.ydown(i) = lhs / rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs / rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", "BR", rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for addition of BoutReal and Field3DParallel +Field3DParallel operator+(const BoutReal lhs, const Field3DParallel& rhs) { + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(rhs.getRegionID()); + if (rhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs + rhs.yup(i); + result.ydown(i) = lhs + rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs + rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", "BR", rhs.name); +#endif + checkData(result); + return result; +} + +// Provide the C++ wrapper for subtraction of BoutReal and Field3DParallel +Field3DParallel operator-(const BoutReal lhs, const Field3DParallel& rhs) { + + Field3DParallel result{emptyFrom(rhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(rhs.getRegionID()); + if (rhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs - rhs.yup(i); + result.ydown(i) = lhs - rhs.ydown(i); + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs - rhs[index]; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", "BR", rhs.name); +#endif + checkData(result); + return result; +} From d1c5689481cfaeca64e41721cecdf3c73c02db08 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 26 Jun 2025 10:54:01 +0200 Subject: [PATCH 046/259] No need for orderedDicts dicts have been preserving order for several releases now. --- src/field/gen_fieldops.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 4ae8bf8a23..8e961cecb6 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -54,15 +54,13 @@ def smart_open(filename, mode="r"): # The arthimetic operators -# OrderedDict to (try to) ensure consistency between python 2 & 3 -operators = OrderedDict( - [ - ("*", "multiplication"), - ("/", "division"), - ("+", "addition"), - ("-", "subtraction"), - ] -) +operators = { + "*": "multiplication", + "/": "division", + "+": "addition", + "-": "subtraction", +} + header = """// This file is autogenerated - see gen_fieldops.py #include From e01bda2cbdc777fe8d13fd5ee386ee4af35d1734 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 26 Jun 2025 10:54:22 +0200 Subject: [PATCH 047/259] Remove wrong comment, FieldPerp is present --- src/field/gen_fieldops.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 8e961cecb6..839b75dcdf 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -219,7 +219,6 @@ def returnType(f1, f2): region_loop = "BOUT_FOR" # Declare what fields we currently support: - # Field perp is currently missing field3D = Field( "Field3D", ["x", "y", "z"], From 4ffb732409536618bc4422a8cfac81ff83760388 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 5 Jun 2025 10:03:47 +0000 Subject: [PATCH 048/259] Add PETSc version guards for function cast --- include/bout/petsc_interface.hxx | 9 +++++++++ src/solver/impls/imex-bdf2/imex-bdf2.cxx | 20 +++++++++++--------- src/solver/impls/snes/snes.cxx | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index 8e7d44c67d..670d91b2ec 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -615,6 +615,15 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { return PetscVector(vec, result); } +// Compatibility wrappers +// For < 3.24 +#if PETSC_VERSION_GE(3, 24, 0) \ + || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE != 0) +// Nothing to do +#else +using MatFDColoringFn = PetscErrorCode (*)(); +#endif + #endif // BOUT_HAS_PETSC #endif // __PETSC_INTERFACE_H__ diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index adafbb71c5..3629965b87 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -116,7 +117,7 @@ static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, +static PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, true); } @@ -654,9 +655,15 @@ void IMEXBDF2::constructSNES(SNES* snesIn) { // Create data structure for SNESComputeJacobianDefaultColor MatFDColoringCreate(Jmf, iscoloring, &fdcoloring); // Set the function to difference - MatFDColoringSetFunction( - fdcoloring, reinterpret_cast(FormFunctionForColoring), - this); +#if PETSC_VERSION_GE(3, 24, 0) \ + || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE == 0) +#define FUNC_MAYBE_CAST(func) func +#else +#define FUNC_MAYBE_CAST(func) reinterpret_cast(func) +#endif + MatFDColoringSetFunction(fdcoloring, FUNC_MAYBE_CAST(FormFunctionForColoring), + this); +#undef FUNC_MAYBE_CAST MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jmf, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); @@ -680,12 +687,7 @@ void IMEXBDF2::constructSNES(SNES* snesIn) { 0, // Number of nonzeros per row in off-diagonal portion of local submatrix nullptr, &Jmf); -#if PETSC_VERSION_GE(3, 4, 0) SNESSetJacobian(*snesIn, Jmf, Jmf, SNESComputeJacobianDefault, this); -#else - // Before 3.4 - SNESSetJacobian(*snesIn, Jmf, Jmf, SNESDefaultComputeJacobian, this); -#endif MatSetOption(Jmf, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); } diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 2143aad96a..b1db03f80a 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include From 1bc99e5c42ef94f4f93ccdbf651101417125611f Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 6 Jun 2025 11:41:57 +0200 Subject: [PATCH 049/259] Update docs for what PETSc we support 3.23 has been tested in CI so is expected to work. --- manual/RELEASE_HOWTO.md | 1 + manual/sphinx/user_docs/advanced_install.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/manual/RELEASE_HOWTO.md b/manual/RELEASE_HOWTO.md index 4103e6f197..d8ced2afb5 100644 --- a/manual/RELEASE_HOWTO.md +++ b/manual/RELEASE_HOWTO.md @@ -51,6 +51,7 @@ 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` +- [ ] Update what version of PETSc and SUNDIALS we support (upper bound) After PR is merged: diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index 428666dbd7..91d2fa898b 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -480,7 +480,7 @@ 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.19. More recent versions may +Currently, BOUT++ supports PETSc versions 3.7 - 3.23. 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.19, use the following steps:: From 63a868339eddcb8bb843b9fba66424eeb87fd08b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 17 Jun 2025 16:55:24 +0100 Subject: [PATCH 050/259] Fix PETSc version check for MatFDColoringFn typedef --- include/bout/petsc_interface.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index 670d91b2ec..1538fb5b8e 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -618,7 +618,7 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { // Compatibility wrappers // For < 3.24 #if PETSC_VERSION_GE(3, 24, 0) \ - || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE != 0) + || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE == 0) // Nothing to do #else using MatFDColoringFn = PetscErrorCode (*)(); From 8e5a037b92f8a465a0bb00254ae7681725ae8565 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 17 Jun 2025 17:04:13 +0100 Subject: [PATCH 051/259] Move "maybe cast" macro to header for reuse --- include/bout/petsc_interface.hxx | 3 ++- src/solver/impls/imex-bdf2/imex-bdf2.cxx | 11 ++--------- src/solver/impls/snes/snes.cxx | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index 1538fb5b8e..a38938488c 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -619,9 +619,10 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { // For < 3.24 #if PETSC_VERSION_GE(3, 24, 0) \ || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE == 0) -// Nothing to do +#define BOUT_CAST_MATFDCOLORINGFN(func) func #else using MatFDColoringFn = PetscErrorCode (*)(); +#define BOUT_CAST_MATFDCOLORINGFN(func) reinterpret_cast(func) #endif #endif // BOUT_HAS_PETSC diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index 3629965b87..f374d06356 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -655,15 +655,8 @@ void IMEXBDF2::constructSNES(SNES* snesIn) { // Create data structure for SNESComputeJacobianDefaultColor MatFDColoringCreate(Jmf, iscoloring, &fdcoloring); // Set the function to difference -#if PETSC_VERSION_GE(3, 24, 0) \ - || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE == 0) -#define FUNC_MAYBE_CAST(func) func -#else -#define FUNC_MAYBE_CAST(func) reinterpret_cast(func) -#endif - MatFDColoringSetFunction(fdcoloring, FUNC_MAYBE_CAST(FormFunctionForColoring), - this); -#undef FUNC_MAYBE_CAST + MatFDColoringSetFunction(fdcoloring, + BOUT_CAST_MATFDCOLORINGFN(FormFunctionForColoring), this); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jmf, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index b1db03f80a..a2630ad56d 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -42,7 +42,7 @@ static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, +static PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, true); } From b5aa5d0ea2fe8d656a4921573efbdfd34acdddeb Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 17 Jun 2025 18:08:05 +0100 Subject: [PATCH 052/259] Convert macro to constexpr template function Removes some clang-tidy warnings and silences one about reinterpret_cast --- include/bout/petsc_interface.hxx | 14 ++++++++++++-- src/solver/impls/imex-bdf2/imex-bdf2.cxx | 2 +- src/solver/impls/snes/snes.cxx | 5 ++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index a38938488c..2e55534e68 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -619,10 +619,20 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { // For < 3.24 #if PETSC_VERSION_GE(3, 24, 0) \ || (PETSC_VERSION_GE(3, 23, 0) && PETSC_VERSION_RELEASE == 0) -#define BOUT_CAST_MATFDCOLORINGFN(func) func +namespace bout { +template +constexpr auto cast_MatFDColoringFn(T func) { + return func; +} +} // namespace bout #else using MatFDColoringFn = PetscErrorCode (*)(); -#define BOUT_CAST_MATFDCOLORINGFN(func) reinterpret_cast(func) +namespace bout { +template +constexpr auto cast_MatFDColoringFn(T func) { + return reinterpret_cast(func); // NOLINT(*-reinterpret-cast) +} +} // namespace bout #endif #endif // BOUT_HAS_PETSC diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index f374d06356..dad9a8b3b0 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -656,7 +656,7 @@ void IMEXBDF2::constructSNES(SNES* snesIn) { MatFDColoringCreate(Jmf, iscoloring, &fdcoloring); // Set the function to difference MatFDColoringSetFunction(fdcoloring, - BOUT_CAST_MATFDCOLORINGFN(FormFunctionForColoring), this); + bout::cast_MatFDColoringFn(FormFunctionForColoring), this); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jmf, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index a2630ad56d..a68aa43c38 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -585,9 +585,8 @@ int SNESSolver::init() { // Create data structure for SNESComputeJacobianDefaultColor MatFDColoringCreate(Jmf, iscoloring, &fdcoloring); // Set the function to difference - MatFDColoringSetFunction( - fdcoloring, reinterpret_cast(FormFunctionForColoring), - this); + MatFDColoringSetFunction(fdcoloring, + bout::cast_MatFDColoringFn(FormFunctionForColoring), this); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jmf, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); From 2d831da565f0af7628bbb8000b4c56cc8947e03a Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 18 Sep 2024 16:35:25 +0100 Subject: [PATCH 053/259] CI: Bump all ubuntu images --- .github/workflows/tests.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c316ba4db1..e30f55e0c9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,7 +40,7 @@ jobs: - ${{ github.event_name == 'cron' }} config: - name: "CMake, PETSc unreleased" - os: ubuntu-20.04 + os: ubuntu-24.04 cmake_options: "-DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_METRIC_3D=ON -DBOUT_ENABLE_OPENMP=ON @@ -55,13 +55,13 @@ jobs: build_petsc_branch: main on_cron: true - - name: "Default options, Ubuntu 20.04" - os: ubuntu-20.04 + - name: "Default options, Ubuntu 22.04" + os: ubuntu-22.04 cmake_options: "" on_cron: false - name: "Optimised, static" - os: ubuntu-20.04 + os: ubuntu-latest cmake_options: "-DCHECK=0 -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_FLAGS=-Ofast @@ -75,7 +75,7 @@ jobs: on_cron: false - name: "Debug, shared" - os: ubuntu-20.04 + os: ubuntu-latest cmake_options: "-DCHECK=3 -DCMAKE_BUILD_TYPE=Debug -DBOUT_ENABLE_SIGNAL=ON @@ -86,8 +86,8 @@ jobs: -DSUNDIALS_ROOT=/home/runner/local" on_cron: false - - name: "Shared, release, Ubuntu 20.04" - os: ubuntu-20.04 + - name: "Shared, release" + os: ubuntu-latest cmake_options: "-DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_OPENMP=ON -DCMAKE_BUILD_TYPE=Release @@ -113,7 +113,7 @@ jobs: on_cron: false - name: "CMake, new PETSc" - os: ubuntu-20.04 + os: ubuntu-latest cmake_options: "-DBUILD_SHARED_LIBS=ON -DBOUT_ENABLE_METRIC_3D=ON -DBOUT_ENABLE_OPENMP=ON @@ -128,7 +128,7 @@ jobs: on_cron: false - name: "Coverage" - os: ubuntu-20.04 + os: ubuntu-latest cmake_options: "-DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Debug -DCHECK=3 From 4f6b48fe733b25ce0d9f24b0a13735571b9179cd Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 24 Jun 2025 11:37:26 +0200 Subject: [PATCH 054/259] CI: require python3-boututils --- .ci_fedora.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_fedora.sh b/.ci_fedora.sh index 77e7f45055..70ddbfb1ba 100755 --- a/.ci_fedora.sh +++ b/.ci_fedora.sh @@ -42,7 +42,7 @@ then echo "install_weak_deps=False" >> /etc/dnf/dnf.conf echo "minrate=10M" >> /etc/dnf/dnf.conf time dnf -y install dnf5 - time dnf5 -y install dnf5-plugins cmake python3-zoidberg python3-natsort + time dnf5 -y install dnf5-plugins cmake python3-zoidberg python3-natsort python3-boututils # Allow to override packages - see #2073 time dnf5 copr enable -y davidsch/fixes4bout || : time dnf5 -y upgrade From 9f6d7b003ad0f9e4891fa76714a20948f0010dbb Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 24 Jun 2025 10:54:16 +0200 Subject: [PATCH 055/259] CI: Switch to released fedora Resolves: #3127 --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e30f55e0c9..d193337a28 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -229,8 +229,8 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - - name: Build Fedora rawhide - run: ./.ci_fedora.sh setup openmpi rawhide + - name: Build Fedora + run: ./.ci_fedora.sh setup openmpi latest shell: bash env: TRAVIS_BUILD_DIR: ${{ github.workspace }} From 0dd6dfd1a37004ff4be195f1c0534d46716e3c23 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 5 Jun 2025 00:56:05 +0200 Subject: [PATCH 056/259] coloring for petsc solver is very likely broken --- src/solver/impls/petsc/petsc.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 1b81ca36b6..b502fcef10 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -515,9 +515,7 @@ int PetscSolver::init() { CHKERRQ(ierr); ierr = ISColoringDestroy(&iscoloring); CHKERRQ(ierr); - ierr = MatFDColoringSetFunction(matfdcoloring, - reinterpret_cast(solver_f), this); - CHKERRQ(ierr); + throw BoutException("Coloring is not working"); ierr = SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, matfdcoloring); CHKERRQ(ierr); From ced312785cd2586b86b0c31c54ba84ad2dde14e4 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Oct 2024 14:13:10 +0200 Subject: [PATCH 057/259] Try to do the right thing for linking netCDF::netcdf --- CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60d34e1ad7..55b84cd765 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -789,8 +789,15 @@ foreach (flag ${CONFIG_LDFLAGS_LIST}) # 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}") + string(FIND "${flag}" "::" hascolcol) + if (${hascolcol} EQUAL -1) + message("Fixing ${flag} to -l${flag}") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag}") + else() + string(REGEX MATCH "[^:]*$" flag2 "${flag}") + message("Fixing ${flag} to -l${flag2}") + set(_CONFIG_LDFLAGS "${_CONFIG_LDFLAGS} -l${flag2}") + endif() endif() endif() endforeach() From 75768100b1dd4b7d55541d4c0cf0e65b2481e7ae Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 24 Jan 2025 11:23:42 -0800 Subject: [PATCH 058/259] Remove coverage test from github workflow --- .github/workflows/tests.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d193337a28..ede53ef20d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -127,25 +127,7 @@ jobs: build_petsc: -petsc on_cron: false - - name: "Coverage" - os: ubuntu-latest - 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 - on_cron: false exclude: - # Don't run the coverage tests if the branch isn't master or next - - is_master_or_next: false - config: - name: "Coverage" - is_cron: true config: on_cron: false @@ -204,22 +186,6 @@ jobs: - 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' }} - # Explicitly run the coverage capture target, because - # ci_script.sh also does the upload, and we're going to do - # that ourselves in the next step - run: | - # Ensure that there is a corresponding .gcda file for every .gcno file - # 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 -C build code-coverage-capture - - - name: Upload coverage - if: ${{ matrix.config.name == 'Coverage' }} - uses: codecov/codecov-action@v5 - Fedora: # This is its own job as it doesn't use most of the steps of the # standard_tests From 8eafc089c623aa83ea3faba5d5afecae007e4c9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 22:32:47 +0000 Subject: [PATCH 059/259] Bump externalpackages/boutdata from `a7a372d` to `7164a89` --- updated-dependencies: - dependency-name: externalpackages/boutdata dependency-version: 7164a89c16dba1049d42e1715506b988c0af5926 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/boutdata | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/boutdata b/externalpackages/boutdata index a7a372d5de..7164a89c16 160000 --- a/externalpackages/boutdata +++ b/externalpackages/boutdata @@ -1 +1 @@ -Subproject commit a7a372d5de7594cbe16381a3a82289ddaa58b6e7 +Subproject commit 7164a89c16dba1049d42e1715506b988c0af5926 From 7c2c6543d871f2e9144eb21d0cd9031eed530d3f Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 2 Jul 2025 11:04:43 +0100 Subject: [PATCH 060/259] Fix name clash in some examples and MMS tests `FieldFactory` expects an `input` section, so this cannot be used as a variable name in the input file --- examples/laplacexy/laplace_perp/square/BOUT.inp | 2 +- examples/laplacexy/laplace_perp/test.cxx | 2 +- examples/laplacexy/laplace_perp/torus/BOUT.inp | 2 +- tests/MMS/laplace/data/BOUT.inp | 2 +- tests/MMS/laplace/laplace.cxx | 6 ++++-- tests/MMS/spatial/d2dx2/data/BOUT.inp | 2 +- tests/MMS/spatial/d2dx2/test_d2dx2.cxx | 2 +- tests/MMS/spatial/d2dz2/data/BOUT.inp | 2 +- tests/MMS/spatial/d2dz2/test_d2dz2.cxx | 2 +- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/laplacexy/laplace_perp/square/BOUT.inp b/examples/laplacexy/laplace_perp/square/BOUT.inp index 95ecb7119f..38fb175d90 100644 --- a/examples/laplacexy/laplace_perp/square/BOUT.inp +++ b/examples/laplacexy/laplace_perp/square/BOUT.inp @@ -1,5 +1,5 @@ -input = sin(pi*x - y) +input_field = sin(pi*x - y) non_uniform = true # Include corrections to second derivatives diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index 1312b005da..8a9a99f92c 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -47,7 +47,7 @@ int main(int argc, char** argv) { /////////////////////////////////////// // Read an analytic input - Field2D input = FieldFactory::get()->create2D("input", Options::getRoot(), mesh); + Field2D input = FieldFactory::get()->create2D("input_field", Options::getRoot(), mesh); // Create a LaplaceXY solver LaplaceXY* laplacexy = new LaplaceXY(mesh); diff --git a/examples/laplacexy/laplace_perp/torus/BOUT.inp b/examples/laplacexy/laplace_perp/torus/BOUT.inp index 365294174f..4109b44bab 100644 --- a/examples/laplacexy/laplace_perp/torus/BOUT.inp +++ b/examples/laplacexy/laplace_perp/torus/BOUT.inp @@ -1,5 +1,5 @@ -input = sin(pi*x - y) +input_field = sin(pi*x - y) calc_metric = true # Read Rxy, Bpxy etc and calculate metric non_uniform = true # Include corrections to second derivatives diff --git a/tests/MMS/laplace/data/BOUT.inp b/tests/MMS/laplace/data/BOUT.inp index 1965b1e8f7..5b3cc37b09 100644 --- a/tests/MMS/laplace/data/BOUT.inp +++ b/tests/MMS/laplace/data/BOUT.inp @@ -5,7 +5,7 @@ MXG = 1 solution = sin(pi*x) -input = -pi^2*sin(pi*x) +input_field = -pi^2*sin(pi*x) [mesh] diff --git a/tests/MMS/laplace/laplace.cxx b/tests/MMS/laplace/laplace.cxx index 54dbaaba67..e81ca64fa1 100644 --- a/tests/MMS/laplace/laplace.cxx +++ b/tests/MMS/laplace/laplace.cxx @@ -5,6 +5,7 @@ #include using bout::globals::mesh; +using namespace std::string_literals; int main(int argc, char** argv) { int init_err = BoutInitialise(argc, argv); @@ -31,10 +32,11 @@ int main(int argc, char** argv) { FieldFactory fact(mesh); - std::shared_ptr gen = fact.parse("input"); + const auto input_name = "input_field"s; + std::shared_ptr gen = fact.parse(input_name); output << "GEN = " << gen->str() << endl; - Field3D input = fact.create3D("input"); + Field3D input = fact.create3D(input_name); Field3D result = lap->solve(input); diff --git a/tests/MMS/spatial/d2dx2/data/BOUT.inp b/tests/MMS/spatial/d2dx2/data/BOUT.inp index 5c1deaf0af..cdc0d96139 100644 --- a/tests/MMS/spatial/d2dx2/data/BOUT.inp +++ b/tests/MMS/spatial/d2dx2/data/BOUT.inp @@ -5,7 +5,7 @@ MXG = 1 MYG = 1 # No guard cells in Y -input = sin(0.5*pi*x) +input_field = sin(0.5*pi*x) solution = -sin(0.5*pi*x) * 0.25*pi*pi [mesh] diff --git a/tests/MMS/spatial/d2dx2/test_d2dx2.cxx b/tests/MMS/spatial/d2dx2/test_d2dx2.cxx index 6b35b719e1..228dca4b2a 100644 --- a/tests/MMS/spatial/d2dx2/test_d2dx2.cxx +++ b/tests/MMS/spatial/d2dx2/test_d2dx2.cxx @@ -12,7 +12,7 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); - Field3D input = FieldFactory::get()->create3D("input", Options::getRoot(), mesh); + Field3D input = FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh); Field3D solution = FieldFactory::get()->create3D("solution", Options::getRoot(), mesh); // At this point the boundary cells are set to the analytic solution diff --git a/tests/MMS/spatial/d2dz2/data/BOUT.inp b/tests/MMS/spatial/d2dz2/data/BOUT.inp index 6618d6f574..640411c112 100644 --- a/tests/MMS/spatial/d2dz2/data/BOUT.inp +++ b/tests/MMS/spatial/d2dz2/data/BOUT.inp @@ -5,7 +5,7 @@ zperiod = 1 MXG = 0 # No guard cells in X MYG = 1 # No guard cells in Y -input = sin(z) +input_field = sin(z) solution = -sin(z) [mesh] diff --git a/tests/MMS/spatial/d2dz2/test_d2dz2.cxx b/tests/MMS/spatial/d2dz2/test_d2dz2.cxx index 0b7aa2cde4..9dccb6a992 100644 --- a/tests/MMS/spatial/d2dz2/test_d2dz2.cxx +++ b/tests/MMS/spatial/d2dz2/test_d2dz2.cxx @@ -12,7 +12,7 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); - Field3D input = FieldFactory::get()->create3D("input", Options::getRoot(), mesh); + Field3D input = FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh); Field3D solution = FieldFactory::get()->create3D("solution", Options::getRoot(), mesh); Field3D result = D2DZ2(input); From 824d095d101789137460559cd29ac6d7e62190f0 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 2 Jul 2025 11:07:12 +0100 Subject: [PATCH 061/259] Fix some clang-tidy warnings --- examples/laplacexy/laplace_perp/test.cxx | 14 +++++++++----- tests/MMS/laplace/laplace.cxx | 5 +++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index 8a9a99f92c..291faffabc 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -10,11 +10,15 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); /////////////////////////////////////// - bool calc_metric; - calc_metric = Options::root()["calc_metric"].withDefault(false); + const bool calc_metric = Options::root()["calc_metric"].withDefault(false); if (calc_metric) { // Read metric tensor - Field2D Rxy, Btxy, Bpxy, B0, hthe, I; + Field2D Rxy; + Field2D Btxy; + Field2D Bpxy; + Field2D B0; + Field2D hthe; + Field2D I; mesh->get(Rxy, "Rxy"); // m mesh->get(Btxy, "Btxy"); // T mesh->get(Bpxy, "Bpxy"); // T @@ -50,10 +54,10 @@ int main(int argc, char** argv) { Field2D input = FieldFactory::get()->create2D("input_field", Options::getRoot(), mesh); // Create a LaplaceXY solver - LaplaceXY* laplacexy = new LaplaceXY(mesh); + LaplaceXY laplacexy{mesh}; // Solve, using 0.0 as starting guess - Field2D solved = laplacexy->solve(input, 0.0); + Field2D solved = laplacexy.solve(input, 0.0); // Need to communicate guard cells mesh->communicate(solved); diff --git a/tests/MMS/laplace/laplace.cxx b/tests/MMS/laplace/laplace.cxx index e81ca64fa1..15fc849d8f 100644 --- a/tests/MMS/laplace/laplace.cxx +++ b/tests/MMS/laplace/laplace.cxx @@ -11,7 +11,8 @@ int main(int argc, char** argv) { int init_err = BoutInitialise(argc, argv); if (init_err < 0) { return 0; - } else if (init_err > 0) { + } + if (init_err > 0) { return init_err; } @@ -34,7 +35,7 @@ int main(int argc, char** argv) { const auto input_name = "input_field"s; std::shared_ptr gen = fact.parse(input_name); - output << "GEN = " << gen->str() << endl; + output.write("GEN = {}\n", gen->str()); Field3D input = fact.create3D(input_name); From 5f0720a5b7831568089118c9bba75ee20006a2c6 Mon Sep 17 00:00:00 2001 From: malamast Date: Wed, 2 Jul 2025 18:15:03 -0700 Subject: [PATCH 062/259] SNES solver: Added a PID controller to update the timestep of the backward euler SNES solver. The user sets target_its a desired number of nonlinear iterations and the timestep is updated based on the ratio of that number and the actual number on nonlinear iteration of each Newton step. The exponent can be tuned to the problem needs. A smaller exponent results in smaller changes of dt. --- src/solver/impls/snes/snes.cxx | 144 +++++++++++++++++++++++++-------- src/solver/impls/snes/snes.hxx | 14 ++++ 2 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 15099f9e2a..8b0b09fea2 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -118,6 +118,9 @@ SNESSolver::SNESSolver(Options* opts) maxits((*options)["max_nonlinear_iterations"] .doc("Maximum number of nonlinear iterations per SNES solve") .withDefault(50)), + maxf((*options)["maxf"] + .doc("Maximum number of function evaluations per SNES solve") + .withDefault(10000)), lower_its((*options)["lower_its"] .doc("Iterations below which the next timestep is increased") .withDefault(static_cast(maxits * 0.5))), @@ -133,6 +136,17 @@ SNESSolver::SNESSolver(Options* opts) timestep_factor_on_lower_its((*options)["timestep_factor_on_lower_its"] .doc("Multiply timestep if iterations are below lower_its") .withDefault(1.4)), + pidController( + (*options)["pidController"].doc("Use PID controller?").withDefault(false)), + target_its((*options)["target_its"] + .doc("Target snes iterations") + .withDefault(static_cast(7))), + kP((*options)["kP"].doc("Proportional PID parameter") + .withDefault(0.7)), + kI((*options)["kI"].doc("Integral PID parameter") + .withDefault(0.3)), + kD((*options)["kD"].doc("Derivative PID parameter") + .withDefault(0.2)), diagnose( (*options)["diagnose"].doc("Print additional diagnostics").withDefault(false)), diagnose_failures((*options)["diagnose_failures"] @@ -632,14 +646,21 @@ int SNESSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - // Set Jacobian and preconditioner to persist across time steps - SNESSetLagJacobianPersists(snes, PETSC_TRUE); - SNESSetLagPreconditionerPersists(snes, PETSC_TRUE); + if (pidController){ + nl_its_prev = target_its; + nl_its_prev2 = target_its; + SNESSetLagJacobianPersists(snes, PETSC_FALSE); + SNESSetLagPreconditionerPersists(snes, PETSC_FALSE); + } else { + // Set Jacobian and preconditioner to persist across time steps + SNESSetLagJacobianPersists(snes, PETSC_TRUE); + SNESSetLagPreconditionerPersists(snes, PETSC_TRUE); + } SNESSetLagPreconditioner(snes, 1); // Rebuild when Jacobian is rebuilt } // Set tolerances - SNESSetTolerances(snes, atol, rtol, stol, maxits, PETSC_DEFAULT); + SNESSetTolerances(snes, atol, rtol, stol, maxits, maxf); // Force SNES to take at least one nonlinear iteration. // This may prevent the solver from getting stuck in false steady state conditions @@ -843,6 +864,11 @@ int SNESSolver::run() { VecAXPBY(snes_x, -beta, (1. + beta), x1); } + + if (pidController){ + SNESSetLagJacobian(snes, lag_jacobian); + } + // Run the solver PetscErrorCode ierr = SNESSolve(snes, nullptr, snes_x); @@ -900,6 +926,7 @@ int SNESSolver::run() { updateColoring(); jacobian_pruned = false; // Reset flag. Will be set after pruning. } + if (saved_jacobian_lag == 0) { // This triggers a Jacobian recalculation SNESGetLagJacobian(snes, &saved_jacobian_lag); @@ -1033,45 +1060,67 @@ int SNESSolver::run() { #endif // PETSC_VERSION_GE(3,20,0) if (looping) { - // Consider changing the timestep. - // Note: The preconditioner depends on the timestep, - // so if it is not recalculated the it will be less - // effective. - if ((nl_its <= lower_its) && (timestep < max_timestep) - && (steps_since_snes_failure > 2)) { - // Increase timestep slightly - timestep *= timestep_factor_on_lower_its; - - if (timestep > max_timestep) { - timestep = max_timestep; + + if (pidController){ + // Changing the timestep. + // Note: The preconditioner depends on the timestep, + // so we recalculate the jacobian and the preconditioner + // every time the timestep changes + + timestep = pid(timestep, nl_its); + + // NOTE(malamast): Do we really need this? + // Recompute Jacobian (for now) + if (saved_jacobian_lag == 0) { + SNESGetLagJacobian(snes, &saved_jacobian_lag); + SNESSetLagJacobian(snes, 1); } - // Note: Setting the SNESJacobianFn to NULL retains - // previously set evaluation function. - // - // The SNES Jacobian is a combination of the RHS Jacobian - // and a factor involving the timestep. - // Depends on equation_form - // -> Probably call SNESSetJacobian(snes, Jfd, Jfd, NULL, fdcoloring); - if (static_cast(lin_its) / nl_its > 4) { - // Recompute Jacobian (for now) + } else { + + // Consider changing the timestep. + // Note: The preconditioner depends on the timestep, + // so if it is not recalculated the it will be less + // effective. + if ((nl_its <= lower_its) && (timestep < max_timestep) + && (steps_since_snes_failure > 2)) { + // Increase timestep slightly + timestep *= timestep_factor_on_lower_its; + + if (timestep > max_timestep) { + timestep = max_timestep; + } + + // Note: Setting the SNESJacobianFn to NULL retains + // previously set evaluation function. + // + // The SNES Jacobian is a combination of the RHS Jacobian + // and a factor involving the timestep. + // Depends on equation_form + // -> Probably call SNESSetJacobian(snes, Jfd, Jfd, NULL, fdcoloring); + + if (static_cast(lin_its) / nl_its > 4) { + // Recompute Jacobian (for now) + if (saved_jacobian_lag == 0) { + SNESGetLagJacobian(snes, &saved_jacobian_lag); + SNESSetLagJacobian(snes, 1); + } + } + + } else if (nl_its >= upper_its) { + // Reduce timestep slightly + timestep *= timestep_factor_on_upper_its; + + // Recompute Jacobian if (saved_jacobian_lag == 0) { SNESGetLagJacobian(snes, &saved_jacobian_lag); SNESSetLagJacobian(snes, 1); } } - } else if (nl_its >= upper_its) { - // Reduce timestep slightly - timestep *= timestep_factor_on_upper_its; - - // Recompute Jacobian - if (saved_jacobian_lag == 0) { - SNESGetLagJacobian(snes, &saved_jacobian_lag); - SNESSetLagJacobian(snes, 1); - } } + } snes_failures = 0; } while (looping); @@ -1386,4 +1435,33 @@ void SNESSolver::updateColoring() { } } + +BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { + + /* ---------- multiplicative PID factors ---------- */ + BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); + BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); + BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) / double(nl_its_prev2), kD); + + // clamp groth factor to avoid huge changes + BoutReal fac = facP * facI * facD; + if (fac < 0.2) + fac = 0.2; + else if (fac > 5.0) + fac = 5.0; + + /* ---------- update timestep and history ---------- */ + BoutReal dt_new = timestep * fac; + + if (dt_new > max_timestep) { + dt_new = max_timestep; + } + + nl_its_prev2 = nl_its_prev; + nl_its_prev = static_cast(nl_its); + + return dt_new; +} + + #endif // BOUT_HAS_PETSC diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index cba2352582..02e2368d71 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -98,6 +98,7 @@ private: BoutReal atol; ///< Absolute tolerance BoutReal rtol; ///< Relative tolerance BoutReal stol; ///< Convergence tolerance + int maxf; ///< Maximum number of function evaluations allowed in the solver (default: 10000) int maxits; ///< Maximum nonlinear iterations int lower_its, upper_its; ///< Limits on iterations for timestep adjustment @@ -106,6 +107,19 @@ private: BoutReal timestep_factor_on_upper_its; BoutReal timestep_factor_on_lower_its; + ///< PID controller parameters + bool pidController; ///< Use PID controller? + int target_its; ///< Target number of nonlinear iterations for the PID controller. + ///< Use with caution! Not tested values. + BoutReal kP; ///< (0.6 - 0.8) Proportional parameter (main response to current step) + BoutReal kI; ///< (0.2 - 0.4) Integral parameter (smooths history of changes) + BoutReal kD; ///< (0.1 - 0.3) Derivative (dampens oscillation - optional) + + int nl_its_prev; + int nl_its_prev2; + + BoutReal pid(BoutReal timestep, int nl_its); ///< Updates the timestep + bool diagnose; ///< Output additional diagnostics bool diagnose_failures; ///< Print diagnostics on SNES failures From 656dbdcf6120810c5abc3e24a7e6ba507e398c12 Mon Sep 17 00:00:00 2001 From: malamast <42969991+malamast@users.noreply.github.com> Date: Thu, 3 Jul 2025 02:28:18 +0000 Subject: [PATCH 063/259] Apply clang-format changes --- src/solver/impls/snes/snes.cxx | 57 ++++++++++++++++------------------ src/solver/impls/snes/snes.hxx | 10 +++--- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 8b0b09fea2..8b763acf13 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -119,8 +119,8 @@ SNESSolver::SNESSolver(Options* opts) .doc("Maximum number of nonlinear iterations per SNES solve") .withDefault(50)), maxf((*options)["maxf"] - .doc("Maximum number of function evaluations per SNES solve") - .withDefault(10000)), + .doc("Maximum number of function evaluations per SNES solve") + .withDefault(10000)), lower_its((*options)["lower_its"] .doc("Iterations below which the next timestep is increased") .withDefault(static_cast(maxits * 0.5))), @@ -128,25 +128,24 @@ SNESSolver::SNESSolver(Options* opts) .doc("Iterations above which the next timestep is reduced") .withDefault(static_cast(maxits * 0.8))), timestep_factor_on_failure((*options)["timestep_factor_on_failure"] - .doc("Multiply timestep on convergence failure") - .withDefault(0.5)), - timestep_factor_on_upper_its((*options)["timestep_factor_on_upper_its"] - .doc("Multiply timestep if iterations exceed upper_its") - .withDefault(0.9)), - timestep_factor_on_lower_its((*options)["timestep_factor_on_lower_its"] - .doc("Multiply timestep if iterations are below lower_its") - .withDefault(1.4)), + .doc("Multiply timestep on convergence failure") + .withDefault(0.5)), + timestep_factor_on_upper_its( + (*options)["timestep_factor_on_upper_its"] + .doc("Multiply timestep if iterations exceed upper_its") + .withDefault(0.9)), + timestep_factor_on_lower_its( + (*options)["timestep_factor_on_lower_its"] + .doc("Multiply timestep if iterations are below lower_its") + .withDefault(1.4)), pidController( (*options)["pidController"].doc("Use PID controller?").withDefault(false)), target_its((*options)["target_its"] - .doc("Target snes iterations") - .withDefault(static_cast(7))), - kP((*options)["kP"].doc("Proportional PID parameter") - .withDefault(0.7)), - kI((*options)["kI"].doc("Integral PID parameter") - .withDefault(0.3)), - kD((*options)["kD"].doc("Derivative PID parameter") - .withDefault(0.2)), + .doc("Target snes iterations") + .withDefault(static_cast(7))), + kP((*options)["kP"].doc("Proportional PID parameter").withDefault(0.7)), + kI((*options)["kI"].doc("Integral PID parameter").withDefault(0.3)), + kD((*options)["kD"].doc("Derivative PID parameter").withDefault(0.2)), diagnose( (*options)["diagnose"].doc("Print additional diagnostics").withDefault(false)), diagnose_failures((*options)["diagnose_failures"] @@ -646,7 +645,7 @@ int SNESSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - if (pidController){ + if (pidController) { nl_its_prev = target_its; nl_its_prev2 = target_its; SNESSetLagJacobianPersists(snes, PETSC_FALSE); @@ -864,8 +863,7 @@ int SNESSolver::run() { VecAXPBY(snes_x, -beta, (1. + beta), x1); } - - if (pidController){ + if (pidController) { SNESSetLagJacobian(snes, lag_jacobian); } @@ -1061,7 +1059,7 @@ int SNESSolver::run() { if (looping) { - if (pidController){ + if (pidController) { // Changing the timestep. // Note: The preconditioner depends on the timestep, // so we recalculate the jacobian and the preconditioner @@ -1076,9 +1074,8 @@ int SNESSolver::run() { SNESSetLagJacobian(snes, 1); } - } else { - + // Consider changing the timestep. // Note: The preconditioner depends on the timestep, // so if it is not recalculated the it will be less @@ -1118,9 +1115,7 @@ int SNESSolver::run() { SNESSetLagJacobian(snes, 1); } } - } - } snes_failures = 0; } while (looping); @@ -1435,13 +1430,14 @@ void SNESSolver::updateColoring() { } } - BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ - BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); + BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) / double(nl_its_prev2), kD); + BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) + / double(nl_its_prev2), + kD); // clamp groth factor to avoid huge changes BoutReal fac = facP * facI * facD; @@ -1458,10 +1454,9 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { } nl_its_prev2 = nl_its_prev; - nl_its_prev = static_cast(nl_its); + nl_its_prev = static_cast(nl_its); return dt_new; } - #endif // BOUT_HAS_PETSC diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index 02e2368d71..8a0b5bcecb 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -98,7 +98,7 @@ private: BoutReal atol; ///< Absolute tolerance BoutReal rtol; ///< Relative tolerance BoutReal stol; ///< Convergence tolerance - int maxf; ///< Maximum number of function evaluations allowed in the solver (default: 10000) + int maxf; ///< Maximum number of function evaluations allowed in the solver (default: 10000) int maxits; ///< Maximum nonlinear iterations int lower_its, upper_its; ///< Limits on iterations for timestep adjustment @@ -108,12 +108,12 @@ private: BoutReal timestep_factor_on_lower_its; ///< PID controller parameters - bool pidController; ///< Use PID controller? - int target_its; ///< Target number of nonlinear iterations for the PID controller. - ///< Use with caution! Not tested values. + bool pidController; ///< Use PID controller? + int target_its; ///< Target number of nonlinear iterations for the PID controller. + ///< Use with caution! Not tested values. BoutReal kP; ///< (0.6 - 0.8) Proportional parameter (main response to current step) BoutReal kI; ///< (0.2 - 0.4) Integral parameter (smooths history of changes) - BoutReal kD; ///< (0.1 - 0.3) Derivative (dampens oscillation - optional) + BoutReal kD; ///< (0.1 - 0.3) Derivative (dampens oscillation - optional) int nl_its_prev; int nl_its_prev2; From 5a240c85eb6fa8bc22b0351342a50e7205517d4d Mon Sep 17 00:00:00 2001 From: Malamas Tsagkaridis <42969991+malamast@users.noreply.github.com> Date: Mon, 7 Jul 2025 13:10:51 -0700 Subject: [PATCH 064/259] Update src/solver/impls/snes/snes.cxx Code changes suggested by ZedThree Co-authored-by: Peter Hill --- src/solver/impls/snes/snes.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 8b763acf13..678713f445 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -142,7 +142,7 @@ SNESSolver::SNESSolver(Options* opts) (*options)["pidController"].doc("Use PID controller?").withDefault(false)), target_its((*options)["target_its"] .doc("Target snes iterations") - .withDefault(static_cast(7))), + .withDefault(7)), kP((*options)["kP"].doc("Proportional PID parameter").withDefault(0.7)), kI((*options)["kI"].doc("Integral PID parameter").withDefault(0.3)), kD((*options)["kD"].doc("Derivative PID parameter").withDefault(0.2)), From 9276da0e3fa50b7a9f613dabf011b018fa16004e Mon Sep 17 00:00:00 2001 From: malamast <42969991+malamast@users.noreply.github.com> Date: Mon, 7 Jul 2025 20:12:06 +0000 Subject: [PATCH 065/259] Apply clang-format changes --- src/bout++.cxx | 2 +- src/solver/impls/snes/snes.cxx | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bout++.cxx b/src/bout++.cxx index 7f23cf5f91..4e9e37fe8d 100644 --- a/src/bout++.cxx +++ b/src/bout++.cxx @@ -84,7 +84,7 @@ const char DEFAULT_DIR[] = "data"; // Define S_ISDIR if not defined by system headers (that is, MSVC) // Taken from https://github.com/curl/curl/blob/e59540139a398dc70fde6aec487b19c5085105af/lib/curl_setup.h#L748-L751 #if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) -#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifdef _MSC_VER diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 678713f445..9906274a6e 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -140,9 +140,7 @@ SNESSolver::SNESSolver(Options* opts) .withDefault(1.4)), pidController( (*options)["pidController"].doc("Use PID controller?").withDefault(false)), - target_its((*options)["target_its"] - .doc("Target snes iterations") - .withDefault(7)), + target_its((*options)["target_its"].doc("Target snes iterations").withDefault(7)), kP((*options)["kP"].doc("Proportional PID parameter").withDefault(0.7)), kI((*options)["kI"].doc("Integral PID parameter").withDefault(0.3)), kD((*options)["kD"].doc("Derivative PID parameter").withDefault(0.2)), From 210a6bc51499aaf39a01ee46ce4408b5909692da Mon Sep 17 00:00:00 2001 From: Malamas Tsagkaridis <42969991+malamast@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:34:07 -0700 Subject: [PATCH 066/259] Update src/solver/impls/snes/snes.cxx Co-authored-by: Peter Hill --- src/solver/impls/snes/snes.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 9906274a6e..387c908cb8 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1431,9 +1431,9 @@ void SNESSolver::updateColoring() { BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ - BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); - BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) + const BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); + const BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); + const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) / double(nl_its_prev2), kD); From e881832ad7d0d5447886b0787af8ab179d9c833d Mon Sep 17 00:00:00 2001 From: Malamas Tsagkaridis <42969991+malamast@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:34:26 -0700 Subject: [PATCH 067/259] Update src/solver/impls/snes/snes.cxx Co-authored-by: Peter Hill --- src/solver/impls/snes/snes.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 387c908cb8..a0f9c06801 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1437,12 +1437,8 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { / double(nl_its_prev2), kD); - // clamp groth factor to avoid huge changes - BoutReal fac = facP * facI * facD; - if (fac < 0.2) - fac = 0.2; - else if (fac > 5.0) - fac = 5.0; + // clamp growth factor to avoid huge changes + const BoutReal fac = std::clamp(facP * facI * facD, 0.2, 5.0); /* ---------- update timestep and history ---------- */ BoutReal dt_new = timestep * fac; From 133980416d2b266e15a718b3ef045b7b355a37e4 Mon Sep 17 00:00:00 2001 From: Malamas Tsagkaridis <42969991+malamast@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:34:37 -0700 Subject: [PATCH 068/259] Update src/solver/impls/snes/snes.cxx Co-authored-by: Peter Hill --- src/solver/impls/snes/snes.cxx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index a0f9c06801..9d9a396c3c 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1441,11 +1441,7 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { const BoutReal fac = std::clamp(facP * facI * facD, 0.2, 5.0); /* ---------- update timestep and history ---------- */ - BoutReal dt_new = timestep * fac; - - if (dt_new > max_timestep) { - dt_new = max_timestep; - } + const BoutReal dt_new = std::min(timestep * fac, max_timestep); nl_its_prev2 = nl_its_prev; nl_its_prev = static_cast(nl_its); From 687d21c5da8e40c68ff5d7306ae769a058ce9038 Mon Sep 17 00:00:00 2001 From: Malamas Tsagkaridis <42969991+malamast@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:34:47 -0700 Subject: [PATCH 069/259] Update src/solver/impls/snes/snes.cxx Co-authored-by: Peter Hill --- src/solver/impls/snes/snes.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 9d9a396c3c..89910f1655 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1444,7 +1444,7 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { const BoutReal dt_new = std::min(timestep * fac, max_timestep); nl_its_prev2 = nl_its_prev; - nl_its_prev = static_cast(nl_its); + nl_its_prev = nl_its; return dt_new; } From 0c8ef879a944b2d58fdbdc04ac74f69f2c37c33f Mon Sep 17 00:00:00 2001 From: Malamas Tsagkaridis <42969991+malamast@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:34:57 -0700 Subject: [PATCH 070/259] Update src/solver/impls/snes/snes.cxx Co-authored-by: Peter Hill --- src/solver/impls/snes/snes.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 89910f1655..0b61320f34 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1083,9 +1083,7 @@ int SNESSolver::run() { // Increase timestep slightly timestep *= timestep_factor_on_lower_its; - if (timestep > max_timestep) { - timestep = max_timestep; - } + timestep = std::min(timestep, max_timestep); // Note: Setting the SNESJacobianFn to NULL retains // previously set evaluation function. From fd6f18943cf2d715a507ce50cb7ff702a21b6196 Mon Sep 17 00:00:00 2001 From: malamast <42969991+malamast@users.noreply.github.com> Date: Tue, 8 Jul 2025 18:36:20 +0000 Subject: [PATCH 071/259] Apply clang-format changes --- src/solver/impls/snes/snes.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 0b61320f34..e14d3d4569 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1431,9 +1431,9 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ const BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); const BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) - / double(nl_its_prev2), - kD); + const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) + / double(nl_its) / double(nl_its_prev2), + kD); // clamp growth factor to avoid huge changes const BoutReal fac = std::clamp(facP * facI * facD, 0.2, 5.0); From 86dc232b63e50248a9fa9293893880459660990e Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 10 Jul 2025 13:57:16 +0200 Subject: [PATCH 072/259] Implement more of Field3DParallel --- include/bout/field.hxx | 2 +- include/bout/field3d.hxx | 35 ++++++++++++++++++++++++++++------- src/field/field3d.cxx | 37 ++++++++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 27835ecbd7..876e76a0b5 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -185,7 +185,7 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { template inline T emptyFrom(const T& f) { static_assert(bout::utils::is_Field_v, "emptyFrom only works on Fields"); - return T(f.getMesh(), f.getLocation(), {f.getDirectionY(), f.getDirectionZ()}, + return T(f.getMesh(), f.getLocation(), DirectionTypes{f.getDirectionY(), f.getDirectionZ()}, f.getRegionID()) .allocate(); } diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index a8f2c183ae..a81a79d8a3 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -38,6 +38,7 @@ class Field3D; #include class Mesh; +class Field3DParallel; /// Class for 3D X-Y-Z scalar fields /*! @@ -525,6 +526,8 @@ public: bool allowCalcParallelSlices{true}; + inline Field3DParallel asF3dwy(); + protected: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null int nx{-1}, ny{-1}, nz{-1}; @@ -703,15 +706,12 @@ class Field3DParallel: public Field3D { public: template - Field3DParallel(Types... args): Field3D(&args ...) { - ensureFieldAligned(); - } - Field3DParallel(Field3D&& f3d): Field3D(std::move(f3d)) { - ensureFieldAligned(); - } - Field3DParallel(const Field3D& f3d): Field3D(f3d) { + Field3DParallel(Types... args): Field3D(args ...) { ensureFieldAligned(); } + // Field3DParallel(const Field2D& f) : Field3D(f) { + // ensureFieldAligned(); + // } // Explicitly needed, as DirectionTypes is sometimes constructed from a // brace enclosed list Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, @@ -727,6 +727,13 @@ class Field3DParallel: public Field3D Field3D(std::move(data), localmesh, location, directions_in) { ensureFieldAligned(); } + Field3DParallel(BoutReal, Mesh*); + Field3D& asF3d() { + return *this; + } + const Field3D& asF3d() const { + return *this; + } Field3DParallel& operator*=(const Field3D&); Field3DParallel& operator/=(const Field3D&); @@ -740,8 +747,22 @@ class Field3DParallel: public Field3D Field3DParallel& operator/=(BoutReal); Field3DParallel& operator+=(BoutReal); Field3DParallel& operator-=(BoutReal); + Field3DParallel& operator=(const Field3D& rhs) { + Field3D::operator=(rhs); + ensureFieldAligned(); + return *this; + } + Field3DParallel& operator=(Field3D&& rhs) { + Field3D::operator=(std::move(rhs)); + ensureFieldAligned(); + return *this; + } + Field3DParallel& operator=(BoutReal); private: void ensureFieldAligned(); }; +Field3DParallel Field3D::asF3dwy() { + return Field3DParallel(*this); +} #endif /* BOUT_FIELD3D_H */ diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 0c6cefd1cb..db9a054e80 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -93,7 +93,13 @@ Field3D::Field3D(const BoutReal val, Mesh* localmesh) : Field3D(localmesh) { TRACE("Field3D: Copy constructor from value"); *this = val; -#if BOUT_USE_FCI_AUTOMAGIC +} + +Field3DParallel::Field3DParallel(const BoutReal val, Mesh* localmesh) : Field3D(localmesh) { + + TRACE("Field3DParallel: Copy constructor from value"); + + *this = val; if (this->isFci()) { splitParallelSlices(); for (size_t i = 0; i < numberParallelSlices(); ++i) { @@ -101,9 +107,9 @@ Field3D::Field3D(const BoutReal val, Mesh* localmesh) : Field3D(localmesh) { ydown(i) = val; } } -#endif } + Field3D::Field3D(Array data_in, Mesh* localmesh, CELL_LOC datalocation, DirectionTypes directions_in) : Field(localmesh, datalocation, directions_in), data(std::move(data_in)) { @@ -361,18 +367,30 @@ Field3D& Field3D::operator=(const BoutReal val) { TRACE("Field3D = BoutReal"); track(val, "operator="); -#if BOUT_USE_FCI_AUTOMAGIC - if (isFci() && hasParallelSlices()) { + // Delete existing parallel slices. We don't copy parallel slices, so any + // that currently exist will be incorrect. + clearParallelSlices(); + resetRegion(); + + allocate(); + + BOUT_FOR(i, getRegion("RGN_ALL")) { (*this)[i] = val; } + this->name = "BR"; + + return *this; +} + +Field3DParallel& Field3DParallel::operator=(const BoutReal val) { + TRACE("Field3DParallel = BoutReal"); + track(val, "operator="); + + if (isFci()) { + ASSERT2(hasParallelSlices()); for (size_t i = 0; i < numberParallelSlices(); ++i) { yup(i) = val; ydown(i) = val; } } -#else - // Delete existing parallel slices. We don't copy parallel slices, so any - // that currently exist will be incorrect. - clearParallelSlices(); -#endif resetRegion(); allocate(); @@ -941,6 +959,7 @@ Options* Field3D::track(const T& change, std::string operation) { return nullptr; } +template Options* Field3D::track(const Field3DParallel&, std::string); template Options* Field3D::track(const Field3D&, std::string); template Options* Field3D::track(const Field2D&, std::string); template Options* Field3D::track(const FieldPerp&, std::string); From 167e39ee6e5eb114cfe7940e7bc8210e05c24746 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 10 Jul 2025 13:59:06 +0200 Subject: [PATCH 073/259] Start using Field3DParallel for derivatives --- include/bout/coordinates.hxx | 14 +++++++------- include/bout/derivs.hxx | 6 +++--- include/bout/index_derivs_interface.hxx | 17 +++++++++++------ src/mesh/coordinates.cxx | 18 +++++++++--------- src/sys/derivs.cxx | 6 +++--- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index d7c80ed8bc..8410b62765 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -159,7 +159,7 @@ public: const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); - Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") const; @@ -171,7 +171,7 @@ public: FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, + Field3D Grad_par(const Field3DParallel& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); /// Advection along magnetic field V*b.Grad(f) @@ -179,7 +179,7 @@ public: CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, + Field3D Vpar_Grad_par(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); @@ -187,14 +187,14 @@ public: FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + Field3D Div_par(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); // Second derivative along magnetic field FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + Field3D Grad2_par2(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code @@ -206,13 +206,13 @@ public: // Full parallel Laplacian operator on scalar field // Laplace_par(f) = Div( b (b dot Grad(f)) ) FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); - Field3D Laplace_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); + Field3D Laplace_par(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT); // Full Laplacian operator on scalar field FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_conditions = "free_o3", const std::string& dfdy_dy_region = ""); - Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + Field3D Laplace(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_conditions = "free_o3", const std::string& dfdy_dy_region = ""); diff --git a/include/bout/derivs.hxx b/include/bout/derivs.hxx index 1c360bb9cd..a8d9279378 100644 --- a/include/bout/derivs.hxx +++ b/include/bout/derivs.hxx @@ -82,7 +82,7 @@ Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); @@ -410,7 +410,7 @@ Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Field3D VDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D VDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); @@ -533,7 +533,7 @@ Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Field3D FDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, +Field3D FDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index bc9a687b34..564c718c93 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -202,17 +202,12 @@ T DDY(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D AUTO_TRACE(); if (f.isFci()) { ASSERT1(f.getDirectionY() == YDirectionType::Standard); - T f_tmp = f; if (!f.hasParallelSlices()) { -#if BOUT_USE_FCI_AUTOMAGIC - f_tmp.calcParallelSlices(); -#else throw BoutException( "parallel slices needed for parallel derivatives. Make sure to communicate and " "apply parallel boundary conditions before calling derivative"); -#endif } - return standardDerivative(f_tmp, outloc, + return standardDerivative(f, outloc, method, region); } else { const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); @@ -369,6 +364,11 @@ T VDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, return are_unaligned ? fromFieldAligned(result, region) : result; } } +inline Field3D VDDY(const Field3D& v, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return VDDY(v, f.asF3d(), outloc, method, region); +} template T FDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, @@ -393,6 +393,11 @@ T FDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, return are_unaligned ? fromFieldAligned(result, region) : result; } } +inline Field3D FDDY(const Field3D& v, const Field3DParallel& f, + CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return FDDY(v, f.asF3d(), outloc, method, region); +} ////////////// Z DERIVATIVE ///////////////// diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index d013634644..dffc5001a4 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1510,8 +1510,8 @@ Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, 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 { +Field3D Coordinates::DDY(const Field3DParallel& f, CELL_LOC outloc, + const std::string& method, const std::string& region) const { return bout::derivatives::index::DDY(f, outloc, method, region) / dy; }; @@ -1543,7 +1543,7 @@ Coordinates::FieldMetric Coordinates::Grad_par(const Field2D& var, return DDY(var) * invSg(); } -Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, +Field3D Coordinates::Grad_par(const Field3DParallel& var, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Grad_par( Field3D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1563,8 +1563,8 @@ Coordinates::FieldMetric Coordinates::Vpar_Grad_par(const Field2D& v, const Fiel return VDDY(v, f) * invSg(); } -Field3D Coordinates::Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, - const std::string& method) { +Field3D Coordinates::Vpar_Grad_par(const Field3D& v, const Field3DParallel& f, + CELL_LOC outloc, const std::string& method) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); return VDDY(v, f, outloc, method) * invSg(); @@ -1585,7 +1585,7 @@ Coordinates::FieldMetric Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, return Bxy * Grad_par(f / Bxy_floc, outloc, method); } -Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, +Field3D Coordinates::Div_par(const Field3DParallel& f, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Div_par( Field3D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1627,7 +1627,7 @@ Coordinates::FieldMetric Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outl return result; } -Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, +Field3D Coordinates::Grad2_par2(const Field3DParallel& f, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Grad2_par2( Field3D )"); if (outloc == CELL_DEFAULT) { @@ -1795,7 +1795,7 @@ Coordinates::FieldMetric Coordinates::Laplace_par(const Field2D& f, CELL_LOC out return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * DDY(f, outloc) / J; } -Field3D Coordinates::Laplace_par(const Field3D& f, CELL_LOC outloc) { +Field3D Coordinates::Laplace_par(const Field3DParallel& f, CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * ::DDY(f, outloc) / J; } @@ -1817,7 +1817,7 @@ Coordinates::FieldMetric Coordinates::Laplace(const Field2D& f, CELL_LOC outloc, return result; } -Field3D Coordinates::Laplace(const Field3D& f, CELL_LOC outloc, +Field3D Coordinates::Laplace(const Field3DParallel& f, CELL_LOC outloc, const std::string& dfdy_boundary_conditions, const std::string& dfdy_dy_region) { TRACE("Coordinates::Laplace( Field3D )"); diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index ee9bcbcc2c..71afe56507 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -70,7 +70,7 @@ Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc, const std::strin ////////////// Y DERIVATIVE ///////////////// -Field3D DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, +Field3D DDY(const Field3DParallel& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::DDY(f, outloc, method, region) / f.getCoordinates(outloc)->dy; @@ -410,7 +410,7 @@ Coordinates::FieldMetric VDDY(const Field2D& v, const Field2D& f, CELL_LOC outlo } // general case -Field3D VDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc, +Field3D VDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::VDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; @@ -471,7 +471,7 @@ Coordinates::FieldMetric FDDY(const Field2D& v, const Field2D& f, CELL_LOC outlo / f.getCoordinates(outloc)->dy; } -Field3D FDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc, +Field3D FDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::FDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; From 59445b6adf6f70816949ca0bbf57a5f211878694 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 16 Jul 2025 14:06:10 +0200 Subject: [PATCH 074/259] Do not use separate derivative store for Field3DParallel --- include/bout/deriv_store.hxx | 9 +++++++++ include/bout/index_derivs.hxx | 2 +- include/bout/index_derivs_interface.hxx | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/bout/deriv_store.hxx b/include/bout/deriv_store.hxx index 6dc44c76ad..e5eacc4bae 100644 --- a/include/bout/deriv_store.hxx +++ b/include/bout/deriv_store.hxx @@ -533,4 +533,13 @@ private: } }; +template +auto& getStore() { + if constexpr(std::is_same::value) { + return DerivativeStore::getInstance(); + } else { + return DerivativeStore::getInstance(); + } +} + #endif diff --git a/include/bout/index_derivs.hxx b/include/bout/index_derivs.hxx index 456f98f8c2..d0f653d7d9 100644 --- a/include/bout/index_derivs.hxx +++ b/include/bout/index_derivs.hxx @@ -149,7 +149,7 @@ struct registerMethod { // removed and we can use nGuard directly in the template statement. const int nGuards = method.meta.nGuards; - auto& derivativeRegister = DerivativeStore::getInstance(); + auto& derivativeRegister = getStore(); switch (method.meta.derivType) { case (DERIV::Standard): diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index 564c718c93..45248beb38 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -150,7 +150,7 @@ T standardDerivative(const T& f, CELL_LOC outloc, const std::string& method, } // Lookup the method - auto derivativeMethod = DerivativeStore::getInstance().getStandardDerivative( + auto derivativeMethod = getStore().getStandardDerivative( method, direction, stagger, derivType); // Create the result field From 1f3521fe4147a148289a446e116791367119324b Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Wed, 16 Jul 2025 12:10:05 +0000 Subject: [PATCH 075/259] Apply clang-format changes --- include/bout/deriv_store.hxx | 2 +- include/bout/field.hxx | 4 +-- include/bout/field3d.hxx | 38 +++++++++++-------------- include/bout/index_derivs_interface.hxx | 4 +-- src/field/field3d.cxx | 4 +-- 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/include/bout/deriv_store.hxx b/include/bout/deriv_store.hxx index e5eacc4bae..4d555e42be 100644 --- a/include/bout/deriv_store.hxx +++ b/include/bout/deriv_store.hxx @@ -535,7 +535,7 @@ private: template auto& getStore() { - if constexpr(std::is_same::value) { + if constexpr (std::is_same::value) { return DerivativeStore::getInstance(); } else { return DerivativeStore::getInstance(); diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 876e76a0b5..53c0a7a050 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -185,8 +185,8 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { template inline T emptyFrom(const T& f) { static_assert(bout::utils::is_Field_v, "emptyFrom only works on Fields"); - return T(f.getMesh(), f.getLocation(), DirectionTypes{f.getDirectionY(), f.getDirectionZ()}, - f.getRegionID()) + return T(f.getMesh(), f.getLocation(), + DirectionTypes{f.getDirectionY(), f.getDirectionZ()}, f.getRegionID()) .allocate(); } diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index a81a79d8a3..2c46670683 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -702,11 +702,10 @@ inline Field3D copy(const Field3D& f) { return result; } -class Field3DParallel: public Field3D -{ - public: - template - Field3DParallel(Types... args): Field3D(args ...) { +class Field3DParallel : public Field3D { +public: + template + Field3DParallel(Types... args) : Field3D(args...) { ensureFieldAligned(); } // Field3DParallel(const Field2D& f) : Field3D(f) { @@ -715,25 +714,21 @@ class Field3DParallel: public Field3D // Explicitly needed, as DirectionTypes is sometimes constructed from a // brace enclosed list Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, - DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Standard}, - std::optional regionID = {}) : - Field3D(localmesh, location_in, directions_in, regionID) { + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}, + std::optional regionID = {}) + : Field3D(localmesh, location_in, directions_in, regionID) { ensureFieldAligned(); } Field3DParallel(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, - DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Standard}) : - Field3D(std::move(data), localmesh, location, directions_in) { + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}) + : Field3D(std::move(data), localmesh, location, directions_in) { ensureFieldAligned(); } Field3DParallel(BoutReal, Mesh*); - Field3D& asF3d() { - return *this; - } - const Field3D& asF3d() const { - return *this; - } + Field3D& asF3d() { return *this; } + const Field3D& asF3d() const { return *this; } Field3DParallel& operator*=(const Field3D&); Field3DParallel& operator/=(const Field3D&); @@ -749,7 +744,7 @@ class Field3DParallel: public Field3D Field3DParallel& operator-=(BoutReal); Field3DParallel& operator=(const Field3D& rhs) { Field3D::operator=(rhs); - ensureFieldAligned(); + ensureFieldAligned(); return *this; } Field3DParallel& operator=(Field3D&& rhs) { @@ -758,11 +753,10 @@ class Field3DParallel: public Field3D return *this; } Field3DParallel& operator=(BoutReal); + private: void ensureFieldAligned(); }; -Field3DParallel Field3D::asF3dwy() { - return Field3DParallel(*this); -} +Field3DParallel Field3D::asF3dwy() { return Field3DParallel(*this); } #endif /* BOUT_FIELD3D_H */ diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index 45248beb38..029a3bd5bc 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -150,8 +150,8 @@ T standardDerivative(const T& f, CELL_LOC outloc, const std::string& method, } // Lookup the method - auto derivativeMethod = getStore().getStandardDerivative( - method, direction, stagger, derivType); + auto derivativeMethod = + getStore().getStandardDerivative(method, direction, stagger, derivType); // Create the result field T result{emptyFrom(f).setLocation(outloc)}; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index db9a054e80..760f3e40d9 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -95,7 +95,8 @@ Field3D::Field3D(const BoutReal val, Mesh* localmesh) : Field3D(localmesh) { *this = val; } -Field3DParallel::Field3DParallel(const BoutReal val, Mesh* localmesh) : Field3D(localmesh) { +Field3DParallel::Field3DParallel(const BoutReal val, Mesh* localmesh) + : Field3D(localmesh) { TRACE("Field3DParallel: Copy constructor from value"); @@ -109,7 +110,6 @@ Field3DParallel::Field3DParallel(const BoutReal val, Mesh* localmesh) : Field3D( } } - Field3D::Field3D(Array data_in, Mesh* localmesh, CELL_LOC datalocation, DirectionTypes directions_in) : Field(localmesh, datalocation, directions_in), data(std::move(data_in)) { From 8c40bad75e0c9d4f463fd425fb21032036d91c3c Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 16 Jul 2025 14:16:24 +0200 Subject: [PATCH 076/259] Do not change non-FCI fields --- src/field/field3d.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 760f3e40d9..436b424bd7 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -980,9 +980,9 @@ Options* Field3D::track(const BoutReal& change, std::string operation) { void Field3DParallel::ensureFieldAligned() { if (isFci()) { ASSERT2(hasParallelSlices()); - } else { - if (getDirectionY() != YDirectionType::Aligned) { - *this = toFieldAligned(*this); - } - } + } // else { + // if (getDirectionY() != YDirectionType::Aligned) { + // *this = toFieldAligned(*this); + // } + // } } From 784d38167a11d9c162b564d1f50f5619b76486ab Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 17 Jul 2025 11:02:46 +0200 Subject: [PATCH 077/259] Add function to header file Otherwise, the Field3DParallel is casted to Field3D and the wrong overloads are used --- include/bout/field3d.hxx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 2c46670683..a5d9eb5b64 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -580,6 +580,26 @@ Field3D operator-(BoutReal lhs, const Field3D& rhs); Field3D operator*(BoutReal lhs, const Field3D& rhs); Field3D operator/(BoutReal lhs, const Field3D& rhs); +Field3DParallel operator+(const Field3D& lhs, const Field3DParallel& rhs); +Field3DParallel operator-(const Field3D& lhs, const Field3DParallel& rhs); +Field3DParallel operator*(const Field3D& lhs, const Field3DParallel& rhs); +Field3DParallel operator/(const Field3D& lhs, const Field3DParallel& rhs); + +Field3DParallel operator+(const Field3DParallel& lhs, const Field3D& rhs); +Field3DParallel operator-(const Field3DParallel& lhs, const Field3D& rhs); +Field3DParallel operator*(const Field3DParallel& lhs, const Field3D& rhs); +Field3DParallel operator/(const Field3DParallel& lhs, const Field3D& rhs); + +Field3DParallel operator+(const Field3DParallel& lhs, const Field3DParallel& rhs); +Field3DParallel operator-(const Field3DParallel& lhs, const Field3DParallel& rhs); +Field3DParallel operator*(const Field3DParallel& lhs, const Field3DParallel& rhs); +Field3DParallel operator/(const Field3DParallel& lhs, const Field3DParallel& rhs); + +Field3DParallel operator+(const BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator-(const BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator*(const BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator/(const BoutReal lhs, const Field3DParallel& rhs); + /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. From b880846e31f5a264ddbcce92fe59136db4dc53de Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 17 Jul 2025 11:03:10 +0200 Subject: [PATCH 078/259] Ensure emptyFrom works --- include/bout/field3d.hxx | 1 + 1 file changed, 1 insertion(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index a5d9eb5b64..e6177d0846 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -738,6 +738,7 @@ public: ZDirectionType::Standard}, std::optional regionID = {}) : Field3D(localmesh, location_in, directions_in, regionID) { + splitParallelSlices(); ensureFieldAligned(); } Field3DParallel(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, From 8619876339753cc0c5f8c1b4810adb274a57fc26 Mon Sep 17 00:00:00 2001 From: malamast Date: Thu, 17 Jul 2025 09:56:23 -0700 Subject: [PATCH 079/259] snes: I addied some changes made on my remote branch by clang-tidy. I added the line MatSetOption(Jfd,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE); after the creation of Jfd to tell petsc to keep the pattern of the non zero elements in memory. Also, I changed the default coloring type to greedy which is more suited for large parallel problems. --- src/solver/impls/snes/snes.cxx | 82 +++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index e14d3d4569..4f6c11fb42 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -119,8 +119,8 @@ SNESSolver::SNESSolver(Options* opts) .doc("Maximum number of nonlinear iterations per SNES solve") .withDefault(50)), maxf((*options)["maxf"] - .doc("Maximum number of function evaluations per SNES solve") - .withDefault(10000)), + .doc("Maximum number of function evaluations per SNES solve") + .withDefault(10000)), lower_its((*options)["lower_its"] .doc("Iterations below which the next timestep is increased") .withDefault(static_cast(maxits * 0.5))), @@ -128,22 +128,25 @@ SNESSolver::SNESSolver(Options* opts) .doc("Iterations above which the next timestep is reduced") .withDefault(static_cast(maxits * 0.8))), timestep_factor_on_failure((*options)["timestep_factor_on_failure"] - .doc("Multiply timestep on convergence failure") - .withDefault(0.5)), - timestep_factor_on_upper_its( - (*options)["timestep_factor_on_upper_its"] - .doc("Multiply timestep if iterations exceed upper_its") - .withDefault(0.9)), - timestep_factor_on_lower_its( - (*options)["timestep_factor_on_lower_its"] - .doc("Multiply timestep if iterations are below lower_its") - .withDefault(1.4)), + .doc("Multiply timestep on convergence failure") + .withDefault(0.5)), + timestep_factor_on_upper_its((*options)["timestep_factor_on_upper_its"] + .doc("Multiply timestep if iterations exceed upper_its") + .withDefault(0.9)), + timestep_factor_on_lower_its((*options)["timestep_factor_on_lower_its"] + .doc("Multiply timestep if iterations are below lower_its") + .withDefault(1.4)), pidController( (*options)["pidController"].doc("Use PID controller?").withDefault(false)), - target_its((*options)["target_its"].doc("Target snes iterations").withDefault(7)), - kP((*options)["kP"].doc("Proportional PID parameter").withDefault(0.7)), - kI((*options)["kI"].doc("Integral PID parameter").withDefault(0.3)), - kD((*options)["kD"].doc("Derivative PID parameter").withDefault(0.2)), + target_its((*options)["target_its"] + .doc("Target snes iterations") + .withDefault(static_cast(7))), + kP((*options)["kP"].doc("Proportional PID parameter") + .withDefault(0.7)), + kI((*options)["kI"].doc("Integral PID parameter") + .withDefault(0.3)), + kD((*options)["kD"].doc("Derivative PID parameter") + .withDefault(0.2)), diagnose( (*options)["diagnose"].doc("Print additional diagnostics").withDefault(false)), diagnose_failures((*options)["diagnose_failures"] @@ -351,6 +354,7 @@ int SNESSolver::init() { // Set size of Matrix on each processor to nlocal x nlocal MatCreate(BoutComm::get(), &Jfd); + MatSetOption(Jfd,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE); MatSetSizes(Jfd, nlocal, nlocal, PETSC_DETERMINE, PETSC_DETERMINE); MatSetFromOptions(Jfd); // Determine which row/columns of the matrix are locally owned @@ -643,7 +647,7 @@ int SNESSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - if (pidController) { + if (pidController){ nl_its_prev = target_its; nl_its_prev2 = target_its; SNESSetLagJacobianPersists(snes, PETSC_FALSE); @@ -861,7 +865,8 @@ int SNESSolver::run() { VecAXPBY(snes_x, -beta, (1. + beta), x1); } - if (pidController) { + + if (pidController){ SNESSetLagJacobian(snes, lag_jacobian); } @@ -1057,7 +1062,7 @@ int SNESSolver::run() { if (looping) { - if (pidController) { + if (pidController){ // Changing the timestep. // Note: The preconditioner depends on the timestep, // so we recalculate the jacobian and the preconditioner @@ -1072,8 +1077,9 @@ int SNESSolver::run() { SNESSetLagJacobian(snes, 1); } - } else { + } else { + // Consider changing the timestep. // Note: The preconditioner depends on the timestep, // so if it is not recalculated the it will be less @@ -1083,7 +1089,9 @@ int SNESSolver::run() { // Increase timestep slightly timestep *= timestep_factor_on_lower_its; - timestep = std::min(timestep, max_timestep); + if (timestep > max_timestep) { + timestep = max_timestep; + } // Note: Setting the SNESJacobianFn to NULL retains // previously set evaluation function. @@ -1111,7 +1119,9 @@ int SNESSolver::run() { SNESSetLagJacobian(snes, 1); } } + } + } snes_failures = 0; } while (looping); @@ -1400,7 +1410,9 @@ void SNESSolver::updateColoring() { // Re-calculate the coloring MatColoring coloring = NULL; MatColoringCreate(Jfd, &coloring); - MatColoringSetType(coloring, MATCOLORINGSL); + // MatColoringSetType(coloring, MATCOLORINGSL); // Serial algorithm. Better for smale-to-medium size problems. + MatColoringSetType(coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs + // MatColoringSetType(coloring, MATCOLORINGJP); // This didn't work MatColoringSetFromOptions(coloring); // Calculate new index sets @@ -1426,25 +1438,33 @@ void SNESSolver::updateColoring() { } } + BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ - const BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); - const BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) - / double(nl_its) / double(nl_its_prev2), - kD); + BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); + BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); + BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) / double(nl_its_prev2), kD); - // clamp growth factor to avoid huge changes - const BoutReal fac = std::clamp(facP * facI * facD, 0.2, 5.0); + // clamp groth factor to avoid huge changes + BoutReal fac = facP * facI * facD; + if (fac < 0.2) + fac = 0.2; + else if (fac > 5.0) + fac = 5.0; /* ---------- update timestep and history ---------- */ - const BoutReal dt_new = std::min(timestep * fac, max_timestep); + BoutReal dt_new = timestep * fac; + + if (dt_new > max_timestep) { + dt_new = max_timestep; + } nl_its_prev2 = nl_its_prev; - nl_its_prev = nl_its; + nl_its_prev = static_cast(nl_its); return dt_new; } + #endif // BOUT_HAS_PETSC From c20863993e7e87565cecef5a16eb18a97ab9518a Mon Sep 17 00:00:00 2001 From: malamast <42969991+malamast@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:59:07 +0000 Subject: [PATCH 080/259] Apply clang-format changes --- src/solver/impls/snes/snes.cxx | 62 ++++++++++++++++------------------ 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 4f6c11fb42..0b57a52d39 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -119,8 +119,8 @@ SNESSolver::SNESSolver(Options* opts) .doc("Maximum number of nonlinear iterations per SNES solve") .withDefault(50)), maxf((*options)["maxf"] - .doc("Maximum number of function evaluations per SNES solve") - .withDefault(10000)), + .doc("Maximum number of function evaluations per SNES solve") + .withDefault(10000)), lower_its((*options)["lower_its"] .doc("Iterations below which the next timestep is increased") .withDefault(static_cast(maxits * 0.5))), @@ -128,25 +128,24 @@ SNESSolver::SNESSolver(Options* opts) .doc("Iterations above which the next timestep is reduced") .withDefault(static_cast(maxits * 0.8))), timestep_factor_on_failure((*options)["timestep_factor_on_failure"] - .doc("Multiply timestep on convergence failure") - .withDefault(0.5)), - timestep_factor_on_upper_its((*options)["timestep_factor_on_upper_its"] - .doc("Multiply timestep if iterations exceed upper_its") - .withDefault(0.9)), - timestep_factor_on_lower_its((*options)["timestep_factor_on_lower_its"] - .doc("Multiply timestep if iterations are below lower_its") - .withDefault(1.4)), + .doc("Multiply timestep on convergence failure") + .withDefault(0.5)), + timestep_factor_on_upper_its( + (*options)["timestep_factor_on_upper_its"] + .doc("Multiply timestep if iterations exceed upper_its") + .withDefault(0.9)), + timestep_factor_on_lower_its( + (*options)["timestep_factor_on_lower_its"] + .doc("Multiply timestep if iterations are below lower_its") + .withDefault(1.4)), pidController( (*options)["pidController"].doc("Use PID controller?").withDefault(false)), target_its((*options)["target_its"] - .doc("Target snes iterations") - .withDefault(static_cast(7))), - kP((*options)["kP"].doc("Proportional PID parameter") - .withDefault(0.7)), - kI((*options)["kI"].doc("Integral PID parameter") - .withDefault(0.3)), - kD((*options)["kD"].doc("Derivative PID parameter") - .withDefault(0.2)), + .doc("Target snes iterations") + .withDefault(static_cast(7))), + kP((*options)["kP"].doc("Proportional PID parameter").withDefault(0.7)), + kI((*options)["kI"].doc("Integral PID parameter").withDefault(0.3)), + kD((*options)["kD"].doc("Derivative PID parameter").withDefault(0.2)), diagnose( (*options)["diagnose"].doc("Print additional diagnostics").withDefault(false)), diagnose_failures((*options)["diagnose_failures"] @@ -354,7 +353,7 @@ int SNESSolver::init() { // Set size of Matrix on each processor to nlocal x nlocal MatCreate(BoutComm::get(), &Jfd); - MatSetOption(Jfd,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE); + MatSetOption(Jfd, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE); MatSetSizes(Jfd, nlocal, nlocal, PETSC_DETERMINE, PETSC_DETERMINE); MatSetFromOptions(Jfd); // Determine which row/columns of the matrix are locally owned @@ -647,7 +646,7 @@ int SNESSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - if (pidController){ + if (pidController) { nl_its_prev = target_its; nl_its_prev2 = target_its; SNESSetLagJacobianPersists(snes, PETSC_FALSE); @@ -865,8 +864,7 @@ int SNESSolver::run() { VecAXPBY(snes_x, -beta, (1. + beta), x1); } - - if (pidController){ + if (pidController) { SNESSetLagJacobian(snes, lag_jacobian); } @@ -1062,7 +1060,7 @@ int SNESSolver::run() { if (looping) { - if (pidController){ + if (pidController) { // Changing the timestep. // Note: The preconditioner depends on the timestep, // so we recalculate the jacobian and the preconditioner @@ -1077,9 +1075,8 @@ int SNESSolver::run() { SNESSetLagJacobian(snes, 1); } - } else { - + // Consider changing the timestep. // Note: The preconditioner depends on the timestep, // so if it is not recalculated the it will be less @@ -1119,9 +1116,7 @@ int SNESSolver::run() { SNESSetLagJacobian(snes, 1); } } - } - } snes_failures = 0; } while (looping); @@ -1411,7 +1406,8 @@ void SNESSolver::updateColoring() { MatColoring coloring = NULL; MatColoringCreate(Jfd, &coloring); // MatColoringSetType(coloring, MATCOLORINGSL); // Serial algorithm. Better for smale-to-medium size problems. - MatColoringSetType(coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs + MatColoringSetType( + coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs // MatColoringSetType(coloring, MATCOLORINGJP); // This didn't work MatColoringSetFromOptions(coloring); @@ -1438,13 +1434,14 @@ void SNESSolver::updateColoring() { } } - BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ - BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); + BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) / double(nl_its_prev2), kD); + BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) + / double(nl_its_prev2), + kD); // clamp groth factor to avoid huge changes BoutReal fac = facP * facI * facD; @@ -1461,10 +1458,9 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { } nl_its_prev2 = nl_its_prev; - nl_its_prev = static_cast(nl_its); + nl_its_prev = static_cast(nl_its); return dt_new; } - #endif // BOUT_HAS_PETSC From 844f2d4bbb59f8c7e7d81a0cd8437b8248d2b45b Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 17 Jul 2025 23:51:26 +0200 Subject: [PATCH 081/259] Use f3dwy to preserve parallel fields The communication was a no-op, as that did never calculate the parallel fields. --- src/mesh/coordinates.cxx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index dffc5001a4..ce0225341f 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1039,15 +1039,9 @@ int Coordinates::geometry(bool recalculate_staggered, G3_23 = 0.5 * g13 * (DDZ(g_12) + DDY(g_13) - DDX(g_23)) + 0.5 * g23 * DDZ(g_22) + 0.5 * g33 * DDY(g_33); - auto tmp = J * g12; - communicate(tmp); - G1 = (DDX(J * g11) + DDY(tmp) + DDZ(J * g13)) / J; - tmp = J * g22; - communicate(tmp); - G2 = (DDX(J * g12) + DDY(tmp) + DDZ(J * g23)) / J; - tmp = J * g23; - communicate(tmp); - G3 = (DDX(J * g13) + DDY(tmp) + DDZ(J * g33)) / J; + G1 = (DDX(J * g11) + DDY(J.asF3dwy() * g12) + DDZ(J * g13)) / J; + G2 = (DDX(J * g12) + DDY(J.asF3dwy() * g22) + DDZ(J * g23)) / J; + G3 = (DDX(J * g13) + DDY(J.asF3dwy() * g23) + DDZ(J * g33)) / J; // Communicate christoffel symbol terms output_progress.write("\tCommunicating connection terms\n"); From 25fd12fff5b3733dec4687dac19293682c9a5132 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 17 Jul 2025 23:52:30 +0200 Subject: [PATCH 082/259] Also load dy It is needed for e.g. calculating d1_dy --- src/mesh/parallel/fci.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 580897f47a..0a231de6cd 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -122,6 +122,8 @@ void load_parallel_metric_components([[maybe_unused]] Coordinates* coords, LOAD_PAR(g_13, false); LOAD_PAR(g_23, false); + LOAD_PAR(dy, false); + if (not LOAD_PAR(J, true)) { auto g = coords->g11.ynext(offset) * coords->g22.ynext(offset) * coords->g33.ynext(offset) From 5e1a3dfa7ca61468f45abb2d5bef5681c569419f Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 17 Jul 2025 23:53:10 +0200 Subject: [PATCH 083/259] Preserve parallel fields for d1_dy calculation --- src/mesh/coordinates.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index ce0225341f..8e67b0ef74 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1119,7 +1119,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2y, "d2y" + suffix, 0.0, false, location)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = DDY(1. / dy); // d/di(1/dy) + d1_dy = DDY(1. / dy.asF3dwy()); // d/di(1/dy) communicate(d1_dy); d1_dy = From e034dddf35be6b48ace9ca03a8b750f62ede0ee6 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 17 Jul 2025 23:54:03 +0200 Subject: [PATCH 084/259] Add overloads for DD?(Field3DParallel) They should return Field3D, not Field3DParallel --- include/bout/index_derivs_interface.hxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index 029a3bd5bc..bf4597e88b 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -177,6 +177,10 @@ T DDX(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D AUTO_TRACE(); return standardDerivative(f, outloc, method, region); } +inline Field3D DDX(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDX(f.asF3d(), outloc, method, region); +} template T D2DX2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -217,6 +221,10 @@ T DDY(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D return is_unaligned ? fromFieldAligned(result, region) : result; } } +inline Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDY(f.asF3d(), outloc, method, region); +} template T D2DY2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -259,6 +267,10 @@ T DDZ(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D AUTO_TRACE(); return standardDerivative(f, outloc, method, region); } +inline Field3D DDZ(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { + return DDZ(f.asF3d(), outloc, method, region); +} template T D2DZ2(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", From cdcb380685c9b80a0d566fbdb6e22fef539d4990 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 17 Jul 2025 21:54:55 +0000 Subject: [PATCH 085/259] Apply clang-format changes --- include/bout/index_derivs_interface.hxx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index bf4597e88b..ed3d749776 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -177,8 +177,9 @@ T DDX(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D AUTO_TRACE(); return standardDerivative(f, outloc, method, region); } -inline Field3D DDX(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY") { +inline Field3D DDX(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { return DDX(f.asF3d(), outloc, method, region); } @@ -221,8 +222,9 @@ T DDY(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D return is_unaligned ? fromFieldAligned(result, region) : result; } } -inline Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY") { +inline Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { return DDY(f.asF3d(), outloc, method, region); } @@ -267,8 +269,9 @@ T DDZ(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D AUTO_TRACE(); return standardDerivative(f, outloc, method, region); } -inline Field3D DDZ(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY") { +inline Field3D DDZ(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY") { return DDZ(f.asF3d(), outloc, method, region); } From da7865d76cea7c7158455b4f68754eca43118155 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 18 Jul 2025 07:24:03 +0200 Subject: [PATCH 086/259] add asF3dwy() stub to Field2D --- include/bout/field2d.hxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/bout/field2d.hxx b/include/bout/field2d.hxx index 5eab330e8e..76f1b31566 100644 --- a/include/bout/field2d.hxx +++ b/include/bout/field2d.hxx @@ -281,6 +281,10 @@ public: int size() const override { return nx * ny; } + Field2D& asF3dwy() { + return *this; + } + private: /// Internal data array. Handles allocation/freeing of memory Array data; From 6a75dfc65a7e01747a4c003e419acb085715f59b Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Fri, 18 Jul 2025 05:30:17 +0000 Subject: [PATCH 087/259] Apply clang-format changes --- include/bout/field2d.hxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/bout/field2d.hxx b/include/bout/field2d.hxx index 76f1b31566..fe7556fd17 100644 --- a/include/bout/field2d.hxx +++ b/include/bout/field2d.hxx @@ -281,9 +281,7 @@ public: int size() const override { return nx * ny; } - Field2D& asF3dwy() { - return *this; - } + Field2D& asF3dwy() { return *this; } private: /// Internal data array. Handles allocation/freeing of memory From b593a19fc834ccfd9717387f17397c4a54be4719 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 18 Jul 2025 09:18:58 +0100 Subject: [PATCH 088/259] Fix more clang-tidy warnings --- examples/laplacexy/laplace_perp/test.cxx | 4 +++- tests/MMS/laplace/laplace.cxx | 18 +++++++++--------- tests/MMS/spatial/d2dx2/test_d2dx2.cxx | 7 +++++-- tests/MMS/spatial/d2dz2/test_d2dz2.cxx | 8 ++++++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index 291faffabc..75577bb8b7 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -1,4 +1,5 @@ #include +#include #include #include @@ -51,7 +52,8 @@ int main(int argc, char** argv) { /////////////////////////////////////// // Read an analytic input - Field2D input = FieldFactory::get()->create2D("input_field", Options::getRoot(), mesh); + const Field2D input = + FieldFactory::get()->create2D("input_field", Options::getRoot(), mesh); // Create a LaplaceXY solver LaplaceXY laplacexy{mesh}; diff --git a/tests/MMS/laplace/laplace.cxx b/tests/MMS/laplace/laplace.cxx index 15fc849d8f..fbcdee355c 100644 --- a/tests/MMS/laplace/laplace.cxx +++ b/tests/MMS/laplace/laplace.cxx @@ -1,8 +1,11 @@ #include - #include +#include #include #include +#include + +#include using bout::globals::mesh; using namespace std::string_literals; @@ -34,16 +37,13 @@ int main(int argc, char** argv) { FieldFactory fact(mesh); const auto input_name = "input_field"s; - std::shared_ptr gen = fact.parse(input_name); + const auto gen = fact.parse(input_name); output.write("GEN = {}\n", gen->str()); - Field3D input = fact.create3D(input_name); - - Field3D result = lap->solve(input); - - Field3D solution = fact.create3D("solution"); - - Field3D error = result - solution; + const Field3D input = fact.create3D(input_name); + const Field3D result = lap->solve(input); + const Field3D solution = fact.create3D("solution"); + const Field3D error = result - solution; Options dump; dump["input"] = input; diff --git a/tests/MMS/spatial/d2dx2/test_d2dx2.cxx b/tests/MMS/spatial/d2dx2/test_d2dx2.cxx index 228dca4b2a..7f7127cea9 100644 --- a/tests/MMS/spatial/d2dx2/test_d2dx2.cxx +++ b/tests/MMS/spatial/d2dx2/test_d2dx2.cxx @@ -4,7 +4,9 @@ #include #include +#include #include +#include using bout::globals::mesh; @@ -13,7 +15,8 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); Field3D input = FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh); - Field3D solution = FieldFactory::get()->create3D("solution", Options::getRoot(), mesh); + const Field3D solution = + FieldFactory::get()->create3D("solution", Options::getRoot(), mesh); // At this point the boundary cells are set to the analytic solution input.setBoundary("bndry"); @@ -21,7 +24,7 @@ int main(int argc, char** argv) { // Boundaries of input now set using extrapolation around mid-point boundary - Field3D result = D2DX2(input); + const Field3D result = D2DX2(input); // At this point result is not set in the boundary cells Options dump; diff --git a/tests/MMS/spatial/d2dz2/test_d2dz2.cxx b/tests/MMS/spatial/d2dz2/test_d2dz2.cxx index 9dccb6a992..68a12b062f 100644 --- a/tests/MMS/spatial/d2dz2/test_d2dz2.cxx +++ b/tests/MMS/spatial/d2dz2/test_d2dz2.cxx @@ -4,7 +4,9 @@ #include #include +#include #include +#include using bout::globals::mesh; @@ -12,8 +14,10 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); - Field3D input = FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh); - Field3D solution = FieldFactory::get()->create3D("solution", Options::getRoot(), mesh); + const Field3D input = + FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh); + const Field3D solution = + FieldFactory::get()->create3D("solution", Options::getRoot(), mesh); Field3D result = D2DZ2(input); From 79af980ebeb5b193f2cae9492df5fec29682e3c1 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 11 Mar 2025 16:47:24 +0100 Subject: [PATCH 089/259] Loosen tolerance for hypre3d test It seems something changed, that make hypre be less precise --- tests/integrated/test-laplace-hypre3d/runtest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-laplace-hypre3d/runtest b/tests/integrated/test-laplace-hypre3d/runtest index b50c5993b7..12ae54d9b7 100755 --- a/tests/integrated/test-laplace-hypre3d/runtest +++ b/tests/integrated/test-laplace-hypre3d/runtest @@ -13,7 +13,7 @@ test_directories = [ ("data_circular_core-sol", 1), ] -tolerance = 1.0e-6 +tolerance = 1.0e-4 build_and_log("Laplace 3D with Hypre") From e8277e4771f55013632bab87f5bd7a2a7678592a Mon Sep 17 00:00:00 2001 From: ZedThree <1486942+ZedThree@users.noreply.github.com> Date: Fri, 18 Jul 2025 08:24:40 +0000 Subject: [PATCH 090/259] Apply clang-format changes --- src/bout++.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bout++.cxx b/src/bout++.cxx index 7f23cf5f91..4e9e37fe8d 100644 --- a/src/bout++.cxx +++ b/src/bout++.cxx @@ -84,7 +84,7 @@ const char DEFAULT_DIR[] = "data"; // Define S_ISDIR if not defined by system headers (that is, MSVC) // Taken from https://github.com/curl/curl/blob/e59540139a398dc70fde6aec487b19c5085105af/lib/curl_setup.h#L748-L751 #if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) -#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifdef _MSC_VER From 7c586e35f822d7c68018dfe9689a39e5ea144712 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 20:22:11 +0000 Subject: [PATCH 091/259] Bump ZedThree/clang-tidy-review from 0.20.1 to 0.21.0 Bumps [ZedThree/clang-tidy-review](https://github.com/zedthree/clang-tidy-review) from 0.20.1 to 0.21.0. - [Release notes](https://github.com/zedthree/clang-tidy-review/releases) - [Changelog](https://github.com/ZedThree/clang-tidy-review/blob/master/CHANGELOG.md) - [Commits](https://github.com/zedthree/clang-tidy-review/compare/v0.20.1...v0.21.0) --- updated-dependencies: - dependency-name: ZedThree/clang-tidy-review dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/clang-tidy-review.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 1e2f88d208..1a9a0ea079 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.20.1 + uses: ZedThree/clang-tidy-review@v0.21.0 id: review with: build_dir: build @@ -47,4 +47,4 @@ jobs: -DBOUT_UPDATE_GIT_SUBMODULE=OFF - name: Upload clang-tidy fixes - uses: ZedThree/clang-tidy-review/upload@v0.20.1 + uses: ZedThree/clang-tidy-review/upload@v0.21.0 From 3e9bdfd8587d76355064f46c62ef2a0f389971c3 Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 18 Jul 2025 10:56:38 +0200 Subject: [PATCH 092/259] Add some documentation --- include/bout/field3d.hxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index e6177d0846..c4807099da 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -722,15 +722,16 @@ inline Field3D copy(const Field3D& f) { return result; } +/// Field3DParallel is intended to behave like Field3D, but preserve parallel +/// Fields. +/// Operations on Field3D, like multiplication, exp and floor only work on the +/// "main" field, Field3DParallel will retain the parallel slices. class Field3DParallel : public Field3D { public: template Field3DParallel(Types... args) : Field3D(args...) { ensureFieldAligned(); } - // Field3DParallel(const Field2D& f) : Field3D(f) { - // ensureFieldAligned(); - // } // Explicitly needed, as DirectionTypes is sometimes constructed from a // brace enclosed list Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, From 24e96d0c4b385e1168aa40ca89b5e64b53a5a12a Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 18 Jul 2025 10:58:02 +0200 Subject: [PATCH 093/259] Be more explicit in the naming --- include/bout/field2d.hxx | 2 +- include/bout/field3d.hxx | 8 ++++---- include/bout/index_derivs_interface.hxx | 10 +++++----- src/mesh/coordinates.cxx | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/bout/field2d.hxx b/include/bout/field2d.hxx index fe7556fd17..e510194c42 100644 --- a/include/bout/field2d.hxx +++ b/include/bout/field2d.hxx @@ -281,7 +281,7 @@ public: int size() const override { return nx * ny; } - Field2D& asF3dwy() { return *this; } + Field2D& asField3DParallel() { return *this; } private: /// Internal data array. Handles allocation/freeing of memory diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index c4807099da..cc6b77c508 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -526,7 +526,7 @@ public: bool allowCalcParallelSlices{true}; - inline Field3DParallel asF3dwy(); + inline Field3DParallel asField3DParallel(); protected: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null @@ -749,8 +749,8 @@ public: ensureFieldAligned(); } Field3DParallel(BoutReal, Mesh*); - Field3D& asF3d() { return *this; } - const Field3D& asF3d() const { return *this; } + Field3D& asField3D() { return *this; } + const Field3D& asField3D() const { return *this; } Field3DParallel& operator*=(const Field3D&); Field3DParallel& operator/=(const Field3D&); @@ -780,5 +780,5 @@ private: void ensureFieldAligned(); }; -Field3DParallel Field3D::asF3dwy() { return Field3DParallel(*this); } +Field3DParallel Field3D::asField3DParallel() { return Field3DParallel(*this); } #endif /* BOUT_FIELD3D_H */ diff --git a/include/bout/index_derivs_interface.hxx b/include/bout/index_derivs_interface.hxx index ed3d749776..82489d3279 100644 --- a/include/bout/index_derivs_interface.hxx +++ b/include/bout/index_derivs_interface.hxx @@ -180,7 +180,7 @@ T DDX(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D inline Field3D DDX(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - return DDX(f.asF3d(), outloc, method, region); + return DDX(f.asField3D(), outloc, method, region); } template @@ -225,7 +225,7 @@ T DDY(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D inline Field3D DDY(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - return DDY(f.asF3d(), outloc, method, region); + return DDY(f.asField3D(), outloc, method, region); } template @@ -272,7 +272,7 @@ T DDZ(const T& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "D inline Field3D DDZ(const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - return DDZ(f.asF3d(), outloc, method, region); + return DDZ(f.asField3D(), outloc, method, region); } template @@ -382,7 +382,7 @@ T VDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, inline Field3D VDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - return VDDY(v, f.asF3d(), outloc, method, region); + return VDDY(v, f.asField3D(), outloc, method, region); } template @@ -411,7 +411,7 @@ T FDDY(const T& vel, const T& f, CELL_LOC outloc = CELL_DEFAULT, inline Field3D FDDY(const Field3D& v, const Field3DParallel& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY") { - return FDDY(v, f.asF3d(), outloc, method, region); + return FDDY(v, f.asField3D(), outloc, method, region); } ////////////// Z DERIVATIVE ///////////////// diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 8e67b0ef74..8da9857d92 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1039,9 +1039,9 @@ int Coordinates::geometry(bool recalculate_staggered, G3_23 = 0.5 * g13 * (DDZ(g_12) + DDY(g_13) - DDX(g_23)) + 0.5 * g23 * DDZ(g_22) + 0.5 * g33 * DDY(g_33); - G1 = (DDX(J * g11) + DDY(J.asF3dwy() * g12) + DDZ(J * g13)) / J; - G2 = (DDX(J * g12) + DDY(J.asF3dwy() * g22) + DDZ(J * g23)) / J; - G3 = (DDX(J * g13) + DDY(J.asF3dwy() * g23) + DDZ(J * g33)) / J; + G1 = (DDX(J * g11) + DDY(J.asField3DParallel() * g12) + DDZ(J * g13)) / J; + G2 = (DDX(J * g12) + DDY(J.asField3DParallel() * g22) + DDZ(J * g23)) / J; + G3 = (DDX(J * g13) + DDY(J.asField3DParallel() * g23) + DDZ(J * g33)) / J; // Communicate christoffel symbol terms output_progress.write("\tCommunicating connection terms\n"); @@ -1119,7 +1119,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2y, "d2y" + suffix, 0.0, false, location)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = DDY(1. / dy.asF3dwy()); // d/di(1/dy) + d1_dy = DDY(1. / dy.asField3DParallel()); // d/di(1/dy) communicate(d1_dy); d1_dy = From 196138a223ae0725a33a18167ce5737cad94dd6d Mon Sep 17 00:00:00 2001 From: David Bold Date: Fri, 18 Jul 2025 12:43:16 +0200 Subject: [PATCH 094/259] Apply clang-tidy fix --- src/field/generated_fieldops.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 7b742b7e43..53db167571 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -5,6 +5,7 @@ #include #include #include +#include // Provide the C++ wrapper for multiplication of Field3D and Field3D Field3D operator*(const Field3D& lhs, const Field3D& rhs) { From d816d7819e128925fe806052aeebb5ecdac1eaf2 Mon Sep 17 00:00:00 2001 From: malamast Date: Fri, 18 Jul 2025 10:23:33 -0700 Subject: [PATCH 095/259] SNES: changes the pidController flag to pid_controller to match the variable naming convention. --- src/solver/impls/snes/snes.cxx | 10 +++++----- src/solver/impls/snes/snes.hxx | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 4f6c11fb42..8c10052e33 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -136,8 +136,8 @@ SNESSolver::SNESSolver(Options* opts) timestep_factor_on_lower_its((*options)["timestep_factor_on_lower_its"] .doc("Multiply timestep if iterations are below lower_its") .withDefault(1.4)), - pidController( - (*options)["pidController"].doc("Use PID controller?").withDefault(false)), + pid_controller( + (*options)["pid_controller"].doc("Use PID controller?").withDefault(false)), target_its((*options)["target_its"] .doc("Target snes iterations") .withDefault(static_cast(7))), @@ -647,7 +647,7 @@ int SNESSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - if (pidController){ + if (pid_controller){ nl_its_prev = target_its; nl_its_prev2 = target_its; SNESSetLagJacobianPersists(snes, PETSC_FALSE); @@ -866,7 +866,7 @@ int SNESSolver::run() { } - if (pidController){ + if (pid_controller){ SNESSetLagJacobian(snes, lag_jacobian); } @@ -1062,7 +1062,7 @@ int SNESSolver::run() { if (looping) { - if (pidController){ + if (pid_controller){ // Changing the timestep. // Note: The preconditioner depends on the timestep, // so we recalculate the jacobian and the preconditioner diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index 8a0b5bcecb..e31ca44625 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -108,7 +108,7 @@ private: BoutReal timestep_factor_on_lower_its; ///< PID controller parameters - bool pidController; ///< Use PID controller? + bool pid_controller; ///< Use PID controller? int target_its; ///< Target number of nonlinear iterations for the PID controller. ///< Use with caution! Not tested values. BoutReal kP; ///< (0.6 - 0.8) Proportional parameter (main response to current step) From a7acfc3e97b47250e5a58f69a1a0806543e31bd5 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 10:54:45 +0200 Subject: [PATCH 096/259] Disable hypre3d test --- tests/integrated/test-laplace-hypre3d/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-laplace-hypre3d/CMakeLists.txt b/tests/integrated/test-laplace-hypre3d/CMakeLists.txt index 2645c18c67..b09b416feb 100644 --- a/tests/integrated/test-laplace-hypre3d/CMakeLists.txt +++ b/tests/integrated/test-laplace-hypre3d/CMakeLists.txt @@ -7,4 +7,5 @@ bout_add_integrated_test(test-laplace-hypre3d data_slab_sol/BOUT.inp USE_RUNTEST REQUIRES BOUT_HAS_HYPRE + REQUIRES BOUT_RUN_ALL_TESTS ) From b8da0fb31e06e532bf40d4d5734a5fdcd63601a1 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:01:45 +0200 Subject: [PATCH 097/259] do not use const for BoutReal in signature --- include/bout/field3d.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index cc6b77c508..82c0dd9d6f 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -595,10 +595,10 @@ Field3DParallel operator-(const Field3DParallel& lhs, const Field3DParallel& rhs Field3DParallel operator*(const Field3DParallel& lhs, const Field3DParallel& rhs); Field3DParallel operator/(const Field3DParallel& lhs, const Field3DParallel& rhs); -Field3DParallel operator+(const BoutReal lhs, const Field3DParallel& rhs); -Field3DParallel operator-(const BoutReal lhs, const Field3DParallel& rhs); -Field3DParallel operator*(const BoutReal lhs, const Field3DParallel& rhs); -Field3DParallel operator/(const BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator+(BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator-(BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator*(BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator/(BoutReal lhs, const Field3DParallel& rhs); /*! * Unary minus. Returns the negative of given field, From f32693df1741178d0fd671036f73be23d965245c Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:12:18 +0200 Subject: [PATCH 098/259] Add Field3DParallel + Field2D fieldops This is needed for 2D metrics, and in this case we probably want to clear the parallel fields. --- include/bout/field3d.hxx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 82c0dd9d6f..0e99ede05f 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -600,6 +600,32 @@ Field3DParallel operator-(BoutReal lhs, const Field3DParallel& rhs); Field3DParallel operator*(BoutReal lhs, const Field3DParallel& rhs); Field3DParallel operator/(BoutReal lhs, const Field3DParallel& rhs); +Field3D operator+(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} +Field3D operator-(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} +Field3D operator*(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} +Field3D operator/(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} + +Field3D operator+(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() + rhs; +} +Field3D operator-(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() - rhs; +} +Field3D operator*(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() * rhs; +} +Field3D operator/(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() / rhs; +} + /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. From 0ecf55cb8cd71d4356029552e6079316f0ee0a2d Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:14:10 +0200 Subject: [PATCH 099/259] Move function definition after class definition --- include/bout/field3d.hxx | 54 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 0e99ede05f..c46f68d010 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -600,32 +600,6 @@ Field3DParallel operator-(BoutReal lhs, const Field3DParallel& rhs); Field3DParallel operator*(BoutReal lhs, const Field3DParallel& rhs); Field3DParallel operator/(BoutReal lhs, const Field3DParallel& rhs); -Field3D operator+(const Field2D& lhs, const Field3DParallel& rhs) { - return lhs + rhs.asField3D(); -} -Field3D operator-(const Field2D& lhs, const Field3DParallel& rhs) { - return lhs + rhs.asField3D(); -} -Field3D operator*(const Field2D& lhs, const Field3DParallel& rhs) { - return lhs + rhs.asField3D(); -} -Field3D operator/(const Field2D& lhs, const Field3DParallel& rhs) { - return lhs + rhs.asField3D(); -} - -Field3D operator+(const Field3DParallel& lhs, const Field2D& rhs) { - return lhs.asField3D() + rhs; -} -Field3D operator-(const Field3DParallel& lhs, const Field2D& rhs) { - return lhs.asField3D() - rhs; -} -Field3D operator*(const Field3DParallel& lhs, const Field2D& rhs) { - return lhs.asField3D() * rhs; -} -Field3D operator/(const Field3DParallel& lhs, const Field2D& rhs) { - return lhs.asField3D() / rhs; -} - /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. @@ -807,4 +781,32 @@ private: }; Field3DParallel Field3D::asField3DParallel() { return Field3DParallel(*this); } + + +inline Field3D operator+(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} +inline Field3D operator-(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} +inline Field3D operator*(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} +inline Field3D operator/(const Field2D& lhs, const Field3DParallel& rhs) { + return lhs + rhs.asField3D(); +} + +inline Field3D operator+(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() + rhs; +} +inline Field3D operator-(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() - rhs; +} +inline Field3D operator*(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() * rhs; +} +inline Field3D operator/(const Field3DParallel& lhs, const Field2D& rhs) { + return lhs.asField3D() / rhs; +} + #endif /* BOUT_FIELD3D_H */ From 3012a229cbb29794248a925f80b65b28ffa17a6b Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:17:16 +0200 Subject: [PATCH 100/259] Prefer std::move --- include/bout/field3d.hxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index c46f68d010..d4d2ab7651 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -35,6 +35,7 @@ class Field3D; #include "bout/region.hxx" #include +#include #include class Mesh; @@ -729,7 +730,7 @@ inline Field3D copy(const Field3D& f) { class Field3DParallel : public Field3D { public: template - Field3DParallel(Types... args) : Field3D(args...) { + Field3DParallel(Types... args) : Field3D(std::move(args)...) { ensureFieldAligned(); } // Explicitly needed, as DirectionTypes is sometimes constructed from a From 63a78d973defe9b66b0eb5c94bc27fd209815feb Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Mon, 21 Jul 2025 09:18:02 +0000 Subject: [PATCH 101/259] Apply clang-format changes --- include/bout/field3d.hxx | 1 - 1 file changed, 1 deletion(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index d4d2ab7651..35b67db73c 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -783,7 +783,6 @@ private: Field3DParallel Field3D::asField3DParallel() { return Field3DParallel(*this); } - inline Field3D operator+(const Field2D& lhs, const Field3DParallel& rhs) { return lhs + rhs.asField3D(); } From 2f9816208081c458cbde1f1a9c9052740a003e42 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:30:05 +0200 Subject: [PATCH 102/259] Add binary operators Field2D - FieldPerp the functions where implemented, but not defined in the header --- include/bout/field2d.hxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/bout/field2d.hxx b/include/bout/field2d.hxx index e510194c42..81147cc8e7 100644 --- a/include/bout/field2d.hxx +++ b/include/bout/field2d.hxx @@ -295,6 +295,10 @@ private: }; // Non-member overloaded operators +FieldPerp operator+(const Field2D& lhs, const FieldPerp& rhs); +FieldPerp operator-(const Field2D& lhs, const FieldPerp& rhs); +FieldPerp operator*(const Field2D& lhs, const FieldPerp& rhs); +FieldPerp operator/(const Field2D& lhs, const FieldPerp& rhs); Field2D operator+(const Field2D& lhs, const Field2D& rhs); Field2D operator-(const Field2D& lhs, const Field2D& rhs); From fdbbed68a03269d0c7e1e2ef96803b3dd0c43210 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:30:28 +0200 Subject: [PATCH 103/259] Remove some FCI_AUTOMAGIC --- include/bout/field.hxx | 29 ++++++++++++++--------------- include/bout/fv_ops.hxx | 2 -- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 53c0a7a050..4ef48734fc 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -683,23 +683,22 @@ inline T floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { result[d] = f; } } -#if BOUT_USE_FCI_AUTOMAGIC - if (var.isFci()) { - for (size_t i = 0; i < result.numberParallelSlices(); ++i) { - BOUT_FOR(d, result.yup(i).getRegion(rgn)) { - if (result.yup(i)[d] < f) { - result.yup(i)[d] = f; - } - } - BOUT_FOR(d, result.ydown(i).getRegion(rgn)) { - if (result.ydown(i)[d] < f) { - result.ydown(i)[d] = f; - } + if constexpr (std::is_same_v) { + if (var.hasParallelSlices()) { + for (size_t i = 0; i < result.numberParallelSlices(); ++i) { + BOUT_FOR(d, result.yup(i).getRegion(rgn)) { + if (result.yup(i)[d] < f) { + result.yup(i)[d] = f; + } + } + BOUT_FOR(d, result.ydown(i).getRegion(rgn)) { + if (result.ydown(i)[d] < f) { + result.ydown(i)[d] = f; + } + } } } - } else -#endif - { + } else { result.clearParallelSlices(); } return result; diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 8a9baaf3e7..17658f4eba 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -193,11 +193,9 @@ template const Field3D Div_par(const Field3D& f_in, const Field3D& v_in, const Field3D& wave_speed_in, bool fixflux = true) { -#if BOUT_USE_FCI_AUTOMAGIC if (f_in.isFci()) { return ::Div_par(f_in, v_in); } -#endif ASSERT1_FIELDS_COMPATIBLE(f_in, v_in); ASSERT1_FIELDS_COMPATIBLE(f_in, wave_speed_in); From cb643ebef0d72e99de89018cdfcb0ef6b996ef95 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 11:38:00 +0200 Subject: [PATCH 104/259] Only use "parallel_neumann_o2" if no other parallel bc set --- include/bout/field3d.hxx | 1 + src/field/field3d.cxx | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 35b67db73c..ee958b21cd 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -518,6 +518,7 @@ public: const std::string& condition) override; void applyParallelBoundary(const std::string& region, const std::string& condition, Field3D* f); + void applyParallelBoundaryWithDefault(const std::string& condition); friend void swap(Field3D& first, Field3D& second) noexcept; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 436b424bd7..2cd8ee18b1 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -404,11 +404,9 @@ Field3DParallel& Field3DParallel::operator=(const BoutReal val) { Field3D& Field3D::calcParallelSlices() { ASSERT2(allowCalcParallelSlices); getCoordinates()->getParallelTransform().calcParallelSlices(*this); -#if BOUT_USE_FCI_AUTOMAGIC if (this->isFci()) { - this->applyParallelBoundary("parallel_neumann_o2"); + this->applyParallelBoundaryWithDefault("parallel_neumann_o2"); } -#endif return *this; } @@ -574,6 +572,21 @@ void Field3D::applyParallelBoundary() { } } +void Field3D::applyParallelBoundaryWithDefault(const std::string& condition) { + + checkData(*this); + ASSERT1(hasParallelSlices()); + + // Apply boundary to this field + if (getBoundaryOpPars().empty()) { + applyParallelBoundary(condition); + } else { + for (const auto& bndry : getBoundaryOpPars()) { + bndry->apply(*this); + } + } +} + void Field3D::applyParallelBoundary(BoutReal t) { TRACE("Field3D::applyParallelBoundary(t)"); From 86fc85b00b87af13367f1a99ef4f814dfe504e67 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Mon, 21 Jul 2025 09:38:49 +0000 Subject: [PATCH 105/259] Apply clang-format changes --- include/bout/field.hxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 4ef48734fc..ef0429ab1d 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -686,16 +686,16 @@ inline T floor(const T& var, BoutReal f, const std::string& rgn = "RGN_ALL") { if constexpr (std::is_same_v) { if (var.hasParallelSlices()) { for (size_t i = 0; i < result.numberParallelSlices(); ++i) { - BOUT_FOR(d, result.yup(i).getRegion(rgn)) { - if (result.yup(i)[d] < f) { - result.yup(i)[d] = f; - } - } - BOUT_FOR(d, result.ydown(i).getRegion(rgn)) { - if (result.ydown(i)[d] < f) { - result.ydown(i)[d] = f; - } - } + BOUT_FOR(d, result.yup(i).getRegion(rgn)) { + if (result.yup(i)[d] < f) { + result.yup(i)[d] = f; + } + } + BOUT_FOR(d, result.ydown(i).getRegion(rgn)) { + if (result.ydown(i)[d] < f) { + result.ydown(i)[d] = f; + } + } } } } else { From 857e8c3fc1a3e3d88b93445689d6fe1eb2606476 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 21 Jul 2025 13:03:42 +0200 Subject: [PATCH 106/259] Declare Field3DParallel --- include/bout/field.hxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index ef0429ab1d..27e7fb2b89 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -667,6 +667,8 @@ T copy(const T& f) { return result; } +class Field3DParallel; + /// Apply a floor value \p f to a field \p var. Any value lower than /// the floor is set to the floor. /// From 751a22f6ce2a75047c3e61047bfd4aec5ce62ee2 Mon Sep 17 00:00:00 2001 From: malamast Date: Thu, 24 Jul 2025 11:34:02 -0700 Subject: [PATCH 107/259] SNES: reapplied some changes from previous commits that accidentally got deleted. --- src/solver/impls/snes/snes.cxx | 37 +++++++++++----------------------- src/solver/impls/snes/snes.hxx | 2 +- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 6b0438bb8b..eda4e9e783 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -140,9 +140,7 @@ SNESSolver::SNESSolver(Options* opts) .withDefault(1.4)), pid_controller( (*options)["pid_controller"].doc("Use PID controller?").withDefault(false)), - target_its((*options)["target_its"] - .doc("Target snes iterations") - .withDefault(static_cast(7))), + target_its((*options)["target_its"].doc("Target snes iterations").withDefault(7)), kP((*options)["kP"].doc("Proportional PID parameter").withDefault(0.7)), kI((*options)["kI"].doc("Integral PID parameter").withDefault(0.3)), kD((*options)["kD"].doc("Derivative PID parameter").withDefault(0.2)), @@ -646,7 +644,7 @@ int SNESSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - if (pid_controller){ + if (pid_controller) { nl_its_prev = target_its; nl_its_prev2 = target_its; SNESSetLagJacobianPersists(snes, PETSC_FALSE); @@ -865,7 +863,7 @@ int SNESSolver::run() { } - if (pid_controller){ + if (pid_controller) { SNESSetLagJacobian(snes, lag_jacobian); } @@ -1061,7 +1059,7 @@ int SNESSolver::run() { if (looping) { - if (pid_controller){ + if (pid_controller) { // Changing the timestep. // Note: The preconditioner depends on the timestep, // so we recalculate the jacobian and the preconditioner @@ -1087,9 +1085,7 @@ int SNESSolver::run() { // Increase timestep slightly timestep *= timestep_factor_on_lower_its; - if (timestep > max_timestep) { - timestep = max_timestep; - } + timestep = std::min(timestep, max_timestep); // Note: Setting the SNESJacobianFn to NULL retains // previously set evaluation function. @@ -1407,8 +1403,7 @@ void SNESSolver::updateColoring() { MatColoring coloring = NULL; MatColoringCreate(Jfd, &coloring); // MatColoringSetType(coloring, MATCOLORINGSL); // Serial algorithm. Better for smale-to-medium size problems. - MatColoringSetType( - coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs + MatColoringSetType(coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs // MatColoringSetType(coloring, MATCOLORINGJP); // This didn't work MatColoringSetFromOptions(coloring); @@ -1438,28 +1433,20 @@ void SNESSolver::updateColoring() { BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ - BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); - BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) + const BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); + const BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); + const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) / double(nl_its_prev2), kD); // clamp groth factor to avoid huge changes - BoutReal fac = facP * facI * facD; - if (fac < 0.2) - fac = 0.2; - else if (fac > 5.0) - fac = 5.0; + const BoutReal fac = std::clamp(facP * facI * facD, 0.2, 5.0); /* ---------- update timestep and history ---------- */ - BoutReal dt_new = timestep * fac; - - if (dt_new > max_timestep) { - dt_new = max_timestep; - } + const BoutReal dt_new = std::min(timestep * fac, max_timestep); nl_its_prev2 = nl_its_prev; - nl_its_prev = static_cast(nl_its); + nl_its_prev = nl_its; return dt_new; } diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index e31ca44625..bd942f09ff 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -109,7 +109,7 @@ private: ///< PID controller parameters bool pid_controller; ///< Use PID controller? - int target_its; ///< Target number of nonlinear iterations for the PID controller. + int target_its; ///< Target number of nonlinear iterations for the PID controller. ///< Use with caution! Not tested values. BoutReal kP; ///< (0.6 - 0.8) Proportional parameter (main response to current step) BoutReal kI; ///< (0.2 - 0.4) Integral parameter (smooths history of changes) From 865c0ab26987f393b9e8ab9294603259a501e3f1 Mon Sep 17 00:00:00 2001 From: malamast <42969991+malamast@users.noreply.github.com> Date: Thu, 24 Jul 2025 19:35:33 +0000 Subject: [PATCH 108/259] Apply clang-format changes --- src/solver/impls/snes/snes.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index eda4e9e783..72891941b6 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -862,7 +862,6 @@ int SNESSolver::run() { VecAXPBY(snes_x, -beta, (1. + beta), x1); } - if (pid_controller) { SNESSetLagJacobian(snes, lag_jacobian); } @@ -1403,7 +1402,8 @@ void SNESSolver::updateColoring() { MatColoring coloring = NULL; MatColoringCreate(Jfd, &coloring); // MatColoringSetType(coloring, MATCOLORINGSL); // Serial algorithm. Better for smale-to-medium size problems. - MatColoringSetType(coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs + MatColoringSetType( + coloring, MATCOLORINGGREEDY); // Parallel algorith. Better for large parallel runs // MatColoringSetType(coloring, MATCOLORINGJP); // This didn't work MatColoringSetFromOptions(coloring); @@ -1435,9 +1435,9 @@ BoutReal SNESSolver::pid(BoutReal timestep, int nl_its) { /* ---------- multiplicative PID factors ---------- */ const BoutReal facP = std::pow(double(target_its) / double(nl_its), kP); const BoutReal facI = std::pow(double(nl_its_prev) / double(nl_its), kI); - const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) / double(nl_its) - / double(nl_its_prev2), - kD); + const BoutReal facD = std::pow(double(nl_its_prev) * double(nl_its_prev) + / double(nl_its) / double(nl_its_prev2), + kD); // clamp groth factor to avoid huge changes const BoutReal fac = std::clamp(facP * facI * facD, 0.2, 5.0); From dd146a80b92dbf4afe42dd426e572bd07eb9066c Mon Sep 17 00:00:00 2001 From: Tom Body <116750897+tbody-cfs@users.noreply.github.com> Date: Wed, 16 Apr 2025 20:27:18 -0400 Subject: [PATCH 109/259] Update CMakeLists.txt Address #2945 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c45fca3b72..9405c9e8d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ message(STATUS "Configuring BOUT++ version ${BOUT_FULL_VERSION}") project(BOUT++ DESCRIPTION "Fluid PDE solver framework" VERSION ${BOUT_CMAKE_ACCEPTABLE_VERSION} - LANGUAGES CXX) + LANGUAGES C CXX) include(CMakeDependentOption) From 5988480b4f509c24b76602405fe4d4133a3eeb9c Mon Sep 17 00:00:00 2001 From: Tom Body Date: Fri, 18 Apr 2025 16:18:09 +0000 Subject: [PATCH 110/259] Move enable C to NetCDF --- cmake/FindnetCDF.cmake | 1 + cmake/SetupBOUTThirdParty.cmake | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindnetCDF.cmake b/cmake/FindnetCDF.cmake index 393c57549b..361095954e 100644 --- a/cmake/FindnetCDF.cmake +++ b/cmake/FindnetCDF.cmake @@ -32,6 +32,7 @@ if (NOT netCDF_ROOT AND EXISTS "${BOUT_USE_NETCDF}") set(netCDF_ROOT "${BOUT_USE_NETCDF}") endif() +enable_language(C) find_package(netCDF QUIET CONFIG) if (netCDF_FOUND) diff --git a/cmake/SetupBOUTThirdParty.cmake b/cmake/SetupBOUTThirdParty.cmake index 10942f8aa9..f8712c1b58 100644 --- a/cmake/SetupBOUTThirdParty.cmake +++ b/cmake/SetupBOUTThirdParty.cmake @@ -293,7 +293,6 @@ if (BOUT_USE_SUNDIALS) FetchContent_MakeAvailable(sundials) message(STATUS "SUNDIALS done configuring") else() - enable_language(C) find_package(SUNDIALS REQUIRED) if (SUNDIALS_VERSION VERSION_LESS 4.0.0) message(FATAL_ERROR "SUNDIALS_VERSION 4.0.0 or newer is required. Found version ${SUNDIALS_VERSION}.") From 0f7c8546e6a5396c5c692a631bf103d0cde945bc Mon Sep 17 00:00:00 2001 From: Tom Body Date: Fri, 18 Apr 2025 17:36:08 +0000 Subject: [PATCH 111/259] Remove top-level C --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9405c9e8d6..c45fca3b72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ message(STATUS "Configuring BOUT++ version ${BOUT_FULL_VERSION}") project(BOUT++ DESCRIPTION "Fluid PDE solver framework" VERSION ${BOUT_CMAKE_ACCEPTABLE_VERSION} - LANGUAGES C CXX) + LANGUAGES CXX) include(CMakeDependentOption) From 0ab77ba7c88ba13d693d565423e2311abd59feac Mon Sep 17 00:00:00 2001 From: Tom Body Date: Fri, 18 Apr 2025 18:47:12 +0000 Subject: [PATCH 112/259] Add back in C language for SUNDIALS --- cmake/SetupBOUTThirdParty.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/SetupBOUTThirdParty.cmake b/cmake/SetupBOUTThirdParty.cmake index f8712c1b58..53ceb4351c 100644 --- a/cmake/SetupBOUTThirdParty.cmake +++ b/cmake/SetupBOUTThirdParty.cmake @@ -272,6 +272,7 @@ option(BOUT_DOWNLOAD_SUNDIALS "Download and build SUNDIALS" OFF) cmake_dependent_option(BOUT_USE_SUNDIALS "Enable support for SUNDIALS time solvers" OFF "NOT BOUT_DOWNLOAD_SUNDIALS" ON) if (BOUT_USE_SUNDIALS) + enable_language(C) if (BOUT_DOWNLOAD_SUNDIALS) message(STATUS "Downloading and configuring SUNDIALS") include(FetchContent) From dc1d72d06b02068e44050c47e09fb32261b968d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 19:03:34 +0000 Subject: [PATCH 113/259] Update pygithub requirement from ~=2.6 to ~=2.7 Updates the requirements on [pygithub](https://github.com/pygithub/pygithub) to permit the latest version. - [Release notes](https://github.com/pygithub/pygithub/releases) - [Changelog](https://github.com/PyGithub/PyGithub/blob/main/doc/changes.rst) - [Commits](https://github.com/pygithub/pygithub/compare/v2.6.0...v2.7.0) --- updated-dependencies: - dependency-name: pygithub dependency-version: 2.7.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements_maint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_maint.txt b/requirements_maint.txt index e6ba00ce48..a5e94a0af5 100644 --- a/requirements_maint.txt +++ b/requirements_maint.txt @@ -1,3 +1,3 @@ -pygithub~=2.6 +pygithub~=2.7 ruamel-yaml~=0.18 Unidecode~=1.3 From b192b6a1690dd361b34d3c9a8b5e8265b7e912c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 02:47:33 +0000 Subject: [PATCH 114/259] Bump externalpackages/googletest from `bac6a8f` to `244cec8` Bumps [externalpackages/googletest](https://github.com/google/googletest) from `bac6a8f` to `244cec8`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/bac6a8fd8a729eef0d1b2d1a4625f4de62c60220...244cec869d12e53378fa0efb610cd4c32a454ec8) --- updated-dependencies: - dependency-name: externalpackages/googletest dependency-version: 244cec869d12e53378fa0efb610cd4c32a454ec8 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index bac6a8fd8a..244cec869d 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit bac6a8fd8a729eef0d1b2d1a4625f4de62c60220 +Subproject commit 244cec869d12e53378fa0efb610cd4c32a454ec8 From 424a2e5282810cba6239627b93634be5bc3519c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 04:47:47 +0000 Subject: [PATCH 115/259] Bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/black-fix.yml | 2 +- .github/workflows/clang-format.yml | 2 +- .github/workflows/clang-tidy-review.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/python-package.yml | 6 +++--- .github/workflows/tests.yml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/black-fix.yml b/.github/workflows/black-fix.yml index 92866dfcc2..6c1bfed4a5 100644 --- a/.github/workflows/black-fix.yml +++ b/.github/workflows/black-fix.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: ${{ github.head_ref }} diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 87f1947802..ed60dc9631 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: # Checkout the pull request branch, also include all history - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: ${{ github.head_ref }} fetch-depth: 0 diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 9746075b1a..433204e492 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -17,7 +17,7 @@ jobs: review: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: submodules: true diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a1dac41a6b..1380d0ea8e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -52,7 +52,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Log in to the Container registry uses: docker/login-action@master diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index ea68e58c12..5a788f9eb0 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -17,7 +17,7 @@ jobs: if: always() steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 submodules: true @@ -57,7 +57,7 @@ jobs: if: always() steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 submodules: true @@ -106,7 +106,7 @@ jobs: if: always() steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 submodules: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ede53ef20d..aa3db3adc1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -158,7 +158,7 @@ jobs: liblapack-dev libparpack2-dev - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: submodules: true @@ -192,7 +192,7 @@ jobs: timeout-minutes: 60 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: submodules: true - name: Build Fedora From ec1f94f45ddfc0fe9cc9d83e8e4058d9b48af1b7 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Wed, 13 Aug 2025 10:29:05 -0700 Subject: [PATCH 116/259] snes: Print a warning if the coloring is non-symmetric. Added comments to explain why the coloring may be non-symmetric around an X-point. --- src/solver/impls/snes/snes.cxx | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 72891941b6..134b63c2f8 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -377,8 +377,8 @@ int SNESSolver::init() { auto n_cross = (*options)["stencil:cross"] .doc("Extent of stencil (cross)") .withDefault(0); - //Set n_taxi 2 if nothing else is set - //Probably a better way to do this + // Set n_taxi 2 if nothing else is set + // Probably a better way to do this if (n_square == 0 && n_taxi == 0 && n_cross == 0) { output_info.write("Setting solver:stencil:taxi = 2\n"); n_taxi = 2; @@ -485,7 +485,7 @@ int SNESSolver::init() { d_nnz.reserve(nlocal); for (int i = 0; i < nlocal; ++i) { - //Assume all elements in the z direction are potentially coupled + // Assume all elements in the z direction are potentially coupled d_nnz.emplace_back(d_nnz_map3d[i].size() * mesh->LocalNz + d_nnz_map2d[i].size()); o_nnz.emplace_back(o_nnz_map3d[i].size() * mesh->LocalNz @@ -598,9 +598,21 @@ int SNESSolver::init() { MatAssemblyBegin(Jfd, MAT_FINAL_ASSEMBLY); MatAssemblyEnd(Jfd, MAT_FINAL_ASSEMBLY); - //The above will probably miss some non-zero entries at process boundaries - //Making sure the colouring matrix is symmetric will in some/all(?) - //of the missing non-zeros + { + // Test if the matrix is symmetric + // Values are 0 or 1 so tolerance (1e-5) shouldn't matter + PetscBool symmetric; + ierr = MatIsSymmetric(Jfd, 1e-5, &symmetric); CHKERRQ(ierr); + if (!symmetric) { + output_warn.write("Jacobian pattern is not symmetric\n"); + } + } + + // The above can miss entries around the X-point branch cut: + // The diagonal terms are complicated because moving in X then Y + // is different from moving in Y then X at the X-point. + // Making sure the colouring matrix is symmetric does not + // necessarily give the correct stencil but may help. if ((*options)["force_symmetric_coloring"] .doc("Modifies coloring matrix to force it to be symmetric") .withDefault(false)) { From cf7e0437af135d4812ae77bf9819dbb918c7a838 Mon Sep 17 00:00:00 2001 From: bendudson <219233+bendudson@users.noreply.github.com> Date: Wed, 13 Aug 2025 22:37:55 +0000 Subject: [PATCH 117/259] Apply clang-format changes --- src/solver/impls/snes/snes.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 134b63c2f8..2bb163f324 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -602,7 +602,8 @@ int SNESSolver::init() { // Test if the matrix is symmetric // Values are 0 or 1 so tolerance (1e-5) shouldn't matter PetscBool symmetric; - ierr = MatIsSymmetric(Jfd, 1e-5, &symmetric); CHKERRQ(ierr); + ierr = MatIsSymmetric(Jfd, 1e-5, &symmetric); + CHKERRQ(ierr); if (!symmetric) { output_warn.write("Jacobian pattern is not symmetric\n"); } From 741b1df7c693db1c0970044206d25749801f4291 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 20:51:21 -0700 Subject: [PATCH 118/259] PetscLib: Add setOptionsFromInputFile(TS& ts) Sets options on a TS object using the options in the BOUT.inp [petsc] section. --- include/bout/petsclib.hxx | 7 +++++-- src/sys/petsclib.cxx | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/bout/petsclib.hxx b/include/bout/petsclib.hxx index 2008671286..760b18ff91 100644 --- a/include/bout/petsclib.hxx +++ b/include/bout/petsclib.hxx @@ -22,9 +22,9 @@ * so it *must* be included before *any* PETSc header. * ************************************************************************** - * Copyright 2012 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2012 - 2025 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -113,6 +113,9 @@ public: /// was passed to the constructor. void setOptionsFromInputFile(SNES& snes); + /// Set options for a TS time integrator + void setOptionsFromInputFile(TS& ts); + /*! * Force cleanup. This will call PetscFinalize, printing a warning * if any instances of PetscLib still exist diff --git a/src/sys/petsclib.cxx b/src/sys/petsclib.cxx index f1cf1a9d1b..1830db89d9 100644 --- a/src/sys/petsclib.cxx +++ b/src/sys/petsclib.cxx @@ -119,6 +119,12 @@ void PetscLib::setOptionsFromInputFile(SNES& snes) { BOUT_DO_PETSC(SNESSetFromOptions(snes)); } +void PetscLib::setOptionsFromInputFile(TS& ts) { + BOUT_DO_PETSC(TSSetOptionsPrefix(ts, options_prefix.c_str())); + + BOUT_DO_PETSC(TSSetFromOptions(ts)); +} + void PetscLib::cleanup() { BOUT_OMP_SAFE(critical(PetscLib)) { From 33b984291a799a92466ddc284c2dd78776f94a06 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 20:55:30 -0700 Subject: [PATCH 119/259] PETSc solver: Merge SNES Jacobian coloring with TS interface Uses the TS interface https://petsc.org/release/manual/ts/ allowing many different time integration methods, timestep adaptation methods etc. to be tried. --- src/solver/impls/petsc/petsc.cxx | 1518 +++++++++++++++--------------- src/solver/impls/petsc/petsc.hxx | 102 +- 2 files changed, 789 insertions(+), 831 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index dd63811f0f..22d8594c28 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -2,9 +2,9 @@ * Interface to PETSc solver * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2025 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -32,53 +32,230 @@ #include #include +#include +#include +#include +#include +#include -#include +#include +#include -#include // Cell interpolation -#include #include -extern PetscErrorCode solver_f(TS ts, BoutReal t, Vec globalin, Vec globalout, - void* f_data); +#include "petscsnes.h" + +class ColoringStencil { +private: + bool static isInSquare(int const i, int const j, int const n_square) { + return std::abs(i) <= n_square && std::abs(j) <= n_square; + } + bool static isInCross(int const i, int const j, int const n_cross) { + if (i == 0) { + return std::abs(j) <= n_cross; + } + if (j == 0) { + return std::abs(i) <= n_cross; + } + return false; + } + bool static isInTaxi(int const i, int const j, int const n_taxi) { + return std::abs(i) + std::abs(j) <= n_taxi; + } + +public: + auto static getOffsets(int n_square, int n_taxi, int n_cross) { + ASSERT2(n_square >= 0 && n_cross >= 0 && n_taxi >= 0 + && n_square + n_cross + n_taxi > 0); + auto inside = [&](int i, int j) { + return isInSquare(i, j, n_square) || isInTaxi(i, j, n_taxi) + || isInCross(i, j, n_cross); + }; + std::vector> xy_offsets; + auto loop_bound = std::max({n_square, n_taxi, n_cross}); + for (int i = -loop_bound; i <= loop_bound; ++i) { + for (int j = -loop_bound; j <= loop_bound; ++j) { + if (inside(i, j)) { + xy_offsets.emplace_back(i, j); + } + } + } + return xy_offsets; + } +}; + +// PETSc callback function for matrix-free preconditioner +static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { + // Get the context + void* ctx; + int ierr = PCShellGetContext(pc, &ctx); + CHKERRQ(ierr); + // Run the preconditioner + PetscFunctionReturn(static_cast(ctx)->pre(x, y)); +} + +// PETSc callback function, that evaluates the nonlinear +// function being integrated by TS. +static PetscErrorCode solver_rhs(TS UNUSED(ts), BoutReal t, Vec globalin, Vec globalout, + void* f_data) { + PetscFunctionBegin; + auto* s = static_cast(f_data); + s->rhs(t, globalin, globalout, false); + PetscFunctionReturn(0); +} + +// PETSc callback function for finite differencing. +// May use a linearised form of the RHS function. +static PetscErrorCode solver_rhs_differencing(void* ctx, Vec globalin, Vec globalout) { + PetscFunctionBegin; + auto* s = static_cast(ctx); + s->rhs_differencing(globalin, globalout); + PetscFunctionReturn(0); +} + +// PETSc callback function for coloring. +// May use a linearised form of the RHS function. +static PetscErrorCode solver_rhs_coloring(void* UNUSED(snes), Vec globalin, Vec globalout, + void* ctx) { + PetscFunctionBegin; + auto* s = static_cast(ctx); + s->rhs_differencing(globalin, globalout); + PetscFunctionReturn(0); +} -#if PETSC_VERSION_GE(3, 5, 0) -extern PetscErrorCode solver_rhsjacobian(TS ts, BoutReal t, Vec globalin, Mat J, Mat Jpre, - void* f_data); -extern PetscErrorCode solver_ijacobianfd(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, - void*); +// Compute IJacobian = dF/dU + a dF/dUdot +// This is a dummy matrix that saves the shift. +// The shift is later used in the matrix-free preconditioner +PetscErrorCode solver_ijacobian(TS, BoutReal, Vec, Vec, PetscReal shift, Mat J, Mat Jpre, + void* ctx) { + auto* solver = static_cast(ctx); + solver->shift = shift; + + PetscCall(MatAssemblyBegin(Jpre, MAT_FINAL_ASSEMBLY)); + PetscCall(MatAssemblyEnd(Jpre, MAT_FINAL_ASSEMBLY)); + if (J != Jpre) { + PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); + PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); + } + + PetscFunctionReturn(0); +} + +// This function is called by the TS object every internal timestep +// It is responsible for triggering interpolation and output at +// the output time interval. +PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, void* ctx) { + PetscFunctionBegin; + + auto* s = static_cast(ctx); + if (t < s->next_output) { + // Not reached output time yet => return + PetscFunctionReturn(0); + } + + PetscErrorCode ierr; + PetscReal tfinal; + static int i = 0; + +#if PETSC_VERSION_GE(3, 8, 0) + ierr = TSGetMaxTime(ts, &tfinal); + CHKERRQ(ierr); #else -extern PetscErrorCode solver_rhsjacobian(TS ts, BoutReal t, Vec globalin, Mat* J, - Mat* Jpre, MatStructure* str, void* f_data); -extern PetscErrorCode solver_ijacobianfd(TS, PetscReal, Vec, Vec, PetscReal, Mat*, Mat*, - MatStructure*, void*); + ierr = TSGetDuration(ts, nullptr, &tfinal); + CHKERRQ(ierr); #endif -extern PetscErrorCode solver_if(TS, BoutReal, Vec, Vec, Vec, void*); + // Duplicate the solution vector X into a work vector + Vec interpolatedX; + ierr = VecDuplicate(X, &interpolatedX); + CHKERRQ(ierr); -/// KSP preconditioner PCShell routines for physics preconditioners -extern PetscErrorCode PhysicsPCApply(PC, Vec x, Vec y); -extern PetscErrorCode PhysicsJacobianApply(Mat J, Vec x, Vec y); -extern PetscErrorCode PhysicsSNESApply(SNES, Vec); + // The internal timestepper may have stepped over multiple output times + while (s->next_output <= t && s->next_output <= tfinal) { + if (s->interpolate) { + ierr = TSInterpolate(ts, s->next_output, interpolatedX); + CHKERRQ(ierr); + } + + // Place the interpolated values into the global variables + const PetscScalar* x; + ierr = VecGetArrayRead(interpolatedX, &x); + CHKERRQ(ierr); + s->load_vars(const_cast(x)); + ierr = VecRestoreArrayRead(interpolatedX, &x); + CHKERRQ(ierr); + + if (s->call_monitors(s->next_output, i++, s->getNumberOutputSteps())) { + PetscFunctionReturn(1); + } + + s->next_output += s->getOutputTimestep(); + } + + // Done with vector, so destroy it + ierr = VecDestroy(&interpolatedX); + CHKERRQ(ierr); + + PetscFunctionReturn(0); +} PetscSolver::PetscSolver(Options* opts) : Solver(opts), diagnose( (*options)["diagnose"].doc("Enable some diagnostic output").withDefault(false)), - adaptive( - (*options)["adaptive"].doc("Use adaptive timestepping").withDefault(false)), - use_precon((*options)["use_precon"] - .doc("Use user-supplied preconditioning function") - .withDefault(false)), - use_jacobian((*options)["use_jacobian"] - .doc("Use user-supplied Jacobian function") - .withDefault(false)), - abstol((*options)["atol"].doc("Absolute tolerance").withDefault(1.0e-12)), - reltol((*options)["rtol"].doc("Relative tolerance").withDefault(1.0e-5)), - adams_moulton((*options)["adams_moulton"] - .doc("Use Adams-Moulton implicit multistep method instead of BDF " - "(requires PETSc to have been built with SUNDIALS)") - .withDefault(false)), + user_precon((*options)["user_precon"] + .doc("Use user-supplied preconditioning function?") + .withDefault(false)), + atol((*options)["atol"].doc("Absolute tolerance").withDefault(1.0e-12)), + rtol((*options)["rtol"].doc("Relative tolerance").withDefault(1.0e-5)), + stol((*options)["stol"] + .doc("Convergence tolerance in terms of the norm of the change in " + "the solution between steps") + .withDefault(1e-8)), + maxnl((*options)["max_nonlinear_iterations"] + .doc("Maximum number of nonlinear iterations per SNES solve") + .withDefault(50)), + maxf((*options)["maxf"] + .doc("Maximum number of function evaluations per SNES solve") + .withDefault(10000)), + maxl((*options)["maxl"].doc("Maximum number of linear iterations").withDefault(20)), + ts_type( + (*options)["ts_type"].doc("PETSc time integrator type").withDefault("beuler")), + adapt_type((*options)["adapt_type"] + .doc("PETSc TSAdaptType timestep adaptation method") + .withDefault("basic")), + snes_type((*options)["snes_type"] + .doc("PETSc nonlinear solver method to use") + .withDefault("newtonls")), + ksp_type((*options)["ksp_type"] + .doc("Linear solver type. By default let PETSc decide (gmres)") + .withDefault("default")), + pc_type( + (*options)["pc_type"] + .doc("Preconditioner type. By default lets PETSc decide (ilu or bjacobi)") + .withDefault("default")), + pc_hypre_type((*options)["pc_hypre_type"] + .doc("hypre preconditioner type: euclid, pilut, parasails, " + "boomeramg, ams, ads") + .withDefault("pilut")), + line_search_type((*options)["line_search_type"] + .doc("Line search type: basic, bt, l2, cp, nleqerr") + .withDefault("default")), + matrix_free((*options)["matrix_free"] + .doc("Use matrix free Jacobian?") + .withDefault(false)), + matrix_free_operator((*options)["matrix_free_operator"] + .doc("Use matrix free Jacobian-vector operator?") + .withDefault(false)), + lag_jacobian((*options)["lag_jacobian"] + .doc("Re-use the Jacobian this number of SNES iterations") + .withDefault(50)), + use_coloring((*options)["use_coloring"] + .doc("Use matrix coloring to calculate Jacobian?") + .withDefault(true)), + kspsetinitialguessnonzero((*options)["kspsetinitialguessnonzero"] + .doc("Set the initial guess to be non-zero") + .withDefault(false)), start_timestep((*options)["start_timestep"] .doc("Initial internal timestep (defaults to output timestep)") .withDefault(getOutputTimestep())), @@ -87,9 +264,9 @@ PetscSolver::PetscSolver(Options* opts) PetscSolver::~PetscSolver() { VecDestroy(&u); - MatDestroy(&J); + MatDestroy(&Jfd); MatDestroy(&Jmf); - MatFDColoringDestroy(&matfdcoloring); + MatFDColoringDestroy(&fdcoloring); TSDestroy(&ts); } @@ -99,74 +276,45 @@ PetscSolver::~PetscSolver() { int PetscSolver::init() { PetscErrorCode ierr; - int neq; - MPI_Comm comm = PETSC_COMM_WORLD; - PetscMPIInt rank; TRACE("Initialising PETSc-dev solver"); - PetscFunctionBegin; - PetscLogEventRegister("PetscSolver::init", PETSC_VIEWER_CLASSID, &init_event); - PetscLogEventRegister("loop_vars", PETSC_VIEWER_CLASSID, &loop_event); - PetscLogEventRegister("solver_f", PETSC_VIEWER_CLASSID, &solver_event); - Solver::init(); - ierr = PetscLogEventBegin(init_event, 0, 0, 0, 0); - CHKERRQ(ierr); - output.write("Initialising PETSc-dev solver\n"); - ierr = bout::globals::mpi->MPI_Comm_rank(comm, &rank); - CHKERRQ(ierr); + int nlocal = getLocalN(); // Number of evolving variables on this processor - PetscInt local_N = getLocalN(); // Number of evolving variables on this processor - - /********** Get total problem size **********/ - if (bout::globals::mpi->MPI_Allreduce(&local_N, &neq, 1, MPI_INT, MPI_SUM, + // Get total problem size + int neq; + if (bout::globals::mpi->MPI_Allreduce(&nlocal, &neq, 1, MPI_INT, MPI_SUM, BoutComm::get())) { - output_error.write("\tERROR: MPI_Allreduce failed!\n"); - ierr = PetscLogEventEnd(init_event, 0, 0, 0, 0); - CHKERRQ(ierr); - PetscFunctionReturn(1); + throw BoutException("MPI_Allreduce failed!"); } - ierr = VecCreate(BoutComm::get(), &u); - CHKERRQ(ierr); - ierr = VecSetSizes(u, local_N, PETSC_DECIDE); + output_info.write("\t3d fields = {:d}, 2d fields = {:d} neq={:d}, local_N={:d}\n", + n3Dvars(), n2Dvars(), neq, nlocal); + + // Create a vector to contain the state + PetscCall(VecCreate(BoutComm::get(), &u)); + ierr = VecSetSizes(u, nlocal, PETSC_DECIDE); CHKERRQ(ierr); ierr = VecSetFromOptions(u); CHKERRQ(ierr); - ////////// SAVE INITIAL STATE TO PETSc VECTOR /////////// - // Set pointer to data array in vector u. - BoutReal* udata; - + // Save initial state to PETSc Vec + BoutReal* udata; // Pointer to data array in vector u. ierr = VecGetArray(u, &udata); CHKERRQ(ierr); save_vars(udata); ierr = VecRestoreArray(u, &udata); CHKERRQ(ierr); - PetscReal norm; - ierr = VecNorm(u, NORM_1, &norm); - CHKERRQ(ierr); - output_info << "initial |u| = " << norm << "\n"; - - PetscBool J_load; - char load_file[PETSC_MAX_PATH_LEN]; /* jacobian input file name */ - PetscBool J_write = PETSC_FALSE, J_slowfd = PETSC_FALSE; - // Create timestepper ierr = TSCreate(BoutComm::get(), &ts); CHKERRQ(ierr); ierr = TSSetProblemType(ts, TS_NONLINEAR); CHKERRQ(ierr); -#if PETSC_HAS_SUNDIALS - ierr = TSSetType(ts, TSSUNDIALS); - CHKERRQ(ierr); -#else - ierr = TSSetType(ts, TSRK); + ierr = TSSetType(ts, ts_type.c_str()); CHKERRQ(ierr); -#endif ierr = TSSetApplicationContext(ts, this); CHKERRQ(ierr); @@ -175,55 +323,38 @@ int PetscSolver::init() { Vec rhs_vec; ierr = VecDuplicate(u, &rhs_vec); CHKERRQ(ierr); - ierr = TSSetRHSFunction(ts, rhs_vec, solver_f, this); - CHKERRQ(ierr); - ierr = VecDestroy(&rhs_vec); + ierr = TSSetRHSFunction(ts, rhs_vec, solver_rhs, this); CHKERRQ(ierr); // Set up adaptive time-stepping TSAdapt adapt; ierr = TSGetAdapt(ts, &adapt); CHKERRQ(ierr); - if (adaptive) { - ierr = TSAdaptSetType(adapt, TSADAPTBASIC); - CHKERRQ(ierr); - } else { - ierr = TSAdaptSetType(adapt, TSADAPTNONE); - CHKERRQ(ierr); - } - - // Set default absolute/relative tolerances - ierr = TSSetTolerances(ts, abstol, nullptr, reltol, nullptr); + ierr = TSAdaptSetType(adapt, adapt_type.c_str()); CHKERRQ(ierr); -#if PETSC_VERSION_LT(3, 5, 0) - ierr = TSRKSetTolerance(ts, reltol); + // Set default absolute/relative tolerances + // Note: Vector atol and rtol not given + ierr = TSSetTolerances(ts, atol, nullptr, rtol, nullptr); CHKERRQ(ierr); -#endif - + if (ts_type == TSSUNDIALS) { #if PETSC_HAS_SUNDIALS - // Set Sundials tolerances - ierr = TSSundialsSetTolerance(ts, abstol, reltol); - CHKERRQ(ierr); - - // Select Sundials Adams-Moulton or BDF method - if (adams_moulton) { - output.write("\tUsing Adams-Moulton implicit multistep method\n"); - ierr = TSSundialsSetType(ts, SUNDIALS_ADAMS); - CHKERRQ(ierr); - } else { - output.write("\tUsing BDF method\n"); - ierr = TSSundialsSetType(ts, SUNDIALS_BDF); - CHKERRQ(ierr); - } + // The PETSc interface to SUNDIALS' CVODE + TSSundialsSetType(ts, SUNDIALS_BDF); + TSSundialsSetTolerance(ts, atol, rtol); +#else + throw BoutException("PETSc was not built with SUNDIALS. Reconfigure and build PETSc " + "with --download-sundials"); #endif + } - // Initial time and timestep + // Initial time of the simulation state ierr = TSSetTime(ts, simtime); CHKERRQ(ierr); + next_output = simtime; + ierr = TSSetTimeStep(ts, start_timestep); CHKERRQ(ierr); - next_output = simtime; // Total number of steps PetscInt total_steps = mxstep * getNumberOutputSteps(); @@ -245,377 +376,537 @@ int PetscSolver::init() { // Set the current solution ierr = TSSetSolution(ts, u); CHKERRQ(ierr); - - // Create RHSJacobian J - SNES snes, psnes; - KSP ksp, nksp; - PC pc, npc; - PCType pctype; - TSType tstype; - PetscBool pcnone = PETSC_TRUE; - - ierr = TSGetSNES(ts, &snes); - CHKERRQ(ierr); + // Allow TS to step over the final time + // Note: This does not affect intermediate outputs, that + // are always interpolated (in PetscMonitor) ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_INTERPOLATE); CHKERRQ(ierr); + ierr = TSMonitorSet(ts, PetscMonitor, this, nullptr); -#if PETSC_VERSION_GE(3, 7, 0) - ierr = PetscOptionsGetBool(nullptr, nullptr, "-interpolate", &interpolate, nullptr); - CHKERRQ(ierr); -#else - ierr = PetscOptionsGetBool(nullptr, "-interpolate", &interpolate, nullptr); - CHKERRQ(ierr); -#endif + if (ts_type != TSSUNDIALS) { + // Get and configure the SNES nonlinear solver + // Note: SUNDIALS does not use PETSc SNES or KSP + // https://petsc.org/release/manual/ts/#using-sundials-from-petsc - // Check for -output_name to see if user specified a "performance" - // run, if they didn't then use the standard monitor function. TODO: - // use PetscFList -#if PETSC_VERSION_GE(3, 7, 0) - ierr = PetscOptionsGetString(nullptr, nullptr, "-output_name", this->output_name, - sizeof this->output_name, &output_flag); - CHKERRQ(ierr); -#else - ierr = PetscOptionsGetString(nullptr, "-output_name", this->output_name, - sizeof this->output_name, &output_flag); - CHKERRQ(ierr); -#endif - - // If the output_name is not specified then use the standard monitor function - if (output_flag != 0U) { - ierr = SNESMonitorSet(snes, PetscSNESMonitor, this, nullptr); + ierr = TSGetSNES(ts, &snes); CHKERRQ(ierr); - } else { - ierr = TSMonitorSet(ts, PetscMonitor, this, nullptr); - CHKERRQ(ierr); - } - ierr = SNESSetTolerances(snes, abstol, reltol, PETSC_DEFAULT, PETSC_DEFAULT, - PETSC_DEFAULT); - CHKERRQ(ierr); - - // Matrix free Jacobian - - if (use_jacobian and hasJacobian()) { - // Use a user-supplied Jacobian function - ierr = MatCreateShell(comm, local_N, local_N, neq, neq, this, &Jmf); - CHKERRQ(ierr); - ierr = MatShellSetOperation(Jmf, MATOP_MULT, - reinterpret_cast(PhysicsJacobianApply)); - CHKERRQ(ierr); - ierr = TSSetIJacobian(ts, Jmf, Jmf, solver_ijacobian, this); - CHKERRQ(ierr); - } else { - // Use finite difference approximation - ierr = MatCreateSNESMF(snes, &Jmf); - CHKERRQ(ierr); - ierr = SNESSetJacobian(snes, Jmf, Jmf, MatMFFDComputeJacobian, this); + ierr = SNESSetType(snes, snes_type.c_str()); CHKERRQ(ierr); - } - - ierr = SNESGetKSP(snes, &ksp); - CHKERRQ(ierr); - ierr = KSPSetTolerances(ksp, reltol, abstol, PETSC_DEFAULT, PETSC_DEFAULT); - CHKERRQ(ierr); - - ierr = KSPGetPC(ksp, &pc); - CHKERRQ(ierr); + // Line search + if (line_search_type != "default") { + SNESLineSearch linesearch; + SNESGetLineSearch(snes, &linesearch); + SNESLineSearchSetType(linesearch, line_search_type.c_str()); + } - if (use_precon and hasPreconditioner()) { + // Set tolerances + // Note: TS should set SNES convergence tolerances + SNESSetTolerances(snes, + PETSC_DETERMINE, // atol + PETSC_DETERMINE, // rtol + PETSC_DETERMINE, // stol + maxnl, maxf); -#if PETSC_VERSION_GE(3, 5, 0) - ierr = SNESGetNPC(snes, &psnes); - CHKERRQ(ierr); -#else - ierr = SNESGetPC(snes, &psnes); - CHKERRQ(ierr); + // Force SNES to take at least one nonlinear iteration. + // This may prevent the solver from getting stuck in false steady state conditions +#if PETSC_VERSION_GE(3, 8, 0) + SNESSetForceIteration(snes, PETSC_TRUE); #endif - ierr = SNESGetKSP(psnes, &nksp); - CHKERRQ(ierr); - ierr = KSPGetPC(nksp, &npc); - CHKERRQ(ierr); - ierr = SNESSetType(psnes, SNESSHELL); - CHKERRQ(ierr); - ierr = SNESShellSetSolve(psnes, PhysicsSNESApply); - CHKERRQ(ierr); - // Use a user-supplied preconditioner + // Re-use Jacobian + // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian + // always updates its reference 'u' vector every nonlinear iteration + SNESSetLagJacobian(snes, lag_jacobian); + SNESSetLagJacobianPersists(snes, PETSC_FALSE); - // Tell PETSc we're using a "shell" preconditioner - ierr = PCSetType(pc, PCSHELL); - CHKERRQ(ierr); - - // Set routine for applying preconditioner - ierr = PCShellSetApply(pc, PhysicsPCApply); - CHKERRQ(ierr); + SNESSetLagPreconditionerPersists(snes, PETSC_FALSE); + SNESSetLagPreconditioner(snes, 1); // Rebuild when Jacobian is rebuilt - // Set context to this solver object - ierr = PCShellSetContext(pc, this); - CHKERRQ(ierr); + // Get and configure the KSP linear solver + SNESGetKSP(snes, &ksp); - // Set name of preconditioner - ierr = PCShellSetName(pc, "PhysicsPreconditioner"); - CHKERRQ(ierr); - - // Need a callback for IJacobian to get shift 'alpha' - ierr = TSSetIJacobian(ts, Jmf, Jmf, solver_ijacobian, this); - CHKERRQ(ierr); + if (ksp_type != "default") { + KSPSetType(ksp, ksp_type.c_str()); + } - // Use right preconditioner - ierr = KSPSetPCSide(ksp, PC_RIGHT); - CHKERRQ(ierr); + if (kspsetinitialguessnonzero) { + // Set the initial guess to be non-zero + KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); + } - } else { - // Default to no preconditioner - ierr = PCSetType(pc, PCNONE); - CHKERRQ(ierr); + KSPSetTolerances(ksp, + PETSC_DEFAULT, // rtol + PETSC_DEFAULT, // abstol + PETSC_DEFAULT, // dtol (divergence tolerance) + maxl); // Maximum number of iterations + + // Set up the Jacobian + // Note: We can have both matrix-free Jacobian-vector operator (Jmf) + // and a finite-difference Jacobian matrix (Jfd) + if (matrix_free or matrix_free_operator) { + /* + PETSc SNES matrix free Jacobian, using a different + operator for differencing. + + See PETSc examples + http://www.mcs.anl.gov/petsc/petsc-current/src/snes/examples/tests/ex7.c.html + and this thread: + http://lists.mcs.anl.gov/pipermail/petsc-users/2014-January/020075.html + + */ + MatCreateSNESMF(snes, &Jmf); + + // Set a function to be called for differencing + // This can be a linearised form of the SNES function + // Note: Unsure if setting this will interfere with TS object + // because the SNES Jacobian depends on the timestep + //MatMFFDSetFunction(Jmf, solver_rhs_differencing, this); + } } - ierr = TSSetFromOptions(ts); - CHKERRQ(ierr); // enable PETSc runtime options - - ierr = PCGetType(pc, &pctype); - CHKERRQ(ierr); - ierr = TSGetType(ts, &tstype); - CHKERRQ(ierr); - output.write("\tTS type {:s}, PC type {:s}\n", tstype, pctype); - ierr = PetscObjectTypeCompare(reinterpret_cast(pc), PCNONE, &pcnone); - CHKERRQ(ierr); - if (pcnone) { - ierr = PetscLogEventEnd(init_event, 0, 0, 0, 0); - CHKERRQ(ierr); - PetscFunctionReturn(0); - } - ierr = PetscObjectTypeCompare(reinterpret_cast(pc), PCSHELL, &pcnone); - CHKERRQ(ierr); - if (pcnone) { - ierr = PetscLogEventEnd(init_event, 0, 0, 0, 0); - CHKERRQ(ierr); - PetscFunctionReturn(0); + // Configure preconditioner + PC pc; + if (ts_type == TSSUNDIALS) { +#if PETSC_HAS_SUNDIALS + TSSundialsGetPC(ts, &pc); +#endif + } else { + // Get PC context from KSP + KSPGetPC(ksp, &pc); } + if (matrix_free) { + // Matrix-free preconditioner - // Create Jacobian matrix to be used by preconditioner - output_info << " Get Jacobian matrix at simtime " << simtime << "\n"; -#if PETSC_VERSION_GE(3, 7, 0) - ierr = PetscOptionsGetString(nullptr, nullptr, "-J_load", load_file, - PETSC_MAX_PATH_LEN - 1, &J_load); - CHKERRQ(ierr); -#else - ierr = PetscOptionsGetString(nullptr, "-J_load", load_file, PETSC_MAX_PATH_LEN - 1, - &J_load); - CHKERRQ(ierr); -#endif - if (J_load) { - PetscViewer fd; - output_info << " Load Jmat ...local_N " << local_N << " neq " << neq << "\n"; - ierr = PetscViewerBinaryOpen(comm, load_file, FILE_MODE_READ, &fd); - CHKERRQ(ierr); - ierr = MatCreate(PETSC_COMM_WORLD, &J); - CHKERRQ(ierr); - //ierr = MatSetType(J, MATBAIJ);CHKERRQ(ierr); - ierr = MatSetSizes(J, local_N, local_N, PETSC_DECIDE, PETSC_DECIDE); - CHKERRQ(ierr); - ierr = MatSetFromOptions(J); - CHKERRQ(ierr); - ierr = MatLoad(J, fd); - CHKERRQ(ierr); - ierr = PetscViewerDestroy(&fd); - CHKERRQ(ierr); - } else { // create Jacobian matrix - - /* number of degrees (variables) at each grid point */ - PetscInt dof = n3Dvars(); - - // Maximum allowable size of stencil in x is the number of guard cells - PetscInt stencil_width_estimate = options->operator[]("stencil_width_estimate") - .withDefault(bout::globals::mesh->xstart); - // This is the stencil in each direction (*2) along each dimension - // (*3), plus the point itself. Not sure if this is correct - // though, on several levels: - // 1. Ignores corner points used in e.g. brackets - // 2. Could have different stencil widths in each dimension - // 3. FFTs couple every single point together - PetscInt cols = stencil_width_estimate * 2 * 3 + 1; - PetscInt prealloc; // = cols*dof; - - ierr = MatCreate(comm, &J); - CHKERRQ(ierr); - ierr = MatSetType(J, MATBAIJ); - CHKERRQ(ierr); - ierr = MatSetSizes(J, local_N, local_N, neq, neq); - CHKERRQ(ierr); - ierr = MatSetFromOptions(J); - CHKERRQ(ierr); + if (user_precon) { + output_info.write("\tUsing user-supplied preconditioner\n"); + if (!hasPreconditioner()) { + throw BoutException("Model does not define a preconditioner"); + } + // Set a Shell (matrix-free) preconditioner type + PCSetType(pc, PCSHELL); - // Get nonzero pattern of J - color_none !!! - prealloc = cols * dof * dof; - ierr = MatSeqAIJSetPreallocation(J, prealloc, nullptr); - CHKERRQ(ierr); - ierr = MatMPIAIJSetPreallocation(J, prealloc, nullptr, prealloc, nullptr); - CHKERRQ(ierr); + // Specify the preconditioner function + PCShellSetApply(pc, snesPCapply); - // why nonzeros=295900, allocated nonzeros=2816000/12800000 (*dof*dof), number of mallocs used during MatSetValues calls =256? - prealloc = cols; - ierr = MatSeqBAIJSetPreallocation(J, dof, prealloc, nullptr); - CHKERRQ(ierr); - ierr = MatMPIBAIJSetPreallocation(J, dof, prealloc, nullptr, prealloc, nullptr); - CHKERRQ(ierr); -#if PETSC_VERSION_GE(3, 7, 0) - ierr = PetscOptionsHasName(nullptr, nullptr, "-J_slowfd", &J_slowfd); - CHKERRQ(ierr); -#else - ierr = PetscOptionsHasName(nullptr, "-J_slowfd", &J_slowfd); - CHKERRQ(ierr); -#endif - if (J_slowfd != 0U) { // create Jacobian matrix by slow fd - ierr = SNESSetJacobian(snes, J, J, SNESComputeJacobianDefault, nullptr); - CHKERRQ(ierr); - output_info << "SNESComputeJacobian J by slow fd...\n"; + // Context used to supply object pointer + PCShellSetContext(pc, this); -#if PETSC_VERSION_GE(3, 5, 0) - ierr = TSComputeRHSJacobian(ts, simtime, u, J, J); + // Set name of preconditioner + ierr = PCShellSetName(pc, "PhysicsPreconditioner"); CHKERRQ(ierr); -#else - MatStructure flg; - ierr = TSComputeRHSJacobian(ts, simtime, u, &J, &J, &flg); - CHKERRQ(ierr); -#endif - output_info << "compute J by slow fd is done.\n"; - } else { // get sparse pattern of the Jacobian - throw BoutException("Sorry, unimplemented way of setting PETSc preconditioner. " - "Either set a preconditioner function with 'setPrecon' " - "in your code, or load a matrix with '-Jload' on the " - "command line, or calculate with finite differences " - "with '-J_slowfd' (on command line)"); + } else { + // Can't use preconditioner because no Jacobian matrix available + PCSetType(pc, PCNONE); } - } - - // Create coloring context of J to be used during time stepping - output_info << " Create coloring ...\n"; + // Callback to get the shift parameter + // Use matrix free for both operator and preconditioner + TSSetIJacobian(ts, Jmf, Jmf, solver_ijacobian, this); - ISColoring iscoloring; -#if PETSC_VERSION_GE(3, 5, 0) - MatColoring coloring; - MatColoringCreate(Jmf, &coloring); - MatColoringSetType(coloring, MATCOLORINGSL); - MatColoringSetFromOptions(coloring); - // Calculate index sets - MatColoringApply(coloring, &iscoloring); - MatColoringDestroy(&coloring); -#else - ierr = MatGetColoring(J, MATCOLORINGSL, &iscoloring); - CHKERRQ(ierr); -#endif - ierr = MatFDColoringCreate(J, iscoloring, &matfdcoloring); - CHKERRQ(ierr); - - ierr = MatFDColoringSetFromOptions(matfdcoloring); - CHKERRQ(ierr); - ierr = ISColoringDestroy(&iscoloring); - CHKERRQ(ierr); - throw BoutException("Coloring is not working"); - ierr = SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, matfdcoloring); - CHKERRQ(ierr); - - // Write J in binary for study - see ~petsc/src/mat/examples/tests/ex124.c -#if PETSC_VERSION_GE(3, 7, 0) - ierr = PetscOptionsHasName(nullptr, nullptr, "-J_write", &J_write); - CHKERRQ(ierr); -#else - ierr = PetscOptionsHasName(nullptr, "-J_write", &J_write); - CHKERRQ(ierr); -#endif - if (J_write != 0U) { - PetscViewer viewer = nullptr; - output_info.write("\n[{:d}] Test TSComputeRHSJacobian() ...\n", rank); -#if PETSC_VERSION_GE(3, 5, 0) - ierr = TSComputeRHSJacobian(ts, simtime, u, J, J); - CHKERRQ(ierr); + } else { + // Set PC type from input + if (pc_type != "default") { + PCSetType(pc, pc_type.c_str()); + + if (pc_type == "hypre") { +#if PETSC_HAVE_HYPRE + // Set the type of hypre preconditioner + PCHYPRESetType(pc, pc_hypre_type.c_str()); #else - MatStructure J_structure; - ierr = TSComputeRHSJacobian(ts, simtime, u, &J, &J, &J_structure); - CHKERRQ(ierr); + throw BoutException("PETSc was not configured with Hypre."); #endif + } + } - output.write("[{:d}] TSComputeRHSJacobian is done\n", rank); + // Calculate a Jacobian matrix using finite differences. The finite + // difference Jacobian (Jfd) may be used for both operator and + // preconditioner or, if matrix_free_operator, in only the + // preconditioner. + + if (use_coloring) { + // Use matrix coloring. This greatly reduces the number of + // times the rhs() function needs to be evaluated when + // calculating the Jacobian, by identifying which quantities may + // be simultaneously perturbed. + + // Use global mesh for now + Mesh* mesh = bout::globals::mesh; + + ////////////////////////////////////////////////// + // Get the local indices by starting at 0 + Field3D index = globalIndex(0); + + ////////////////////////////////////////////////// + // Pre-allocate PETSc storage + + output_progress.write("Setting Jacobian matrix sizes\n"); + + const int n2d = f2d.size(); + const int n3d = f3d.size(); + + // Set size of Matrix on each processor to nlocal x nlocal + MatCreate(BoutComm::get(), &Jfd); + MatSetOption(Jfd, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE); + MatSetSizes(Jfd, nlocal, nlocal, PETSC_DETERMINE, PETSC_DETERMINE); + MatSetFromOptions(Jfd); + // Determine which row/columns of the matrix are locally owned + int Istart, Iend; + MatGetOwnershipRange(Jfd, &Istart, &Iend); + // Convert local into global indices + // Note: Not in the boundary cells, to keep -1 values + for (const auto& i : mesh->getRegion3D("RGN_NOBNDRY")) { + index[i] += Istart; + } + // Now communicate to fill guard cells + mesh->communicate(index); + + // Non-zero elements on this processor + std::vector d_nnz; + std::vector o_nnz; + auto n_square = (*options)["stencil:square"] + .doc("Extent of stencil (square)") + .withDefault(0); + auto n_taxi = (*options)["stencil:taxi"] + .doc("Extent of stencil (taxi-cab norm)") + .withDefault(0); + auto n_cross = (*options)["stencil:cross"] + .doc("Extent of stencil (cross)") + .withDefault(0); + // Set n_taxi 2 if nothing else is set + // Probably a better way to do this + if (n_square == 0 && n_taxi == 0 && n_cross == 0) { + output_info.write("Setting solver:stencil:taxi = 2\n"); + n_taxi = 2; + } + + auto const xy_offsets = ColoringStencil::getOffsets(n_square, n_taxi, n_cross); + { + // This is ugly but can't think of a better and robust way to + // count the non-zeros for some arbitrary stencil + // effectively the same loop as the one that sets the non-zeros below + std::vector> d_nnz_map2d(nlocal); + std::vector> o_nnz_map2d(nlocal); + std::vector> d_nnz_map3d(nlocal); + std::vector> o_nnz_map3d(nlocal); + // Loop over every element in 2D to count the *unique* non-zeros + for (int x = mesh->xstart; x <= mesh->xend; x++) { + for (int y = mesh->ystart; y <= mesh->yend; y++) { + + const int ind0 = ROUND(index(x, y, 0)) - Istart; + + // 2D fields + for (int i = 0; i < n2d; i++) { + const PetscInt row = ind0 + i; + // Loop through each point in the stencil + for (const auto& [x_off, y_off] : xy_offsets) { + const int xi = x + x_off; + const int yi = y + y_off; + if ((xi < 0) || (yi < 0) || (xi >= mesh->LocalNx) + || (yi >= mesh->LocalNy)) { + continue; + } + + const int ind2 = ROUND(index(xi, yi, 0)); + if (ind2 < 0) { + continue; // A boundary point + } + + // Depends on all variables on this cell + for (int j = 0; j < n2d; j++) { + const PetscInt col = ind2 + j; + if (col >= Istart && col < Iend) { + d_nnz_map2d[row].insert(col); + } else { + o_nnz_map2d[row].insert(col); + } + } + } + } + // 3D fields + for (int z = 0; z < mesh->LocalNz; z++) { + const int ind = ROUND(index(x, y, z)) - Istart; + + for (int i = 0; i < n3d; i++) { + PetscInt row = ind + i; + if (z == 0) { + row += n2d; + } + + // Depends on 2D fields + for (int j = 0; j < n2d; j++) { + const PetscInt col = ind0 + j; + if (col >= Istart && col < Iend) { + d_nnz_map2d[row].insert(col); + } else { + o_nnz_map2d[row].insert(col); + } + } + + // Star pattern + for (const auto& [x_off, y_off] : xy_offsets) { + const int xi = x + x_off; + const int yi = y + y_off; + + if ((xi < 0) || (yi < 0) || (xi >= mesh->LocalNx) + || (yi >= mesh->LocalNy)) { + continue; + } + + int ind2 = ROUND(index(xi, yi, 0)); + if (ind2 < 0) { + continue; // Boundary point + } + + if (z == 0) { + ind2 += n2d; + } + + // 3D fields on this cell + for (int j = 0; j < n3d; j++) { + const PetscInt col = ind2 + j; + if (col >= Istart && col < Iend) { + d_nnz_map3d[row].insert(col); + } else { + o_nnz_map3d[row].insert(col); + } + } + } + } + } + } + } + + d_nnz.reserve(nlocal); + d_nnz.reserve(nlocal); + + for (int i = 0; i < nlocal; ++i) { + // Assume all elements in the z direction are potentially coupled + d_nnz.emplace_back(d_nnz_map3d[i].size() * mesh->LocalNz + + d_nnz_map2d[i].size()); + o_nnz.emplace_back(o_nnz_map3d[i].size() * mesh->LocalNz + + o_nnz_map2d[i].size()); + } + } + + output_progress.write("Pre-allocating Jacobian\n"); + // Pre-allocate + MatMPIAIJSetPreallocation(Jfd, 0, d_nnz.data(), 0, o_nnz.data()); + MatSeqAIJSetPreallocation(Jfd, 0, d_nnz.data()); + MatSetUp(Jfd); + MatSetOption(Jfd, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); + + ////////////////////////////////////////////////// + // Mark non-zero entries + + output_progress.write("Marking non-zero Jacobian entries\n"); + PetscScalar val = 1.0; + for (int x = mesh->xstart; x <= mesh->xend; x++) { + for (int y = mesh->ystart; y <= mesh->yend; y++) { + + const int ind0 = ROUND(index(x, y, 0)); + + // 2D fields + for (int i = 0; i < n2d; i++) { + const PetscInt row = ind0 + i; + + // Loop through each point in the stencil + for (const auto& [x_off, y_off] : xy_offsets) { + const int xi = x + x_off; + const int yi = y + y_off; + if ((xi < 0) || (yi < 0) || (xi >= mesh->LocalNx) + || (yi >= mesh->LocalNy)) { + continue; + } + + int ind2 = ROUND(index(xi, yi, 0)); + if (ind2 < 0) { + continue; // A boundary point + } + + // Depends on all variables on this cell + for (int j = 0; j < n2d; j++) { + PetscInt col = ind2 + j; + ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); + CHKERRQ(ierr); + } + } + } + // 3D fields + for (int z = 0; z < mesh->LocalNz; z++) { + int ind = ROUND(index(x, y, z)); + + for (int i = 0; i < n3d; i++) { + PetscInt row = ind + i; + if (z == 0) { + row += n2d; + } + + // Depends on 2D fields + for (int j = 0; j < n2d; j++) { + PetscInt col = ind0 + j; + ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); + CHKERRQ(ierr); + } + + // Star pattern + for (const auto& [x_off, y_off] : xy_offsets) { + int xi = x + x_off; + int yi = y + y_off; + + if ((xi < 0) || (yi < 0) || (xi >= mesh->LocalNx) + || (yi >= mesh->LocalNy)) { + continue; + } + for (int zi = 0; zi < mesh->LocalNz; ++zi) { + int ind2 = ROUND(index(xi, yi, zi)); + if (ind2 < 0) { + continue; // Boundary point + } + + if (z == 0) { + ind2 += n2d; + } + + // 3D fields on this cell + for (int j = 0; j < n3d; j++) { + PetscInt col = ind2 + j; + ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); + + if (ierr != 0) { + output.write("ERROR: {} {} : ({}, {}) -> ({}, {}) : {} -> {}\n", + row, x, y, xi, yi, ind2, ind2 + n3d - 1); + } + CHKERRQ(ierr); + } + } + } + } + } + } + } + + // Finished marking non-zero entries + + output_progress.write("Assembling Jacobian matrix\n"); + + // Assemble Matrix + MatAssemblyBegin(Jfd, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(Jfd, MAT_FINAL_ASSEMBLY); + + { + // Test if the matrix is symmetric + // Values are 0 or 1 so tolerance (1e-5) shouldn't matter + PetscBool symmetric; + ierr = MatIsSymmetric(Jfd, 1e-5, &symmetric); + CHKERRQ(ierr); + if (!symmetric) { + output_warn.write("Jacobian pattern is not symmetric\n"); + } + } + + // The above can miss entries around the X-point branch cut: + // The diagonal terms are complicated because moving in X then Y + // is different from moving in Y then X at the X-point. + // Making sure the colouring matrix is symmetric does not + // necessarily give the correct stencil but may help. + if ((*options)["force_symmetric_coloring"] + .doc("Modifies coloring matrix to force it to be symmetric") + .withDefault(false)) { + Mat Jfd_T; + MatCreateTranspose(Jfd, &Jfd_T); + MatAXPY(Jfd, 1, Jfd_T, DIFFERENT_NONZERO_PATTERN); + } + + output_progress.write("Creating Jacobian coloring\n"); + updateColoring(); - if (J_slowfd != 0U) { - output_info.write("[{:d}] writing J in binary to data/Jrhs_dense.dat...\n", rank); - ierr = PetscViewerBinaryOpen(comm, "data/Jrhs_dense.dat", FILE_MODE_WRITE, &viewer); - CHKERRQ(ierr); } else { - output_info.write("[{:d}] writing J in binary to data/Jrhs_sparse.dat...\n", rank); - ierr = - PetscViewerBinaryOpen(comm, "data/Jrhs_sparse.dat", FILE_MODE_WRITE, &viewer); - CHKERRQ(ierr); + // Brute force calculation + // There is usually no reason to use this, except as a check of + // the coloring calculation. + + MatCreateAIJ( + BoutComm::get(), nlocal, nlocal, // Local sizes + PETSC_DETERMINE, PETSC_DETERMINE, // Global sizes + 3, // Number of nonzero entries in diagonal portion of local submatrix + nullptr, + 0, // Number of nonzeros per row in off-diagonal portion of local submatrix + nullptr, &Jfd); + + if (matrix_free_operator) { + SNESSetJacobian(snes, Jmf, Jfd, SNESComputeJacobianDefault, this); + } else { + SNESSetJacobian(snes, Jfd, Jfd, SNESComputeJacobianDefault, this); + } + + MatSetOption(Jfd, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); } - ierr = MatView(J, viewer); - CHKERRQ(ierr); - ierr = PetscViewerDestroy(&viewer); - CHKERRQ(ierr); } - ierr = PetscLogEventEnd(init_event, 0, 0, 0, 0); - CHKERRQ(ierr); - - PetscFunctionReturn(0); + // Get runtime options + lib.setOptionsFromInputFile(ts); + + { + // Some reporting + TSType tstype; + TSGetType(ts, &tstype); + output_info.write("TS Type : {}\n", tstype); + TSAdaptType adapttype; + TSAdaptGetType(adapt, &adapttype); + output_info.write("TS Adapt Type : {}\n", adapttype); + SNESType snestype; + SNESGetType(snes, &snestype); + output_info.write("SNES Type : {}\n", snestype); + KSPType ksptype; + KSPGetType(ksp, &ksptype); + if (ksptype) { + output_info.write("KSP Type : {}\n", ksptype); + } + PCType pctype; + PCGetType(pc, &pctype); + if (pctype) { + output_info.write("PC Type : {}\n", pctype); + } + } + return 0; } -/************************************************************************** - * Run - Advance time - **************************************************************************/ - +// Starts the time integrator PetscErrorCode PetscSolver::run() { - // Set when the next call to monitor is desired next_output = simtime + getOutputTimestep(); PetscFunctionBegin; - if (this->output_flag) { - prev_linear_its = 0; - bout_snes_time = bout::globals::mpi->MPI_Wtime(); - } - + // Run the PETSc time integrator + // The PetscMonitor function is responsible for regular outputs CHKERRQ(TSSolve(ts, u)); - // Gawd, everything is a hack - if ((this->output_flag != 0U) and (BoutComm::rank() == 0)) { - Output petsc_info(output_name); - // Don't write to stdout - petsc_info.disable(); - petsc_info.write("SNES Iteration, KSP Iterations, Wall Time, Norm\n"); - for (const auto& info : snes_list) { - petsc_info.write("{:d}, {:d}, {:e}, {:e}\n", info.it, info.linear_its, info.time, - info.norm); - } - } - PetscFunctionReturn(0); } -/************************************************************************** - * RHS function - **************************************************************************/ - -PetscErrorCode PetscSolver::rhs(TS UNUSED(ts), BoutReal t, Vec udata, Vec dudata) { +// Evaluate the user-supplied RHS function +// This method is called from the static PETSc callback functions +PetscErrorCode PetscSolver::rhs(BoutReal t, Vec udata, Vec dudata, bool linear) { TRACE("Running RHS: PetscSolver::rhs({:e})", t); - const BoutReal* udata_array; - BoutReal* dudata_array; + simtime = t; // This will be used in rhs_differencing PetscFunctionBegin; // Load state from PETSc + const BoutReal* udata_array; VecGetArrayRead(udata, &udata_array); load_vars(const_cast(udata_array)); VecRestoreArrayRead(udata, &udata_array); // Call RHS function - run_rhs(t); + run_rhs(t, linear); // Save derivatives to PETSc + BoutReal* dudata_array; VecGetArray(dudata, &dudata_array); save_derivs(dudata_array); VecRestoreArray(dudata, &dudata_array); @@ -623,19 +914,17 @@ PetscErrorCode PetscSolver::rhs(TS UNUSED(ts), BoutReal t, Vec udata, Vec dudata PetscFunctionReturn(0); } -/************************************************************************** - * Preconditioner function - **************************************************************************/ +// This is used for Jacobian-vector product and Jacobian coloring +PetscErrorCode PetscSolver::rhs_differencing(Vec globalin, Vec globalout) { + return rhs(simtime, globalin, globalout, true); +} -PetscErrorCode PetscSolver::pre(PC UNUSED(pc), Vec x, Vec y) { +// Matrix-free preconditioner function +PetscErrorCode PetscSolver::pre(Vec x, Vec y) { TRACE("PetscSolver::pre()"); BoutReal* data; - if (diagnose) { - output << "Preconditioning" << endl; - } - // Load state VecGetArray(state, &data); load_vars(data); @@ -654,355 +943,44 @@ PetscErrorCode PetscSolver::pre(PC UNUSED(pc), Vec x, Vec y) { save_derivs(data); VecRestoreArray(y, &data); - // Petsc's definition of Jacobian differs by a factor from Sundials' + // Petsc's definition of Jacobian differs by a factor from SUNDIALS' + // PETSc solves (scale + J)^-1 + // SUNDIALS solves (I + gamma J)^-1 PetscErrorCode ierr = VecScale(y, shift); CHKERRQ(ierr); return 0; } -/************************************************************************** - * User-supplied Jacobian function J(state) * x = y - **************************************************************************/ - -PetscErrorCode PetscSolver::jac(Vec x, Vec y) { - TRACE("PetscSolver::jac()"); - - BoutReal* data; - - if (diagnose) { - output << "Jacobian evaluation\n"; - } - - // Load state - VecGetArray(state, &data); - load_vars(data); - VecRestoreArray(state, &data); - - // Load vector to be operated on into F_vars - VecGetArray(x, &data); - load_derivs(data); - VecRestoreArray(x, &data); - - // Call the Jacobian function - runJacobian(ts_time); - - // Save the solution from time derivatives - VecGetArray(y, &data); - save_derivs(data); - VecRestoreArray(y, &data); - - // y = a * x - y - PetscErrorCode ierr = VecAXPBY(y, shift, -1.0, x); - CHKERRQ(ierr); - - return 0; -} - -/************************************************************************** - * Static functions which can be used for PETSc callbacks - **************************************************************************/ - -PetscErrorCode solver_f(TS ts, BoutReal t, Vec globalin, Vec globalout, void* f_data) { - PetscFunctionBegin; - auto* s = static_cast(f_data); - PetscLogEventBegin(s->solver_event, 0, 0, 0, 0); - s->rhs(ts, t, globalin, globalout); - PetscLogEventEnd(s->solver_event, 0, 0, 0, 0); - PetscFunctionReturn(0); -} - -/* - FormIFunction = Udot - RHSFunction -*/ -PetscErrorCode solver_if(TS ts, BoutReal t, Vec globalin, Vec globalindot, Vec globalout, - void* f_data) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = solver_f(ts, t, globalin, globalout, f_data); - CHKERRQ(ierr); - - ierr = VecAYPX(globalout, -1.0, globalindot); - CHKERRQ(ierr); // globalout = globalindot + (-1)globalout - PetscFunctionReturn(0); -} - -#if PETSC_VERSION_GE(3, 5, 0) -PetscErrorCode solver_rhsjacobian(TS UNUSED(ts), BoutReal UNUSED(t), Vec UNUSED(globalin), - Mat J, Mat Jpre, void* UNUSED(f_data)) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = MatAssemblyBegin(Jpre, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - ierr = MatAssemblyEnd(Jpre, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - if (J != Jpre) { - ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - } - PetscFunctionReturn(0); -} -#else -PetscErrorCode solver_rhsjacobian([[maybe_unused]] TS ts, [[maybe_unused]] BoutReal t, - [[maybe_unused]] Vec globalin, Mat* J, Mat* Jpre, - [[maybe_unused]] MatStructure* str, - [[maybe_unused]] void* f_data) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = MatAssemblyBegin(*Jpre, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - ierr = MatAssemblyEnd(*Jpre, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - if (*J != *Jpre) { - ierr = MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - ierr = MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY); - CHKERRQ(ierr); - } - PetscFunctionReturn(0); -} -#endif - -/* - solver_ijacobian - Compute IJacobian = dF/dU + a dF/dUdot - a dummy matrix used for pc=none -*/ -#if PETSC_VERSION_GE(3, 5, 0) -PetscErrorCode solver_ijacobian(TS ts, BoutReal t, Vec globalin, Vec UNUSED(globalindot), - PetscReal a, Mat J, Mat Jpre, void* f_data) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = solver_rhsjacobian(ts, t, globalin, J, Jpre, f_data); - CHKERRQ(ierr); - - ////// Save data for preconditioner - auto* solver = static_cast(f_data); - - if (solver->diagnose) { - output << "Saving state, t = " << t << ", a = " << a << endl; - } - - solver->shift = a; // Save the shift 'a' - solver->state = globalin; // Save system state - solver->ts_time = t; - - PetscFunctionReturn(0); -} -#else -PetscErrorCode solver_ijacobian(TS ts, BoutReal t, Vec globalin, - [[maybe_unused]] Vec globalindot, - [[maybe_unused]] PetscReal a, Mat* J, Mat* Jpre, - MatStructure* str, void* f_data) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = solver_rhsjacobian(ts, t, globalin, J, Jpre, str, (void*)f_data); - CHKERRQ(ierr); - - ////// Save data for preconditioner - PetscSolver* solver = (PetscSolver*)f_data; - - if (solver->diagnose) { - output << "Saving state, t = " << t << ", a = " << a << endl; - } - - solver->shift = a; // Save the shift 'a' - solver->state = globalin; // Save system state - solver->ts_time = t; - - PetscFunctionReturn(0); -} -#endif - -/* - solver_ijacobianfd - Compute IJacobian = dF/dU + a dF/dUdot using finite deference - not implemented yet -*/ -#if PETSC_VERSION_GE(3, 5, 0) -PetscErrorCode solver_ijacobianfd(TS ts, BoutReal t, Vec globalin, - Vec UNUSED(globalindot), PetscReal UNUSED(a), Mat J, - Mat Jpre, void* f_data) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = solver_rhsjacobian(ts, t, globalin, J, Jpre, f_data); - CHKERRQ(ierr); - //*Jpre + a - PetscFunctionReturn(0); -} -#else -PetscErrorCode solver_ijacobianfd(TS ts, BoutReal t, Vec globalin, Vec globalindot, - PetscReal a, Mat* J, Mat* Jpre, MatStructure* str, - void* f_data) { - PetscErrorCode ierr; - - PetscFunctionBegin; - ierr = solver_rhsjacobian(ts, t, globalin, J, Jpre, str, (void*)f_data); - CHKERRQ(ierr); - //*Jpre + a - PetscFunctionReturn(0); -} -#endif -//----------------------------------------- - -PetscErrorCode PhysicsSNESApply(SNES snes, Vec x) { - PetscErrorCode ierr; - Vec F, Fout; - PetscReal fnorm = 0., foutnorm = 0., dot = 0.; - KSP ksp; - PC pc; - Mat A, B; - - PetscFunctionBegin; - ierr = SNESGetJacobian(snes, &A, &B, nullptr, nullptr); - CHKERRQ(ierr); -#if PETSC_VERSION_GE(3, 5, 0) - ierr = SNESComputeJacobian(snes, x, A, B); - CHKERRQ(ierr); -#else - MatStructure diff = DIFFERENT_NONZERO_PATTERN; - ierr = SNESComputeJacobian(snes, x, &A, &B, &diff); - CHKERRQ(ierr); -#endif - ierr = SNESGetKSP(snes, &ksp); - CHKERRQ(ierr); - ierr = KSPGetPC(ksp, &pc); - CHKERRQ(ierr); - ierr = SNESGetFunction(snes, &F, nullptr, nullptr); - CHKERRQ(ierr); - ierr = SNESComputeFunction(snes, x, F); - CHKERRQ(ierr); - ierr = SNESGetSolutionUpdate(snes, &Fout); - CHKERRQ(ierr); - - ierr = PCApply(pc, F, Fout); - CHKERRQ(ierr); - ierr = VecNorm(Fout, NORM_2, &foutnorm); - CHKERRQ(ierr); - ierr = VecAXPY(x, -1., Fout); - CHKERRQ(ierr); - ierr = SNESComputeFunction(snes, x, F); - CHKERRQ(ierr); - ierr = VecNorm(F, NORM_2, &fnorm); - CHKERRQ(ierr); - ierr = VecDot(F, Fout, &dot); - CHKERRQ(ierr); - output_info << " (Debug) function norm: " << fnorm << ", P(f) norm " << foutnorm - << ", F \\cdot Fout " << dot << " "; -#if PETSC_VERSION_GE(3, 5, 0) - Vec func; - ierr = SNESGetFunction(snes, &func, nullptr, nullptr); - CHKERRQ(ierr); - ierr = VecNorm(func, NORM_2, &fnorm); - CHKERRQ(ierr); -#else - ierr = SNESSetFunctionNorm(snes, fnorm); - CHKERRQ(ierr); -#endif - ierr = SNESMonitor(snes, 0, fnorm); - CHKERRQ(ierr); - - PetscFunctionReturn(0); -} - -PetscErrorCode PhysicsPCApply(PC pc, Vec x, Vec y) { - int ierr; - - // Get the context - PetscSolver* s; - ierr = PCShellGetContext(pc, reinterpret_cast(&s)); - CHKERRQ(ierr); - - PetscFunctionReturn(s->pre(pc, x, y)); -} - -PetscErrorCode PhysicsJacobianApply(Mat J, Vec x, Vec y) { - // Get the context - PetscSolver* s; - int ierr = MatShellGetContext(J, reinterpret_cast(&s)); - CHKERRQ(ierr); - PetscFunctionReturn(s->jac(x, y)); -} - -PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, void* ctx) { - PetscErrorCode ierr; - auto* s = static_cast(ctx); - PetscReal tfinal, dt; - Vec interpolatedX; - const PetscScalar* x; - static int i = 0; - - PetscFunctionBegin; - ierr = TSGetTimeStep(ts, &dt); - CHKERRQ(ierr); - -#if PETSC_VERSION_GE(3, 8, 0) - ierr = TSGetMaxTime(ts, &tfinal); - CHKERRQ(ierr); -#else - ierr = TSGetDuration(ts, nullptr, &tfinal); - CHKERRQ(ierr); -#endif - - /* Duplicate the solution vector X into a work vector */ - ierr = VecDuplicate(X, &interpolatedX); - CHKERRQ(ierr); - while (s->next_output <= t && s->next_output <= tfinal) { - if (s->interpolate) { - ierr = TSInterpolate(ts, s->next_output, interpolatedX); - CHKERRQ(ierr); - } - - /* Place the interpolated values into the global variables */ - ierr = VecGetArrayRead(interpolatedX, &x); - CHKERRQ(ierr); - s->load_vars(const_cast(x)); - ierr = VecRestoreArrayRead(interpolatedX, &x); - CHKERRQ(ierr); - - if (s->call_monitors(simtime, i++, s->getNumberOutputSteps())) { - PetscFunctionReturn(1); - } - - s->next_output += s->getOutputTimestep(); - simtime = s->next_output; - } - - /* Done with vector, so destroy it */ - ierr = VecDestroy(&interpolatedX); - CHKERRQ(ierr); - - PetscFunctionReturn(0); -} - -PetscErrorCode PetscSNESMonitor(SNES snes, PetscInt its, PetscReal norm, void* ctx) { - PetscErrorCode ierr; - PetscInt linear_its = 0; - BoutReal tmp = .0; - snes_info row; - auto* s = static_cast(ctx); +void PetscSolver::updateColoring() { + // Re-calculate the coloring + MatColoring coloring = NULL; + MatColoringCreate(Jfd, &coloring); + MatColoringSetType(coloring, MATCOLORINGGREEDY); + MatColoringSetFromOptions(coloring); - PetscFunctionBegin; + // Calculate new index sets + ISColoring iscoloring = NULL; + MatColoringApply(coloring, &iscoloring); + MatColoringDestroy(&coloring); - if (!its) { - s->prev_linear_its = 0; + // Replace the old coloring with the new one + MatFDColoringDestroy(&fdcoloring); + MatFDColoringCreate(Jfd, iscoloring, &fdcoloring); + MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(solver_rhs_coloring), + this); + MatFDColoringSetFromOptions(fdcoloring); + MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); + ISColoringDestroy(&iscoloring); + + // Replace the CTX pointer in SNES Jacobian + // Note: TSComputeIJacobianDefaultColor + if (matrix_free_operator) { + // Use matrix-free calculation for operator, finite difference for preconditioner + SNESSetJacobian(snes, Jmf, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); + } else { + SNESSetJacobian(snes, Jfd, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); } - ierr = SNESGetLinearSolveIterations(snes, &linear_its); - CHKERRQ(ierr); - tmp = bout::globals::mpi->MPI_Wtime(); - - row.it = its; - s->prev_linear_its = row.linear_its = linear_its - s->prev_linear_its; - row.time = tmp - s->bout_snes_time; - row.norm = norm; - - s->snes_list.push_back(row); - - PetscFunctionReturn(0); } #endif diff --git a/src/solver/impls/petsc/petsc.hxx b/src/solver/impls/petsc/petsc.hxx index 686a7c6242..71a09ab61d 100644 --- a/src/solver/impls/petsc/petsc.hxx +++ b/src/solver/impls/petsc/petsc.hxx @@ -1,11 +1,10 @@ /************************************************************************** * Interface to PETSc solver - * NOTE: This class needs tidying, generalising to use FieldData interface * ************************************************************************** - * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu + * Copyright 2010 - 2025 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -55,35 +54,6 @@ namespace { RegisterSolver registersolverpetsc("petsc"); } -using BoutReal = PetscScalar; -#define OPT_SIZE 40 - -using rhsfunc = int (*)(BoutReal); - -extern BoutReal simtime; - -/// Monitor function called on every internal timestep -extern PetscErrorCode PetscMonitor(TS, PetscInt, PetscReal, Vec, void* ctx); -/// Monitor function for SNES -extern PetscErrorCode PetscSNESMonitor(SNES, PetscInt, PetscReal, void* ctx); - -/// Compute IJacobian = dF/dU + a dF/dUdot - a dummy matrix used for pc=none -#if PETSC_VERSION_GE(3, 5, 0) -extern PetscErrorCode solver_ijacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, - void*); -#else -extern PetscErrorCode solver_ijacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat*, Mat*, - MatStructure*, void*); -#endif - -/// Data for SNES -struct snes_info { - PetscInt it; - PetscInt linear_its; - PetscReal time; - PetscReal norm; -}; - class PetscSolver : public Solver { public: PetscSolver(Options* opts = nullptr); @@ -95,24 +65,17 @@ public: // These functions used internally (but need to be public) /// Wrapper for the RHS function - PetscErrorCode rhs(TS ts, PetscReal t, Vec globalin, Vec globalout); + PetscErrorCode rhs(PetscReal t, Vec globalin, Vec globalout, bool linear); + /// RHS function for differencing + PetscErrorCode rhs_differencing(Vec globalin, Vec globalout); /// Wrapper for the preconditioner - PetscErrorCode pre(PC pc, Vec x, Vec y); - /// Wrapper for the Jacobian function - PetscErrorCode jac(Vec x, Vec y); + PetscErrorCode pre(Vec x, Vec y); // Call back functions that need to access internal state friend PetscErrorCode PetscMonitor(TS, PetscInt, PetscReal, Vec, void* ctx); - friend PetscErrorCode PetscSNESMonitor(SNES, PetscInt, PetscReal, void* ctx); -#if PETSC_VERSION_GE(3, 5, 0) - friend PetscErrorCode solver_ijacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, - void*); -#else - friend PetscErrorCode solver_ijacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat*, Mat*, - MatStructure*, void*); -#endif - PetscLogEvent solver_event, loop_event, init_event; + friend PetscErrorCode solver_ijacobian(TS, BoutReal, Vec, Vec, PetscReal shift, Mat J, + Mat Jpre, void* ctx); private: BoutReal shift; ///< Shift (alpha) parameter from TS @@ -121,28 +84,45 @@ private: PetscLib lib; ///< Handles initialising, finalising PETSc - Vec u{nullptr}; ///< PETSc solution vector - TS ts{nullptr}; ///< PETSc timestepper object - Mat J{nullptr}; ///< RHS Jacobian - Mat Jmf{nullptr}; - MatFDColoring matfdcoloring{nullptr}; - - bool diagnose; ///< If true, print some information about current stage + Vec u{nullptr}; ///< PETSc solution vector + TS ts{nullptr}; ///< PETSc timestepper object + SNES snes{nullptr}; ///< PETSc nonlinear solver object + KSP ksp{nullptr}; ///< PETSc linear solver + Mat Jmf{nullptr}; ///< Matrix Free Jacobian + Mat Jfd{nullptr}; ///< Finite Difference Jacobian + MatFDColoring fdcoloring{nullptr}; ///< Matrix coloring context BoutReal next_output; ///< When the monitor should be called next PetscBool interpolate{PETSC_TRUE}; ///< Whether to interpolate or not - char output_name[PETSC_MAX_PATH_LEN]; - PetscBool output_flag{PETSC_FALSE}; - PetscInt prev_linear_its; - BoutReal bout_snes_time{0.0}; - std::vector snes_list; + bool diagnose; ///< If true, print some information about current stage + bool user_precon; ///< Use user-supplied preconditioning function? + + BoutReal atol; ///< Absolute tolerance + BoutReal rtol; ///< Relative tolerance + BoutReal stol; ///< Convergence tolerance + + int maxnl; ///< Maximum nonlinear iterations per SNES solve + int maxf; ///< Maximum number of function evaluations allowed in the solver (default: 10000) + int maxl; ///< Maximum linear iterations + + std::string ts_type; ///< PETSc TS time solver type + std::string adapt_type; ///< TSAdaptType timestep adaptation + std::string snes_type; ///< PETSc SNES nonlinear solver type + std::string ksp_type; ///< PETSc KSP linear solver type + std::string pc_type; ///< Preconditioner type + std::string pc_hypre_type; ///< Hypre preconditioner type + std::string line_search_type; ///< Line search type + + bool matrix_free; ///< Use matrix free Jacobian + bool matrix_free_operator; ///< Use matrix free Jacobian in the operator? + int lag_jacobian; ///< Re-use Jacobian + bool use_coloring; ///< Use matrix coloring + void updateColoring(); ///< Updates the coloring using Jfd + + bool kspsetinitialguessnonzero; ///< Set initial guess to non-zero - bool adaptive; ///< Use adaptive timestepping - bool use_precon, use_jacobian; - BoutReal abstol, reltol; - bool adams_moulton; BoutReal start_timestep; int mxstep; }; From 46f7344592dcd9ceab4ac6d94093c95ec7b1aece Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 21:56:16 -0700 Subject: [PATCH 120/259] petsc solver fixes - Read `interpolate` option, allowing solution interpolation to be disabled for TS methods that don't support it (e.g. `pseudo`). - Fix coloring method: The TS function should be used for coloring, not the RHS function directly. This is because SNES is solving a modified function that depends on the time step and TS method. --- src/solver/impls/petsc/petsc.cxx | 55 +++++++++++++------------------- src/solver/impls/petsc/petsc.hxx | 4 +-- 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 22d8594c28..fce7f1178f 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -104,25 +104,6 @@ static PetscErrorCode solver_rhs(TS UNUSED(ts), BoutReal t, Vec globalin, Vec gl PetscFunctionReturn(0); } -// PETSc callback function for finite differencing. -// May use a linearised form of the RHS function. -static PetscErrorCode solver_rhs_differencing(void* ctx, Vec globalin, Vec globalout) { - PetscFunctionBegin; - auto* s = static_cast(ctx); - s->rhs_differencing(globalin, globalout); - PetscFunctionReturn(0); -} - -// PETSc callback function for coloring. -// May use a linearised form of the RHS function. -static PetscErrorCode solver_rhs_coloring(void* UNUSED(snes), Vec globalin, Vec globalout, - void* ctx) { - PetscFunctionBegin; - auto* s = static_cast(ctx); - s->rhs_differencing(globalin, globalout); - PetscFunctionReturn(0); -} - // Compute IJacobian = dF/dU + a dF/dUdot // This is a dummy matrix that saves the shift. // The shift is later used in the matrix-free preconditioner @@ -172,9 +153,14 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo // The internal timestepper may have stepped over multiple output times while (s->next_output <= t && s->next_output <= tfinal) { + BoutReal output_time = t; if (s->interpolate) { ierr = TSInterpolate(ts, s->next_output, interpolatedX); - CHKERRQ(ierr); + if (ierr != PETSC_SUCCESS) { + throw BoutException("This PETSc TS does not support interpolation. Use a " + "different method or set solver:interpolate=false"); + } + output_time = s->next_output; } // Place the interpolated values into the global variables @@ -185,11 +171,11 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo ierr = VecRestoreArrayRead(interpolatedX, &x); CHKERRQ(ierr); - if (s->call_monitors(s->next_output, i++, s->getNumberOutputSteps())) { + if (s->call_monitors(output_time, i++, s->getNumberOutputSteps())) { PetscFunctionReturn(1); } - s->next_output += s->getOutputTimestep(); + s->next_output = output_time + s->getOutputTimestep(); } // Done with vector, so destroy it @@ -200,7 +186,9 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo } PetscSolver::PetscSolver(Options* opts) - : Solver(opts), + : Solver(opts), interpolate((*options)["interpolate"] + .doc("Interpolate to regular output times?") + .withDefault(true)), diagnose( (*options)["diagnose"].doc("Enable some diagnostic output").withDefault(false)), user_precon((*options)["user_precon"] @@ -379,7 +367,11 @@ int PetscSolver::init() { // Allow TS to step over the final time // Note: This does not affect intermediate outputs, that // are always interpolated (in PetscMonitor) - ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_INTERPOLATE); + if (interpolate) { + ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_INTERPOLATE); + } else { + ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP); + } CHKERRQ(ierr); ierr = TSMonitorSet(ts, PetscMonitor, this, nullptr); @@ -892,7 +884,7 @@ PetscErrorCode PetscSolver::run() { PetscErrorCode PetscSolver::rhs(BoutReal t, Vec udata, Vec dudata, bool linear) { TRACE("Running RHS: PetscSolver::rhs({:e})", t); - simtime = t; // This will be used in rhs_differencing + simtime = t; PetscFunctionBegin; @@ -914,11 +906,6 @@ PetscErrorCode PetscSolver::rhs(BoutReal t, Vec udata, Vec dudata, bool linear) PetscFunctionReturn(0); } -// This is used for Jacobian-vector product and Jacobian coloring -PetscErrorCode PetscSolver::rhs_differencing(Vec globalin, Vec globalout) { - return rhs(simtime, globalin, globalout, true); -} - // Matrix-free preconditioner function PetscErrorCode PetscSolver::pre(Vec x, Vec y) { TRACE("PetscSolver::pre()"); @@ -967,14 +954,16 @@ void PetscSolver::updateColoring() { // Replace the old coloring with the new one MatFDColoringDestroy(&fdcoloring); MatFDColoringCreate(Jfd, iscoloring, &fdcoloring); - MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(solver_rhs_coloring), - this); + // Use the SNES function that is defined by the TS method + // SNESTSFormFunction is defined in PETSc ts.c + // The ctx pointer should be the TS object + MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(SNESTSFormFunction), + ts); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); // Replace the CTX pointer in SNES Jacobian - // Note: TSComputeIJacobianDefaultColor if (matrix_free_operator) { // Use matrix-free calculation for operator, finite difference for preconditioner SNESSetJacobian(snes, Jmf, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); diff --git a/src/solver/impls/petsc/petsc.hxx b/src/solver/impls/petsc/petsc.hxx index 71a09ab61d..5108e8cb30 100644 --- a/src/solver/impls/petsc/petsc.hxx +++ b/src/solver/impls/petsc/petsc.hxx @@ -66,8 +66,6 @@ public: /// Wrapper for the RHS function PetscErrorCode rhs(PetscReal t, Vec globalin, Vec globalout, bool linear); - /// RHS function for differencing - PetscErrorCode rhs_differencing(Vec globalin, Vec globalout); /// Wrapper for the preconditioner PetscErrorCode pre(Vec x, Vec y); @@ -94,7 +92,7 @@ private: BoutReal next_output; ///< When the monitor should be called next - PetscBool interpolate{PETSC_TRUE}; ///< Whether to interpolate or not + bool interpolate; ///< Interpolate to regular times? bool diagnose; ///< If true, print some information about current stage bool user_precon; ///< Use user-supplied preconditioning function? From e4fe421de08e597ff0db426839d5b394247c1425 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 22:31:31 -0700 Subject: [PATCH 121/259] petsc solver: Recover from SNES failures Uses TSSetMaxSNESFailures, that can be overridden with a petsc option. --- src/solver/impls/petsc/petsc.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index fce7f1178f..a6971c7270 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -361,6 +361,9 @@ int PetscSolver::init() { CHKERRQ(ierr); #endif + // Allow TS to recover from SNES failures + PetscCall(TSSetMaxSNESFailures(ts, PETSC_UNLIMITED)); + // Set the current solution ierr = TSSetSolution(ts, u); CHKERRQ(ierr); From 3f67ac9ac22ee0c8b0a13ace14e98720d586d1f0 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 22:34:24 -0700 Subject: [PATCH 122/259] petsc: Tidying with PetscCall Replaces CHKERRQ macro call with a wrapper around the PETSc function call. --- src/solver/impls/petsc/petsc.cxx | 59 +++++++++++--------------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index a6971c7270..126aa46532 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -283,48 +283,35 @@ int PetscSolver::init() { // Create a vector to contain the state PetscCall(VecCreate(BoutComm::get(), &u)); - ierr = VecSetSizes(u, nlocal, PETSC_DECIDE); - CHKERRQ(ierr); - ierr = VecSetFromOptions(u); - CHKERRQ(ierr); + PetscCall(VecSetSizes(u, nlocal, PETSC_DECIDE)); + PetscCall(VecSetFromOptions(u)); // Save initial state to PETSc Vec BoutReal* udata; // Pointer to data array in vector u. - ierr = VecGetArray(u, &udata); - CHKERRQ(ierr); + PetscCall(VecGetArray(u, &udata)); save_vars(udata); - ierr = VecRestoreArray(u, &udata); - CHKERRQ(ierr); + PetscCall(VecRestoreArray(u, &udata)); // Create timestepper - ierr = TSCreate(BoutComm::get(), &ts); - CHKERRQ(ierr); - ierr = TSSetProblemType(ts, TS_NONLINEAR); - CHKERRQ(ierr); - ierr = TSSetType(ts, ts_type.c_str()); - CHKERRQ(ierr); - ierr = TSSetApplicationContext(ts, this); - CHKERRQ(ierr); + PetscCall(TSCreate(BoutComm::get(), &ts)); + PetscCall(TSSetProblemType(ts, TS_NONLINEAR)); + PetscCall(TSSetType(ts, ts_type.c_str())); + PetscCall(TSSetApplicationContext(ts, this)); // Set user provided RHSFunction // Need to duplicate the solution vector for the residual Vec rhs_vec; - ierr = VecDuplicate(u, &rhs_vec); - CHKERRQ(ierr); - ierr = TSSetRHSFunction(ts, rhs_vec, solver_rhs, this); - CHKERRQ(ierr); + PetscCall(VecDuplicate(u, &rhs_vec)); + PetscCall(TSSetRHSFunction(ts, rhs_vec, solver_rhs, this)); // Set up adaptive time-stepping TSAdapt adapt; - ierr = TSGetAdapt(ts, &adapt); - CHKERRQ(ierr); - ierr = TSAdaptSetType(adapt, adapt_type.c_str()); - CHKERRQ(ierr); + PetscCall(TSGetAdapt(ts, &adapt)); + PetscCall(TSAdaptSetType(adapt, adapt_type.c_str())); // Set default absolute/relative tolerances // Note: Vector atol and rtol not given - ierr = TSSetTolerances(ts, atol, nullptr, rtol, nullptr); - CHKERRQ(ierr); + PetscCall(TSSetTolerances(ts, atol, nullptr, rtol, nullptr)); if (ts_type == TSSUNDIALS) { #if PETSC_HAS_SUNDIALS // The PETSc interface to SUNDIALS' CVODE @@ -337,12 +324,10 @@ int PetscSolver::init() { } // Initial time of the simulation state - ierr = TSSetTime(ts, simtime); - CHKERRQ(ierr); + PetscCall(TSSetTime(ts, simtime)); next_output = simtime; - ierr = TSSetTimeStep(ts, start_timestep); - CHKERRQ(ierr); + PetscCall(TSSetTimeStep(ts, start_timestep)); // Total number of steps PetscInt total_steps = mxstep * getNumberOutputSteps(); @@ -352,21 +337,17 @@ int PetscSolver::init() { simtime); #if PETSC_VERSION_GE(3, 8, 0) - ierr = TSSetMaxSteps(ts, total_steps); - CHKERRQ(ierr); - ierr = TSSetMaxTime(ts, tfinal); - CHKERRQ(ierr); + PetscCall(TSSetMaxSteps(ts, total_steps)); + PetscCall(TSSetMaxTime(ts, tfinal)); #else - ierr = TSSetDuration(ts, total_steps, tfinal); - CHKERRQ(ierr); + PetscCall(TSSetDuration(ts, total_steps, tfinal)); #endif // Allow TS to recover from SNES failures PetscCall(TSSetMaxSNESFailures(ts, PETSC_UNLIMITED)); // Set the current solution - ierr = TSSetSolution(ts, u); - CHKERRQ(ierr); + PetscCall(TSSetSolution(ts, u)); // Allow TS to step over the final time // Note: This does not affect intermediate outputs, that // are always interpolated (in PetscMonitor) @@ -376,7 +357,7 @@ int PetscSolver::init() { ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP); } CHKERRQ(ierr); - ierr = TSMonitorSet(ts, PetscMonitor, this, nullptr); + PetscCall(TSMonitorSet(ts, PetscMonitor, this, nullptr)); if (ts_type != TSSUNDIALS) { // Get and configure the SNES nonlinear solver From 1aca504e46980c59d3ff77eeac4c2f13253eb90d Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 23:01:53 -0700 Subject: [PATCH 123/259] petsc solver improvements - Allow Jacobian and preconditioner to persist across SNES solves. This is useful because many steps can typically be taken using the same preconditioner. - Allow solver to recover from time step rejections by setting TSSetMaxStepRejections. This doesn't seem to work as expected with the `pseudo` TS method. --- src/solver/impls/petsc/petsc.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 126aa46532..6154cf39cd 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -346,6 +346,9 @@ int PetscSolver::init() { // Allow TS to recover from SNES failures PetscCall(TSSetMaxSNESFailures(ts, PETSC_UNLIMITED)); + // Recover from step rejections + PetscCall(TSSetMaxStepRejections(ts, PETSC_UNLIMITED)); + // Set the current solution PetscCall(TSSetSolution(ts, u)); // Allow TS to step over the final time @@ -395,9 +398,9 @@ int PetscSolver::init() { // Note: If the 'Amat' Jacobian is matrix free, SNESComputeJacobian // always updates its reference 'u' vector every nonlinear iteration SNESSetLagJacobian(snes, lag_jacobian); - SNESSetLagJacobianPersists(snes, PETSC_FALSE); + SNESSetLagJacobianPersists(snes, PETSC_TRUE); - SNESSetLagPreconditionerPersists(snes, PETSC_FALSE); + SNESSetLagPreconditionerPersists(snes, PETSC_TRUE); SNESSetLagPreconditioner(snes, 1); // Rebuild when Jacobian is rebuilt // Get and configure the KSP linear solver From e9025eed5a8e9f91d52795f232bb3483e9894320 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 14 Aug 2025 23:23:48 -0700 Subject: [PATCH 124/259] petsc: Add petsc headers and define PETSC_UNLIMITED Introduced in PETSc 3.22 (probably), define PETSC_UNLIMITED if it's undefined. Include more headers for used PETSc functionality. --- src/solver/impls/petsc/petsc.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 6154cf39cd..7c09b7d2a4 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -43,8 +43,15 @@ #include +#include "petscsys.h" +#include "petscts.h" #include "petscsnes.h" +#ifndef PETSC_UNLIMITED +// Introduced in PETSc 3.22 +#define PETSC_UNLIMITED -3 +#endif + class ColoringStencil { private: bool static isInSquare(int const i, int const j, int const n_square) { From 672172c7c7e72cb524b368d76519830e0954baf5 Mon Sep 17 00:00:00 2001 From: bendudson <219233+bendudson@users.noreply.github.com> Date: Fri, 15 Aug 2025 06:29:07 +0000 Subject: [PATCH 125/259] Apply clang-format changes --- src/solver/impls/petsc/petsc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 7c09b7d2a4..051d6d3ee1 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -43,9 +43,9 @@ #include +#include "petscsnes.h" #include "petscsys.h" #include "petscts.h" -#include "petscsnes.h" #ifndef PETSC_UNLIMITED // Introduced in PETSc 3.22 From a0b6cca1ace1b45ce48bb60566ad7336ddc86cee Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 08:19:54 -0700 Subject: [PATCH 126/259] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/solver/impls/petsc/petsc.cxx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 051d6d3ee1..55dd948b8a 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -49,7 +49,7 @@ #ifndef PETSC_UNLIMITED // Introduced in PETSc 3.22 -#define PETSC_UNLIMITED -3 +#define PETSC_UNLIMITED (-3) #endif class ColoringStencil { @@ -94,7 +94,7 @@ class ColoringStencil { // PETSc callback function for matrix-free preconditioner static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { // Get the context - void* ctx; + void* ctx = nullptr; int ierr = PCShellGetContext(pc, &ctx); CHKERRQ(ierr); // Run the preconditioner @@ -178,7 +178,7 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo ierr = VecRestoreArrayRead(interpolatedX, &x); CHKERRQ(ierr); - if (s->call_monitors(output_time, i++, s->getNumberOutputSteps())) { + if (s->call_monitors(output_time, i++, s->getNumberOutputSteps()) != 0) { PetscFunctionReturn(1); } @@ -669,9 +669,9 @@ int PetscSolver::init() { for (int i = 0; i < nlocal; ++i) { // Assume all elements in the z direction are potentially coupled - d_nnz.emplace_back(d_nnz_map3d[i].size() * mesh->LocalNz + d_nnz.emplace_back((d_nnz_map3d[i].size() * mesh->LocalNz) + d_nnz_map2d[i].size()); - o_nnz.emplace_back(o_nnz_map3d[i].size() * mesh->LocalNz + o_nnz.emplace_back((o_nnz_map3d[i].size() * mesh->LocalNz) + o_nnz_map2d[i].size()); } } @@ -687,7 +687,7 @@ int PetscSolver::init() { // Mark non-zero entries output_progress.write("Marking non-zero Jacobian entries\n"); - PetscScalar val = 1.0; + PetscScalar const val = 1.0; for (int x = mesh->xstart; x <= mesh->xend; x++) { for (int y = mesh->ystart; y <= mesh->yend; y++) { @@ -706,14 +706,14 @@ int PetscSolver::init() { continue; } - int ind2 = ROUND(index(xi, yi, 0)); + int const ind2 = ROUND(index(xi, yi, 0)); if (ind2 < 0) { continue; // A boundary point } // Depends on all variables on this cell for (int j = 0; j < n2d; j++) { - PetscInt col = ind2 + j; + PetscInt const col = ind2 + j; ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); CHKERRQ(ierr); } @@ -721,7 +721,7 @@ int PetscSolver::init() { } // 3D fields for (int z = 0; z < mesh->LocalNz; z++) { - int ind = ROUND(index(x, y, z)); + int const ind = ROUND(index(x, y, z)); for (int i = 0; i < n3d; i++) { PetscInt row = ind + i; @@ -731,7 +731,7 @@ int PetscSolver::init() { // Depends on 2D fields for (int j = 0; j < n2d; j++) { - PetscInt col = ind0 + j; + PetscInt const col = ind0 + j; ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); CHKERRQ(ierr); } From dbff5bfc9009d939cf1a34bae5da1be64d3bae4e Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 12:24:12 -0700 Subject: [PATCH 127/259] petsc solver: Runs with SUNDIALS, some tidying Runs SUNDIALS through PETSc, but preconditioning slows down the simulation. Something wrong with the Jacobian calculation perhaps. Some tidying, adding header files etc., to address Clang Tidy comments. --- src/solver/impls/petsc/petsc.cxx | 122 +++++++++++++++---------------- src/solver/impls/petsc/petsc.hxx | 1 + 2 files changed, 59 insertions(+), 64 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 55dd948b8a..df559af5bd 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -25,27 +25,30 @@ #include "bout/build_defines.hxx" -#include "petsc.hxx" - #if BOUT_HAS_PETSC -#include +#include "petsc.hxx" + +#include +#include +#include +#include +#include #include #include #include #include +#include #include #include -#include -#include - -#include - -#include "petscsnes.h" -#include "petscsys.h" -#include "petscts.h" +#include +#include +#include +#include +#include +#include #ifndef PETSC_UNLIMITED // Introduced in PETSc 3.22 @@ -95,8 +98,7 @@ class ColoringStencil { static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { // Get the context void* ctx = nullptr; - int ierr = PCShellGetContext(pc, &ctx); - CHKERRQ(ierr); + PetscCall(PCShellGetContext(pc, &ctx)); // Run the preconditioner PetscFunctionReturn(static_cast(ctx)->pre(x, y)); } @@ -141,28 +143,24 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo PetscFunctionReturn(0); } - PetscErrorCode ierr; PetscReal tfinal; static int i = 0; #if PETSC_VERSION_GE(3, 8, 0) - ierr = TSGetMaxTime(ts, &tfinal); - CHKERRQ(ierr); + PetscCall(TSGetMaxTime(ts, &tfinal)); #else - ierr = TSGetDuration(ts, nullptr, &tfinal); - CHKERRQ(ierr); + PetscCall(TSGetDuration(ts, nullptr, &tfinal)); #endif // Duplicate the solution vector X into a work vector Vec interpolatedX; - ierr = VecDuplicate(X, &interpolatedX); - CHKERRQ(ierr); + PetscCall(VecDuplicate(X, &interpolatedX)); // The internal timestepper may have stepped over multiple output times while (s->next_output <= t && s->next_output <= tfinal) { BoutReal output_time = t; if (s->interpolate) { - ierr = TSInterpolate(ts, s->next_output, interpolatedX); + int ierr = TSInterpolate(ts, s->next_output, interpolatedX); if (ierr != PETSC_SUCCESS) { throw BoutException("This PETSc TS does not support interpolation. Use a " "different method or set solver:interpolate=false"); @@ -172,11 +170,9 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo // Place the interpolated values into the global variables const PetscScalar* x; - ierr = VecGetArrayRead(interpolatedX, &x); - CHKERRQ(ierr); + PetscCall(VecGetArrayRead(interpolatedX, &x)); s->load_vars(const_cast(x)); - ierr = VecRestoreArrayRead(interpolatedX, &x); - CHKERRQ(ierr); + PetscCall(VecRestoreArrayRead(interpolatedX, &x)); if (s->call_monitors(output_time, i++, s->getNumberOutputSteps()) != 0) { PetscFunctionReturn(1); @@ -186,8 +182,7 @@ PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, vo } // Done with vector, so destroy it - ierr = VecDestroy(&interpolatedX); - CHKERRQ(ierr); + PetscCall(VecDestroy(&interpolatedX)); PetscFunctionReturn(0); } @@ -214,8 +209,7 @@ PetscSolver::PetscSolver(Options* opts) .doc("Maximum number of function evaluations per SNES solve") .withDefault(10000)), maxl((*options)["maxl"].doc("Maximum number of linear iterations").withDefault(20)), - ts_type( - (*options)["ts_type"].doc("PETSc time integrator type").withDefault("beuler")), + ts_type((*options)["ts_type"].doc("PETSc time integrator type").withDefault("bdf")), adapt_type((*options)["adapt_type"] .doc("PETSc TSAdaptType timestep adaptation method") .withDefault("basic")), @@ -270,7 +264,6 @@ PetscSolver::~PetscSolver() { **************************************************************************/ int PetscSolver::init() { - PetscErrorCode ierr; TRACE("Initialising PETSc-dev solver"); @@ -320,7 +313,7 @@ int PetscSolver::init() { // Note: Vector atol and rtol not given PetscCall(TSSetTolerances(ts, atol, nullptr, rtol, nullptr)); if (ts_type == TSSUNDIALS) { -#if PETSC_HAS_SUNDIALS +#if PETSC_HAVE_SUNDIALS2 // The PETSc interface to SUNDIALS' CVODE TSSundialsSetType(ts, SUNDIALS_BDF); TSSundialsSetTolerance(ts, atol, rtol); @@ -362,11 +355,10 @@ int PetscSolver::init() { // Note: This does not affect intermediate outputs, that // are always interpolated (in PetscMonitor) if (interpolate) { - ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_INTERPOLATE); + PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_INTERPOLATE)); } else { - ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP); + PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP)); } - CHKERRQ(ierr); PetscCall(TSMonitorSet(ts, PetscMonitor, this, nullptr)); if (ts_type != TSSUNDIALS) { @@ -374,11 +366,8 @@ int PetscSolver::init() { // Note: SUNDIALS does not use PETSc SNES or KSP // https://petsc.org/release/manual/ts/#using-sundials-from-petsc - ierr = TSGetSNES(ts, &snes); - CHKERRQ(ierr); - - ierr = SNESSetType(snes, snes_type.c_str()); - CHKERRQ(ierr); + PetscCall(TSGetSNES(ts, &snes)); + PetscCall(SNESSetType(snes, snes_type.c_str())); // Line search if (line_search_type != "default") { @@ -455,7 +444,7 @@ int PetscSolver::init() { // Configure preconditioner PC pc; if (ts_type == TSSUNDIALS) { -#if PETSC_HAS_SUNDIALS +#if PETSC_HAVE_SUNDIALS2 TSSundialsGetPC(ts, &pc); #endif } else { @@ -480,8 +469,7 @@ int PetscSolver::init() { PCShellSetContext(pc, this); // Set name of preconditioner - ierr = PCShellSetName(pc, "PhysicsPreconditioner"); - CHKERRQ(ierr); + PetscCall(PCShellSetName(pc, "PhysicsPreconditioner")); } else { // Can't use preconditioner because no Jacobian matrix available PCSetType(pc, PCNONE); @@ -714,8 +702,7 @@ int PetscSolver::init() { // Depends on all variables on this cell for (int j = 0; j < n2d; j++) { PetscInt const col = ind2 + j; - ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); - CHKERRQ(ierr); + PetscCall(MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES)); } } } @@ -732,8 +719,7 @@ int PetscSolver::init() { // Depends on 2D fields for (int j = 0; j < n2d; j++) { PetscInt const col = ind0 + j; - ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); - CHKERRQ(ierr); + PetscCall(MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES)); } // Star pattern @@ -758,7 +744,7 @@ int PetscSolver::init() { // 3D fields on this cell for (int j = 0; j < n3d; j++) { PetscInt col = ind2 + j; - ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); + int ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); if (ierr != 0) { output.write("ERROR: {} {} : ({}, {}) -> ({}, {}) : {} -> {}\n", @@ -785,8 +771,7 @@ int PetscSolver::init() { // Test if the matrix is symmetric // Values are 0 or 1 so tolerance (1e-5) shouldn't matter PetscBool symmetric; - ierr = MatIsSymmetric(Jfd, 1e-5, &symmetric); - CHKERRQ(ierr); + PetscCall(MatIsSymmetric(Jfd, 1e-5, &symmetric)); if (!symmetric) { output_warn.write("Jacobian pattern is not symmetric\n"); } @@ -842,13 +827,15 @@ int PetscSolver::init() { TSAdaptType adapttype; TSAdaptGetType(adapt, &adapttype); output_info.write("TS Adapt Type : {}\n", adapttype); - SNESType snestype; - SNESGetType(snes, &snestype); - output_info.write("SNES Type : {}\n", snestype); - KSPType ksptype; - KSPGetType(ksp, &ksptype); - if (ksptype) { - output_info.write("KSP Type : {}\n", ksptype); + if (ts_type != TSSUNDIALS) { + SNESType snestype; + SNESGetType(snes, &snestype); + output_info.write("SNES Type : {}\n", snestype); + KSPType ksptype; + KSPGetType(ksp, &ksptype); + if (ksptype) { + output_info.write("KSP Type : {}\n", ksptype); + } } PCType pctype; PCGetType(pc, &pctype); @@ -927,8 +914,7 @@ PetscErrorCode PetscSolver::pre(Vec x, Vec y) { // Petsc's definition of Jacobian differs by a factor from SUNDIALS' // PETSc solves (scale + J)^-1 // SUNDIALS solves (I + gamma J)^-1 - PetscErrorCode ierr = VecScale(y, shift); - CHKERRQ(ierr); + PetscCall(VecScale(y, shift)); return 0; } @@ -951,18 +937,26 @@ void PetscSolver::updateColoring() { // Use the SNES function that is defined by the TS method // SNESTSFormFunction is defined in PETSc ts.c // The ctx pointer should be the TS object - MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(SNESTSFormFunction), - ts); + MatFDColoringSetFunction(fdcoloring, + reinterpret_cast(SNESTSFormFunction), ts); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); // Replace the CTX pointer in SNES Jacobian - if (matrix_free_operator) { - // Use matrix-free calculation for operator, finite difference for preconditioner - SNESSetJacobian(snes, Jmf, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); + if (ts_type == TSSUNDIALS) { +#if PETSC_HAVE_SUNDIALS2 + // The SUNDIALS interface calls TSGetIJacobian + // https://www.mcs.anl.gov/petsc/petsc-3.14/src/ts/impls/implicit/sundials/sundials.c + TSSetIJacobian(ts, Jfd, Jfd, solver_ijacobian, this); +#endif } else { - SNESSetJacobian(snes, Jfd, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); + if (matrix_free_operator) { + // Use matrix-free calculation for operator, finite difference for preconditioner + SNESSetJacobian(snes, Jmf, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); + } else { + SNESSetJacobian(snes, Jfd, Jfd, SNESComputeJacobianDefaultColor, fdcoloring); + } } } diff --git a/src/solver/impls/petsc/petsc.hxx b/src/solver/impls/petsc/petsc.hxx index 5108e8cb30..525ca93b40 100644 --- a/src/solver/impls/petsc/petsc.hxx +++ b/src/solver/impls/petsc/petsc.hxx @@ -47,6 +47,7 @@ class PetscSolver; #include #include +#include #include From 720dd2ef2f70e61b23cc540e0ecaf4bf8512feef Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 14:44:29 -0700 Subject: [PATCH 128/259] petsc solver: Fix Jacobian coloring with sundials method This is fiddly because TS doesn't create a SNES object when TSType is TSSUNDIALS. The nonlinear function being solved in sundials is similar to the PETSc convention, but scaled by the "gamma" / shift factor. --- src/solver/impls/petsc/petsc.cxx | 56 +++++++++++++++++++++++++++----- src/solver/impls/petsc/petsc.hxx | 7 ++++ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index df559af5bd..551552a9b4 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -94,8 +94,9 @@ class ColoringStencil { } }; +namespace { // PETSc callback function for matrix-free preconditioner -static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { +PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { // Get the context void* ctx = nullptr; PetscCall(PCShellGetContext(pc, &ctx)); @@ -105,14 +106,25 @@ static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { // PETSc callback function, that evaluates the nonlinear // function being integrated by TS. -static PetscErrorCode solver_rhs(TS UNUSED(ts), BoutReal t, Vec globalin, Vec globalout, - void* f_data) { +PetscErrorCode solver_rhs(TS UNUSED(ts), BoutReal t, Vec globalin, Vec globalout, + void* f_data) { PetscFunctionBegin; auto* s = static_cast(f_data); s->rhs(t, globalin, globalout, false); PetscFunctionReturn(0); } +// Form function for use with SUNDIALS. +// This is needed because SNESTSFormFunction is not available +// PETSc error: No method snesfunction for TS of type sundials +PetscErrorCode solver_form_function(void* UNUSED(dummy), Vec U, Vec F, void* f_data) { + PetscFunctionBegin; + auto* s = static_cast(f_data); + s->formFunction(U, F); + PetscFunctionReturn(0); +} +} // namespace + // Compute IJacobian = dF/dU + a dF/dUdot // This is a dummy matrix that saves the shift. // The shift is later used in the matrix-free preconditioner @@ -131,6 +143,14 @@ PetscErrorCode solver_ijacobian(TS, BoutReal, Vec, Vec, PetscReal shift, Mat J, PetscFunctionReturn(0); } +PetscErrorCode solver_ijacobian_color(TS ts, PetscReal t, Vec U, Vec Udot, + PetscReal shift, Mat J, Mat B, void* ctx) { + auto* solver = static_cast(ctx); + solver->shift = shift; + + return TSComputeIJacobianDefaultColor(ts, t, U, Udot, shift, J, B, NULL); +} + // This function is called by the TS object every internal timestep // It is responsible for triggering interpolation and output at // the output time interval. @@ -887,6 +907,15 @@ PetscErrorCode PetscSolver::rhs(BoutReal t, Vec udata, Vec dudata, bool linear) PetscFunctionReturn(0); } +PetscErrorCode PetscSolver::formFunction(Vec U, Vec F) { + PetscFunctionBegin; + PetscCall(rhs(simtime, U, F, true)); // Can be linearised for coloring + + // shift * U - dU/dt + PetscCall(VecAXPBY(F, shift, -1.0, U)); + PetscFunctionReturn(0); +} + // Matrix-free preconditioner function PetscErrorCode PetscSolver::pre(Vec x, Vec y) { TRACE("PetscSolver::pre()"); @@ -934,11 +963,17 @@ void PetscSolver::updateColoring() { // Replace the old coloring with the new one MatFDColoringDestroy(&fdcoloring); MatFDColoringCreate(Jfd, iscoloring, &fdcoloring); - // Use the SNES function that is defined by the TS method - // SNESTSFormFunction is defined in PETSc ts.c - // The ctx pointer should be the TS object - MatFDColoringSetFunction(fdcoloring, - reinterpret_cast(SNESTSFormFunction), ts); + if (ts_type != TSSUNDIALS) { + // Use the SNES function that is defined by the TS method + // SNESTSFormFunction is defined in PETSc ts.c + // The ctx pointer should be the TS object + MatFDColoringSetFunction(fdcoloring, + reinterpret_cast(SNESTSFormFunction), ts); + } else { + // SNESTSFormFunction is not available for SUNDIALS + MatFDColoringSetFunction( + fdcoloring, reinterpret_cast(solver_form_function), this); + } MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); @@ -948,7 +983,10 @@ void PetscSolver::updateColoring() { #if PETSC_HAVE_SUNDIALS2 // The SUNDIALS interface calls TSGetIJacobian // https://www.mcs.anl.gov/petsc/petsc-3.14/src/ts/impls/implicit/sundials/sundials.c - TSSetIJacobian(ts, Jfd, Jfd, solver_ijacobian, this); + // This sets the "TSMatFDColoring" property on the Jacobian, that is used in TSComputeIJacobianDefaultColor + PetscObjectCompose((PetscObject)Jfd, "TSMatFDColoring", (PetscObject)fdcoloring); + // Call a wrapper function that stores the shift in the PetscSolver + TSSetIJacobian(ts, Jfd, Jfd, solver_ijacobian_color, this); #endif } else { if (matrix_free_operator) { diff --git a/src/solver/impls/petsc/petsc.hxx b/src/solver/impls/petsc/petsc.hxx index 525ca93b40..a9b41333f7 100644 --- a/src/solver/impls/petsc/petsc.hxx +++ b/src/solver/impls/petsc/petsc.hxx @@ -67,6 +67,8 @@ public: /// Wrapper for the RHS function PetscErrorCode rhs(PetscReal t, Vec globalin, Vec globalout, bool linear); + /// Residual calculation. + PetscErrorCode formFunction(Vec U, Vec F); /// Wrapper for the preconditioner PetscErrorCode pre(Vec x, Vec y); @@ -76,6 +78,11 @@ public: friend PetscErrorCode solver_ijacobian(TS, BoutReal, Vec, Vec, PetscReal shift, Mat J, Mat Jpre, void* ctx); + // Wrapper around TSComputeIJacobianDefaultColor that saves the shift + // This is used to compute the Jacobian using coloring with SUNDIALS TS method. + friend PetscErrorCode solver_ijacobian_color(TS ts, PetscReal t, Vec U, Vec Udot, + PetscReal shift, Mat J, Mat B, void* ctx); + private: BoutReal shift; ///< Shift (alpha) parameter from TS Vec state; From 1e18bf23b15a93e9ec9a67b921582715bb72a469 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 15:14:05 -0700 Subject: [PATCH 129/259] petsc: Use C-style cast for MatFDColoringFn The function signature seems to vary between PETSc versions in ways that break `reinterpret_cast` (and `bout::cast_MatFDColoringFn` in `include/bout/petsc_interface.hxx`). --- src/solver/impls/petsc/petsc.cxx | 18 ++++++++++++------ src/solver/impls/petsc/petsc.hxx | 3 +++ src/sys/petsclib.cxx | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 551552a9b4..ce33bc232c 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -294,7 +295,8 @@ int PetscSolver::init() { // Get total problem size int neq; if (bout::globals::mpi->MPI_Allreduce(&nlocal, &neq, 1, MPI_INT, MPI_SUM, - BoutComm::get())) { + BoutComm::get()) + != 0) { throw BoutException("MPI_Allreduce failed!"); } @@ -967,12 +969,16 @@ void PetscSolver::updateColoring() { // Use the SNES function that is defined by the TS method // SNESTSFormFunction is defined in PETSc ts.c // The ctx pointer should be the TS object - MatFDColoringSetFunction(fdcoloring, - reinterpret_cast(SNESTSFormFunction), ts); + // + // Note: The cast is horrible but the function signature + // varies between PETSc versions in ways that break + // reinterpret_cast. + MatFDColoringSetFunction(fdcoloring, (MatFDColoringFn)SNESTSFormFunction, ts); } else { - // SNESTSFormFunction is not available for SUNDIALS - MatFDColoringSetFunction( - fdcoloring, reinterpret_cast(solver_form_function), this); + // SNESTSFormFunction is not available for SUNDIALS. + // This solver_form_function needs to know the shift + // (SUNDIALS' gamma) that we capture in solver_ijacobian_color. + MatFDColoringSetFunction(fdcoloring, (MatFDColoringFn)solver_form_function, this); } MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); diff --git a/src/solver/impls/petsc/petsc.hxx b/src/solver/impls/petsc/petsc.hxx index a9b41333f7..b7857c7afd 100644 --- a/src/solver/impls/petsc/petsc.hxx +++ b/src/solver/impls/petsc/petsc.hxx @@ -47,6 +47,9 @@ class PetscSolver; #include #include +#include +#include +#include #include #include diff --git a/src/sys/petsclib.cxx b/src/sys/petsclib.cxx index 1830db89d9..bae53a8c7a 100644 --- a/src/sys/petsclib.cxx +++ b/src/sys/petsclib.cxx @@ -15,6 +15,7 @@ #include #include #include +#include #include #include From ca355a8a0393fc0b7f56aeb47c9a34ca17642ae6 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 15:44:40 -0700 Subject: [PATCH 130/259] petsc: Cast coloring function to void This regrettable necessity follows the PETSc examples. Function pointers are cast to `PetscErrorCode (*)(void)`, which means that any future change to the signature will not be caught but will give undefined behavior. May future maintainers forgive me. Some drive-by tidying to appease Clang-tidy. --- include/bout/petsclib.hxx | 1 + src/solver/impls/petsc/petsc.cxx | 25 +++++++++++++++++-------- src/solver/impls/petsc/petsc.hxx | 4 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/bout/petsclib.hxx b/include/bout/petsclib.hxx index 760b18ff91..41d7618fd2 100644 --- a/include/bout/petsclib.hxx +++ b/include/bout/petsclib.hxx @@ -60,6 +60,7 @@ class Options; #define PETSC_HAVE_BROKEN_RECURSIVE_MACRO #include // IWYU pragma: export +#include #include #include "bout/boutexception.hxx" diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index ce33bc232c..abd4fbf64b 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -35,19 +35,25 @@ #include #include +#include #include #include #include #include #include #include +#include +#include #include #include +#include +#include #include -#include +#include #include #include +#include #include #include @@ -149,7 +155,7 @@ PetscErrorCode solver_ijacobian_color(TS ts, PetscReal t, Vec U, Vec Udot, auto* solver = static_cast(ctx); solver->shift = shift; - return TSComputeIJacobianDefaultColor(ts, t, U, Udot, shift, J, B, NULL); + return TSComputeIJacobianDefaultColor(ts, t, U, Udot, shift, J, B, nullptr); } // This function is called by the TS object every internal timestep @@ -765,7 +771,7 @@ int PetscSolver::init() { // 3D fields on this cell for (int j = 0; j < n3d; j++) { - PetscInt col = ind2 + j; + PetscInt const col = ind2 + j; int ierr = MatSetValues(Jfd, 1, &row, 1, &col, &val, INSERT_VALUES); if (ierr != 0) { @@ -952,13 +958,13 @@ PetscErrorCode PetscSolver::pre(Vec x, Vec y) { void PetscSolver::updateColoring() { // Re-calculate the coloring - MatColoring coloring = NULL; + MatColoring coloring{nullptr}; MatColoringCreate(Jfd, &coloring); MatColoringSetType(coloring, MATCOLORINGGREEDY); MatColoringSetFromOptions(coloring); // Calculate new index sets - ISColoring iscoloring = NULL; + ISColoring iscoloring{nullptr}; MatColoringApply(coloring, &iscoloring); MatColoringDestroy(&coloring); @@ -972,13 +978,16 @@ void PetscSolver::updateColoring() { // // Note: The cast is horrible but the function signature // varies between PETSc versions in ways that break - // reinterpret_cast. - MatFDColoringSetFunction(fdcoloring, (MatFDColoringFn)SNESTSFormFunction, ts); + // reinterpret_cast and a C cast to MatFDColoringFn. + // This is the cast that PETSc examples use. + MatFDColoringSetFunction(fdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, + ts); } else { // SNESTSFormFunction is not available for SUNDIALS. // This solver_form_function needs to know the shift // (SUNDIALS' gamma) that we capture in solver_ijacobian_color. - MatFDColoringSetFunction(fdcoloring, (MatFDColoringFn)solver_form_function, this); + MatFDColoringSetFunction(fdcoloring, (PetscErrorCode (*)(void))solver_form_function, + this); } MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); diff --git a/src/solver/impls/petsc/petsc.hxx b/src/solver/impls/petsc/petsc.hxx index b7857c7afd..78f7d1a1e4 100644 --- a/src/solver/impls/petsc/petsc.hxx +++ b/src/solver/impls/petsc/petsc.hxx @@ -48,7 +48,7 @@ class PetscSolver; #include #include -#include +#include #include #include @@ -69,7 +69,7 @@ public: // These functions used internally (but need to be public) /// Wrapper for the RHS function - PetscErrorCode rhs(PetscReal t, Vec globalin, Vec globalout, bool linear); + PetscErrorCode rhs(BoutReal t, Vec udata, Vec dudata, bool linear); /// Residual calculation. PetscErrorCode formFunction(Vec U, Vec F); /// Wrapper for the preconditioner From f9179676563ea24ad7b963ca6a7e589a5dc3164f Mon Sep 17 00:00:00 2001 From: bendudson <219233+bendudson@users.noreply.github.com> Date: Fri, 15 Aug 2025 22:50:57 +0000 Subject: [PATCH 131/259] Apply clang-format changes --- src/solver/impls/petsc/petsc.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index abd4fbf64b..c0e3094481 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -980,13 +980,12 @@ void PetscSolver::updateColoring() { // varies between PETSc versions in ways that break // reinterpret_cast and a C cast to MatFDColoringFn. // This is the cast that PETSc examples use. - MatFDColoringSetFunction(fdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, - ts); + MatFDColoringSetFunction(fdcoloring, (PetscErrorCode(*)(void))SNESTSFormFunction, ts); } else { // SNESTSFormFunction is not available for SUNDIALS. // This solver_form_function needs to know the shift // (SUNDIALS' gamma) that we capture in solver_ijacobian_color. - MatFDColoringSetFunction(fdcoloring, (PetscErrorCode (*)(void))solver_form_function, + MatFDColoringSetFunction(fdcoloring, (PetscErrorCode(*)(void))solver_form_function, this); } MatFDColoringSetFromOptions(fdcoloring); From 3da7deacd60d3595a231255a775fb4b0e9c97b8b Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 16:19:03 -0700 Subject: [PATCH 132/259] Try bout::cast_MatFDColoringFn Getting MatFDColoringSetFunction to work across PETSc versions seems to be unreasonably difficult. --- src/solver/impls/petsc/petsc.cxx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index c0e3094481..ed48d87312 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -976,16 +976,14 @@ void PetscSolver::updateColoring() { // SNESTSFormFunction is defined in PETSc ts.c // The ctx pointer should be the TS object // - // Note: The cast is horrible but the function signature - // varies between PETSc versions in ways that break - // reinterpret_cast and a C cast to MatFDColoringFn. - // This is the cast that PETSc examples use. - MatFDColoringSetFunction(fdcoloring, (PetscErrorCode(*)(void))SNESTSFormFunction, ts); + // Note: The function type casting here is horrible but necessary + MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(SNESTSFormFunction), + ts); } else { // SNESTSFormFunction is not available for SUNDIALS. // This solver_form_function needs to know the shift // (SUNDIALS' gamma) that we capture in solver_ijacobian_color. - MatFDColoringSetFunction(fdcoloring, (PetscErrorCode(*)(void))solver_form_function, + MatFDColoringSetFunction(fdcoloring, bout::cast_MatFDColoringFn(solver_form_function), this); } MatFDColoringSetFromOptions(fdcoloring); From 64dd70e48adea2399c98cd1066bb9f4d7c92f386 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 17:58:11 -0700 Subject: [PATCH 133/259] petsc: More function casting I put on my robe and wizard hat... --- include/bout/petsc_interface.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index 90dd188d8a..5c4f5ed0e8 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -573,7 +573,7 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { namespace bout { template constexpr auto cast_MatFDColoringFn(T func) { - return func; + return reinterpret_cast(func); // NOLINT(*-reinterpret-cast) } } // namespace bout #else From 0413697ab87423a750a42bd109838092891c71b0 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 19:36:29 -0700 Subject: [PATCH 134/259] petsc: Yet more function casting --- include/bout/petsc_interface.hxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx index 5c4f5ed0e8..3ae02f41a6 100644 --- a/include/bout/petsc_interface.hxx +++ b/include/bout/petsc_interface.hxx @@ -6,9 +6,9 @@ * up a linear system. * ************************************************************************** - * Copyright 2019 C. MacMackin + * Copyright 2019 - 2025 BOUT++ contributors * - * Contact: Ben Dudson, bd512@york.ac.uk + * Contact: Ben Dudson, dudson2@llnl.gov * * This file is part of BOUT++. * @@ -573,7 +573,7 @@ PetscVector operator*(const PetscMatrix& mat, const PetscVector& vec) { namespace bout { template constexpr auto cast_MatFDColoringFn(T func) { - return reinterpret_cast(func); // NOLINT(*-reinterpret-cast) + return reinterpret_cast(func); // NOLINT(*-reinterpret-cast) } } // namespace bout #else From 56ad5e52dafaf1302a7b268b3d7cce7d122afc02 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 15 Aug 2025 20:11:30 -0700 Subject: [PATCH 135/259] petsc: Tighten tolerance in test-solver Tests pass with beuler/bdf/cn ts_types if tolerance is sufficiently tight. --- tests/integrated/test-solver/test_solver.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integrated/test-solver/test_solver.cxx b/tests/integrated/test-solver/test_solver.cxx index 2e4345c8cc..a24db71750 100644 --- a/tests/integrated/test-solver/test_solver.cxx +++ b/tests/integrated/test-solver/test_solver.cxx @@ -100,8 +100,7 @@ int main(int argc, char** argv) { root["imexbdf2"]["adaptive"] = true; root["imexbdf2"]["adaptRtol"] = 1.e-5; - root["petsc"]["nout"] = 10000; - root["petsc"]["output_step"] = end / 10000; + root["petsc"]["rtol"] = 1e-7; root["snes"]["adaptive"] = true; From e105d03ef166b179461545acd96f01ce78217ce9 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 18 Aug 2025 11:42:00 +0200 Subject: [PATCH 136/259] Do not automatically apply parallel BCs They might be wrong, introducing bugs. It is better to require it being explicitly. --- src/field/field3d.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 2cd8ee18b1..f3ece1a64e 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -404,9 +404,6 @@ Field3DParallel& Field3DParallel::operator=(const BoutReal val) { Field3D& Field3D::calcParallelSlices() { ASSERT2(allowCalcParallelSlices); getCoordinates()->getParallelTransform().calcParallelSlices(*this); - if (this->isFci()) { - this->applyParallelBoundaryWithDefault("parallel_neumann_o2"); - } return *this; } From fa51a14ab48f5c5650268dc150a39dd65680e858 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 09:53:50 +0200 Subject: [PATCH 137/259] Add default argument like for Field3D Otherwise `Field3DParallel(0.0)` fails, as it constructs a `Field3D` without parallel slices, and then fails as that cannot be converted to a `Field3DParallel` --- include/bout/field3d.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index ee958b21cd..b6d9bd53e6 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -750,7 +750,7 @@ public: : Field3D(std::move(data), localmesh, location, directions_in) { ensureFieldAligned(); } - Field3DParallel(BoutReal, Mesh*); + Field3DParallel(BoutReal, Mesh* mesh = nullptr); Field3D& asField3D() { return *this; } const Field3D& asField3D() const { return *this; } From f18392df94cc70896dd520c79bc17d256d8914fc Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 09:54:08 +0200 Subject: [PATCH 138/259] Add missing functions --- include/bout/field3d.hxx | 5 + src/field/gen_fieldops.py | 2 +- src/field/generated_fieldops.cxx | 241 +++++++++++++++++++++++++++++++ 3 files changed, 247 insertions(+), 1 deletion(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index b6d9bd53e6..b80b56a3cc 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -602,6 +602,11 @@ Field3DParallel operator-(BoutReal lhs, const Field3DParallel& rhs); Field3DParallel operator*(BoutReal lhs, const Field3DParallel& rhs); Field3DParallel operator/(BoutReal lhs, const Field3DParallel& rhs); +Field3DParallel operator+(const Field3DParallel& lhs, BoutReal rhs); +Field3DParallel operator-(const Field3DParallel& lhs, BoutReal rhs); +Field3DParallel operator*(const Field3DParallel& lhs, BoutReal rhs); +Field3DParallel operator/(const Field3DParallel& lhs, BoutReal rhs); + /*! * Unary minus. Returns the negative of given field, * iterates over whole domain including guard/boundary cells. diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 839b75dcdf..e38ea2eafc 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -270,7 +270,7 @@ def returnType(f1, f2): done = [(boutreal, boutreal)] for lhs, rhs in itertools.chain( itertools.product(fields, fields), - itertools.product((field3D, field3DPar, boutreal), (field3D, field3DPar)), + itertools.product(fields2, fields2), ): if (lhs, rhs) in done: continue diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 53db167571..ec9b966467 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -2886,6 +2886,247 @@ Field3DParallel& Field3DParallel::operator-=(const Field3DParallel& rhs) { return *this; } +// Provide the C++ wrapper for multiplication of Field3DParallel and BoutReal +Field3DParallel operator*(const Field3DParallel& lhs, const BoutReal rhs) { + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getRegionID()); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) * rhs; + result.ydown(i) = lhs.ydown(i) * rhs; + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] * rhs; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} * {:s}", lhs.name, "BR"); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by multiplication with BoutReal +Field3DParallel& Field3DParallel::operator*=(const BoutReal rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) *= rhs; + ydown(i) *= rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] *= rhs; } + + track(rhs, "operator*="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} *= {:s}", this->name, "BR"); +#endif + + checkData(*this); + + } else { + track(rhs, "operator*="); + (*this) = (*this) * rhs; + } + return *this; +} + +// Provide the C++ wrapper for division of Field3DParallel and BoutReal +Field3DParallel operator/(const Field3DParallel& lhs, const BoutReal rhs) { + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getRegionID()); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) / rhs; + result.ydown(i) = lhs.ydown(i) / rhs; + } + } + + const auto tmp = 1.0 / rhs; + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] * tmp; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} / {:s}", lhs.name, "BR"); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by division with BoutReal +Field3DParallel& Field3DParallel::operator/=(const BoutReal rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) /= rhs; + ydown(i) /= rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] /= rhs; } + + track(rhs, "operator/="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} /= {:s}", this->name, "BR"); +#endif + + checkData(*this); + + } else { + track(rhs, "operator/="); + (*this) = (*this) / rhs; + } + return *this; +} + +// Provide the C++ wrapper for addition of Field3DParallel and BoutReal +Field3DParallel operator+(const Field3DParallel& lhs, const BoutReal rhs) { + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getRegionID()); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) + rhs; + result.ydown(i) = lhs.ydown(i) + rhs; + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] + rhs; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} + {:s}", lhs.name, "BR"); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by addition with BoutReal +Field3DParallel& Field3DParallel::operator+=(const BoutReal rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) += rhs; + ydown(i) += rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] += rhs; } + + track(rhs, "operator+="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} += {:s}", this->name, "BR"); +#endif + + checkData(*this); + + } else { + track(rhs, "operator+="); + (*this) = (*this) + rhs; + } + return *this; +} + +// Provide the C++ wrapper for subtraction of Field3DParallel and BoutReal +Field3DParallel operator-(const Field3DParallel& lhs, const BoutReal rhs) { + + Field3DParallel result{emptyFrom(lhs)}; + checkData(lhs); + checkData(rhs); + + result.setRegion(lhs.getRegionID()); + if (lhs.isFci()) { + result.splitParallelSlices(); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { + result.yup(i) = lhs.yup(i) - rhs; + result.ydown(i) = lhs.ydown(i) - rhs; + } + } + + BOUT_FOR(index, result.getValidRegionWithDefault("RGN_ALL")) { + result[index] = lhs[index] - rhs; + } + +#if BOUT_USE_TRACK + result.name = fmt::format("{:s} - {:s}", lhs.name, "BR"); +#endif + checkData(result); + return result; +} + +// Provide the C++ operator to update Field3DParallel by subtraction with BoutReal +Field3DParallel& Field3DParallel::operator-=(const BoutReal rhs) { + // only if data is unique we update the field + // otherwise just call the non-inplace version + if (data.unique()) { + + if (this->isFci()) { + for (size_t i{0}; i < yup_fields.size(); ++i) { + yup(i) -= rhs; + ydown(i) -= rhs; + } + } else { + clearParallelSlices(); + } + checkData(*this); + checkData(rhs); + + BOUT_FOR(index, this->getRegion("RGN_ALL")) { (*this)[index] -= rhs; } + + track(rhs, "operator-="); +#if BOUT_USE_TRACK + name = fmt::format("{:s} -= {:s}", this->name, "BR"); +#endif + + checkData(*this); + + } else { + track(rhs, "operator-="); + (*this) = (*this) - rhs; + } + return *this; +} + // Provide the C++ wrapper for multiplication of BoutReal and Field3DParallel Field3DParallel operator*(const BoutReal lhs, const Field3DParallel& rhs) { From d915bfb261323d70908dfc9557c9bf12fabd1856 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 09:54:42 +0200 Subject: [PATCH 139/259] Ensure assignment to a Field3DParallel does not fail --- src/field/field3d.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index f3ece1a64e..6fd5efb670 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -385,7 +385,9 @@ Field3DParallel& Field3DParallel::operator=(const BoutReal val) { track(val, "operator="); if (isFci()) { - ASSERT2(hasParallelSlices()); + if (!hasParallelSlices()) { + splitParallelSlices(); + } for (size_t i = 0; i < numberParallelSlices(); ++i) { yup(i) = val; ydown(i) = val; From a5c36b1623acb9682e1bd1bbac993a89ec1b3caf Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 09:55:57 +0200 Subject: [PATCH 140/259] set parallel Bxy consistent with J and g_22 --- src/mesh/parallel/fci.cxx | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 0a231de6cd..0fcb379b9a 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -59,6 +59,19 @@ std::string parallel_slice_field_name(std::string field, int offset) { }; #if BOUT_USE_METRIC_3D +void set_parallel_metric_component(std::string name, Field3D& component, int offset, + Field3D& data) { + if (!component.hasParallelSlices()) { + component.splitParallelSlices(); + component.allowCalcParallelSlices = false; + } + auto& pcom = component.ynext(offset); + pcom.allocate(); + pcom.setRegion(fmt::format("RGN_YPAR_{:+d}", offset)); + pcom.name = name; + BOUT_FOR(i, component.getRegion("RGN_NOBNDRY")) { pcom[i.yp(offset)] = data[i]; } +} + bool load_parallel_metric_component(std::string name, Field3D& component, int offset, bool doZero) { Mesh* mesh = component.getMesh(); @@ -90,15 +103,7 @@ bool load_parallel_metric_component(std::string name, Field3D& component, int of } tmp = lmin; } - if (!component.hasParallelSlices()) { - component.splitParallelSlices(); - component.allowCalcParallelSlices = false; - } - auto& pcom = component.ynext(offset); - pcom.allocate(); - pcom.setRegion(fmt::format("RGN_YPAR_{:+d}", offset)); - pcom.name = name; - BOUT_FOR(i, component.getRegion("RGN_NOBNDRY")) { pcom[i.yp(offset)] = tmp[i]; } + set_parallel_metric_component(name, component, offset, tmp); return isValid; } #endif @@ -143,6 +148,18 @@ void load_parallel_metric_components([[maybe_unused]] Coordinates* coords, auto& pcom = coords->J.ynext(offset); BOUT_FOR(i, J.getRegion(rgn)) { pcom[i] = J[i]; } } + if (coords->Bxy.getMesh()->sourceHasVar(parallel_slice_field_name("Bxy", 1))) { + LOAD_PAR(Bxy, true); + } else { + Field3D tmp{coords->Bxy.getMesh()}; + tmp.allocate(); + BOUT_FOR(iyp, coords->Bxy.getRegion("RGN_NOBNDRY")) { + const auto i = iyp.ym(offset); + tmp[i] = coords->Bxy[i] * coords->g_22[i] / coords->J[i] + * coords->J.ynext(offset)[iyp] / coords->g_22.ynext(offset)[iyp]; + } + set_parallel_metric_component("Bxy", coords->Bxy, offset, tmp); + } #undef LOAD_PAR #endif } From 6a05d587bba0dec3e1ef542821e4c2cd2c627ddc Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 09:58:40 +0200 Subject: [PATCH 141/259] Add fix also to source of the generated code Follow up from 196138a223 --- src/field/gen_fieldops.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index e38ea2eafc..16a5f4dd6e 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -69,6 +69,7 @@ def smart_open(filename, mode="r"): #include #include #include +#include """ From 96e710b1814ac88639a7d97eb0dd898c166b0d5c Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 10:10:16 +0200 Subject: [PATCH 142/259] Prefer std::vector::emplace_back to work around cuda compiler issue --- include/bout/parallel_boundary_region.hxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 849bb0ffe3..21eddbacee 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -38,6 +38,10 @@ struct Indices { signed char valid; signed char offset; unsigned char abs_offset; + Indices(Ind3D index, RealPoint&& intersection, BoutReal length, signed char valid, + signed char offset, unsigned char abs_offset) + : index(index), intersection(std::move(intersection)), length(length), valid(valid), + offset(offset), abs_offset(abs_offset) {}; }; using IndicesVec = std::vector; @@ -333,12 +337,9 @@ public: if (!bndry_points.empty() && bndry_points.back().index > ind) { is_sorted = false; } - bndry_points.push_back({ind, - {x, y, z}, - length, - valid, - offset, - static_cast(std::abs(offset))}); + bndry_points.emplace_back(ind, bout::parallel_boundary_region::RealPoint{x, y, z}, + length, valid, offset, + static_cast(std::abs(offset))); } void add_point(int ix, int iy, int iz, BoutReal x, BoutReal y, BoutReal z, BoutReal length, char valid, signed char offset) { From baa56fe5ab93e783d40e57550c25e51c365236c0 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 21 Aug 2025 08:16:32 +0000 Subject: [PATCH 143/259] Apply clang-format changes --- include/bout/parallel_boundary_region.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 21eddbacee..5dc265d997 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -41,7 +41,7 @@ struct Indices { Indices(Ind3D index, RealPoint&& intersection, BoutReal length, signed char valid, signed char offset, unsigned char abs_offset) : index(index), intersection(std::move(intersection)), length(length), valid(valid), - offset(offset), abs_offset(abs_offset) {}; + offset(offset), abs_offset(abs_offset){}; }; using IndicesVec = std::vector; From 28dec7aeceb50e71e2725e5ff60e4378208c7090 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 21 Aug 2025 11:37:58 +0200 Subject: [PATCH 144/259] remove unneeded std::move --- include/bout/parallel_boundary_region.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 5dc265d997..f54517be87 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -40,7 +40,7 @@ struct Indices { unsigned char abs_offset; Indices(Ind3D index, RealPoint&& intersection, BoutReal length, signed char valid, signed char offset, unsigned char abs_offset) - : index(index), intersection(std::move(intersection)), length(length), valid(valid), + : index(index), intersection(intersection), length(length), valid(valid), offset(offset), abs_offset(abs_offset){}; }; From 0560964c55494e8f7b5cefc03c0f77cf15602c44 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 25 Aug 2025 11:41:39 +0200 Subject: [PATCH 145/259] add filledFrom for Field3DParallel --- include/bout/field3d.hxx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index b80b56a3cc..c7203c6daa 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -34,6 +34,7 @@ class Field3D; #include "bout/fieldperp.hxx" #include "bout/region.hxx" +#include #include #include #include @@ -815,4 +816,26 @@ inline Field3D operator/(const Field3DParallel& lhs, const Field2D& rhs) { return lhs.asField3D() / rhs; } +inline Field3DParallel +filledFrom(const Field3DParallel& f, + std::function func) { + auto result{emptyFrom(f)}; + if (f.hasParallelSlices()) { + BOUT_FOR(i, result.getRegion("RGN_NOY")) { result[i] = func(0, i); } + + for (size_t i = 0; i < result.numberParallelSlices(); ++i) { + BOUT_FOR(d, result.yup(i).getValidRegionWithDefault("RGN_INVALID")) { + result.yup(i)[d] = func(i + 1, d); + } + BOUT_FOR(d, result.ydown(i).getValidRegionWithDefault("RGN_INVALID")) { + result.ydown(i)[d] = func(-i - 1, d); + } + } + } else { + BOUT_FOR(i, result.getRegion("RGN_ALL")) { result[i] = func(0, i); } + } + + return result; +} + #endif /* BOUT_FIELD3D_H */ From c964ff69c0aa39afb12ea7250fc1ae326381c9e6 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 25 Aug 2025 13:04:21 +0200 Subject: [PATCH 146/259] Allocate before usage --- include/bout/field3d.hxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index c7203c6daa..1c1f2441eb 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -824,9 +824,11 @@ filledFrom(const Field3DParallel& f, BOUT_FOR(i, result.getRegion("RGN_NOY")) { result[i] = func(0, i); } for (size_t i = 0; i < result.numberParallelSlices(); ++i) { + result.yup(i).allocate(); BOUT_FOR(d, result.yup(i).getValidRegionWithDefault("RGN_INVALID")) { result.yup(i)[d] = func(i + 1, d); } + result.ydown(i).allocate(); BOUT_FOR(d, result.ydown(i).getValidRegionWithDefault("RGN_INVALID")) { result.ydown(i)[d] = func(-i - 1, d); } From b9682734df3b38b084142e00ed47761e98d70767 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 1 Sep 2025 12:09:51 +0200 Subject: [PATCH 147/259] Allow more parallel boundary regions Also allow to set boundaries for bndry_par_xin/xout and bndry_par_yup/ydown --- src/mesh/boundary_factory.cxx | 98 ++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/src/mesh/boundary_factory.cxx b/src/mesh/boundary_factory.cxx index d112a216ad..5934daff31 100644 --- a/src/mesh/boundary_factory.cxx +++ b/src/mesh/boundary_factory.cxx @@ -228,46 +228,82 @@ BoundaryOpBase* BoundaryFactory::createFromOptions(const string& varname, string prefix("bndry_"); - string side; + std::array sides; + sides[0] = region->label; switch (region->location) { case BNDRY_XIN: { - side = "xin"; + sides[1] = "xin"; break; } case BNDRY_XOUT: { - side = "xout"; + sides[1] = "xout"; break; } case BNDRY_YDOWN: { - side = "ydown"; + sides[1] = "ydown"; break; } case BNDRY_YUP: { - side = "yup"; + sides[1] = "yup"; break; } case BNDRY_PAR_FWD_XIN: { - side = "par_yup_xin"; + sides[1] = "par_yup_xin"; break; } case BNDRY_PAR_FWD_XOUT: { - side = "par_yup_xout"; + sides[1] = "par_yup_xout"; break; } case BNDRY_PAR_BKWD_XIN: { - side = "par_ydown_xin"; + sides[1] = "par_ydown_xin"; break; } case BNDRY_PAR_BKWD_XOUT: { - side = "par_ydown_xout"; + sides[1] = "par_ydown_xout"; break; } default: { - side = "all"; + sides[1] = "all"; break; } } + switch (region->location) { + case BNDRY_PAR_FWD_XIN: + case BNDRY_PAR_BKWD_XIN: { + sides[2] = "par_xin"; + break; + } + case BNDRY_PAR_BKWD_XOUT: + case BNDRY_PAR_FWD_XOUT: { + sides[2] = "par_xout"; + break; + } + default: { + sides[2] = "all"; + break; + } + } + switch (region->location) { + case BNDRY_PAR_FWD_XIN: + case BNDRY_PAR_FWD_XOUT: { + sides[3] = "par_yup"; + break; + } + case BNDRY_PAR_BKWD_XIN: + case BNDRY_PAR_BKWD_XOUT: { + sides[3] = "par_ydown"; + break; + } + default: { + sides[3] = "all"; + break; + } + } + + sides[4] = region->isParallel ? "par_all" : "all"; + // Get options Options* options = Options::getRoot(); @@ -275,27 +311,10 @@ BoundaryOpBase* BoundaryFactory::createFromOptions(const string& varname, Options* varOpts = options->getSection(varname); string set; - /// First try looking for (var, region) - if (varOpts->isSet(prefix + region->label)) { - varOpts->get(prefix + region->label, set, ""); - return create(set, region); - } - - /// Then (var, side) - if (varOpts->isSet(prefix + side)) { - varOpts->get(prefix + side, set, ""); - return create(set, region); - } - - /// Then (var, all) - if (region->isParallel) { - if (varOpts->isSet(prefix + "par_all")) { - varOpts->get(prefix + "par_all", set, ""); - return create(set, region); - } - } else { - if (varOpts->isSet(prefix + "all")) { - varOpts->get(prefix + "all", set, ""); + /// First try looking for (var, ...) + for (const auto& side : sides) { + if (varOpts->isSet(prefix + side)) { + varOpts->get(prefix + side, set, ""); return create(set, region); } } @@ -303,16 +322,13 @@ BoundaryOpBase* BoundaryFactory::createFromOptions(const string& varname, // Get the "all" options varOpts = options->getSection("all"); - /// Then (all, region) - if (varOpts->isSet(prefix + region->label)) { - varOpts->get(prefix + region->label, set, ""); - return create(set, region); - } - - /// Then (all, side) - if (varOpts->isSet(prefix + side)) { - varOpts->get(prefix + side, set, ""); - return create(set, region); + /// First try looking for (all, ...) + for (const auto& side : sides) { + if (varOpts->isSet(prefix + side)) { + varOpts->get(prefix + side, set, + region->isParallel ? "parallel_dirichlet_o2" : "dirichlet"); + return create(set, region); + } } /// Then (all, all) From 43bfa9adeef649664a7d2390a9d001e73602e478 Mon Sep 17 00:00:00 2001 From: David Bold Date: Mon, 1 Sep 2025 12:21:49 +0200 Subject: [PATCH 148/259] Add limit_at_least function to boundary_iterator --- include/bout/boundary_iterator.hxx | 6 ++++++ include/bout/parallel_boundary_region.hxx | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx index 601f6a8a28..118036256e 100644 --- a/include/bout/boundary_iterator.hxx +++ b/include/bout/boundary_iterator.hxx @@ -77,6 +77,12 @@ public: } } + void limit_at_least(Field3D& f, BoutReal value) const { + if (ynext(f) < value) { + ynext(f) = value; + } + } + BoutReal& ynext(Field3D& f) const { return f[ind().yp(by).xp(bx)]; } const BoutReal& ynext(const Field3D& f) const { return f[ind().yp(by).xp(bx)]; } BoutReal& yprev(Field3D& f) const { return f[ind().yp(-by).xp(-bx)]; } diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index f54517be87..66aed9316e 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -188,6 +188,14 @@ public: } } + void limit_at_least(Field3D& f, BoutReal value) const { + ITER() { + if (getAt(f, i) < value) { + getAt(f, i) = value; + } + } + } + // NB: value needs to be scaled by dy // neumann_o1 is actually o2 if we would use an appropriate one-sided stencil. // But in general we do not, and thus for normal C2 stencils, this is 1st order. From fd49f9bb3f169c5627160027f6024a8ce2d1b3a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 13:50:04 +0000 Subject: [PATCH 149/259] Update pygithub requirement from ~=2.7 to ~=2.8 Updates the requirements on [pygithub](https://github.com/pygithub/pygithub) to permit the latest version. - [Release notes](https://github.com/pygithub/pygithub/releases) - [Changelog](https://github.com/PyGithub/PyGithub/blob/main/doc/changes.rst) - [Commits](https://github.com/pygithub/pygithub/compare/v2.7.0...v2.8.1) --- updated-dependencies: - dependency-name: pygithub dependency-version: 2.8.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements_maint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_maint.txt b/requirements_maint.txt index a5e94a0af5..b1d9db5ff8 100644 --- a/requirements_maint.txt +++ b/requirements_maint.txt @@ -1,3 +1,3 @@ -pygithub~=2.7 +pygithub~=2.8 ruamel-yaml~=0.18 Unidecode~=1.3 From 9cae0e58650ed4314642af015f0d22e91eb30365 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 12:50:09 +0200 Subject: [PATCH 150/259] Remove License-File, add License and README --- tools/pylib/_boutpp_build/backend.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 3df29d276d..8d0b4f4015 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -216,9 +216,16 @@ def build_sdist(sdist_directory, config_settings=None): f"""Metadata-Version: 2.1 Name: {pkgname} Version: {getversion()} -License-File: COPYING """ ) + with open("LICENSE") as src: + pre = "License:" + for l in src: + f.write(f"{pre}{l}\n") + pre = " " + f.write("\n\n") + with open("README.md") as src: + f.write(src.read()) run( f"tar --append -f {sdist_directory}/{fname} _version.txt --xform='s\\_version.txt\\{prefix}/_version.txt\\'" ) From 97b0a882b334f60f0f5731d6a4652e2683e2e0a1 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 13:17:43 +0200 Subject: [PATCH 151/259] Fix spacing --- tools/pylib/_boutpp_build/backend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 8d0b4f4015..c9db2f1b55 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -219,10 +219,10 @@ def build_sdist(sdist_directory, config_settings=None): """ ) with open("LICENSE") as src: - pre = "License:" + pre = "License: " for l in src: - f.write(f"{pre}{l}\n") - pre = " " + f.write(f"{pre}{l}") + pre = " " f.write("\n\n") with open("README.md") as src: f.write(src.read()) From 4803d54bda35086c8d721e1e19e0a56a3024bd09 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 13:19:49 +0200 Subject: [PATCH 152/259] Add content type --- tools/pylib/_boutpp_build/backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index c9db2f1b55..98897ce126 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -223,7 +223,7 @@ def build_sdist(sdist_directory, config_settings=None): for l in src: f.write(f"{pre}{l}") pre = " " - f.write("\n\n") + f.write("\nDescription-Content-Type: text/markdown\n\n") with open("README.md") as src: f.write(src.read()) run( From 89dc6fba5b1767f13bab0b38e489ae7aca86ce1c Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 13:22:32 +0200 Subject: [PATCH 153/259] Fix spacing --- tools/pylib/_boutpp_build/backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 98897ce126..6d341e6aaa 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -223,7 +223,7 @@ def build_sdist(sdist_directory, config_settings=None): for l in src: f.write(f"{pre}{l}") pre = " " - f.write("\nDescription-Content-Type: text/markdown\n\n") + f.write("Description-Content-Type: text/markdown\n\n") with open("README.md") as src: f.write(src.read()) run( From a0657ef4b6bcca6e61b04a18d1af958735cae11e Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 12:50:09 +0200 Subject: [PATCH 154/259] Remove License-File, add License and README --- tools/pylib/_boutpp_build/backend.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 0c1e611a2f..c04f5111fc 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -216,9 +216,16 @@ def build_sdist(sdist_directory, config_settings=None): f"""Metadata-Version: 2.1 Name: {pkgname} Version: {getversion()} -License-File: COPYING """ ) + with open("LICENSE") as src: + pre = "License:" + for l in src: + f.write(f"{pre}{l}\n") + pre = " " + f.write("\n\n") + with open("README.md") as src: + f.write(src.read()) run( f"tar --append -f {sdist_directory}/{fname} _version.txt --xform='s\\_version.txt\\{prefix}/_version.txt\\'" ) From d01957421d8313d03d1d8f3ae8dec340204d8ca5 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 13:17:43 +0200 Subject: [PATCH 155/259] Fix spacing --- tools/pylib/_boutpp_build/backend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index c04f5111fc..f854c4582f 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -219,10 +219,10 @@ def build_sdist(sdist_directory, config_settings=None): """ ) with open("LICENSE") as src: - pre = "License:" + pre = "License: " for l in src: - f.write(f"{pre}{l}\n") - pre = " " + f.write(f"{pre}{l}") + pre = " " f.write("\n\n") with open("README.md") as src: f.write(src.read()) From 7f79d21f82a27a050529bf5bcaa577a987112e96 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 13:19:49 +0200 Subject: [PATCH 156/259] Add content type --- tools/pylib/_boutpp_build/backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index f854c4582f..6fd21c1506 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -223,7 +223,7 @@ def build_sdist(sdist_directory, config_settings=None): for l in src: f.write(f"{pre}{l}") pre = " " - f.write("\n\n") + f.write("\nDescription-Content-Type: text/markdown\n\n") with open("README.md") as src: f.write(src.read()) run( From af37dff14f1875ad2ace70f3f260a246dc8ec010 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 4 Sep 2025 13:22:32 +0200 Subject: [PATCH 157/259] Fix spacing --- tools/pylib/_boutpp_build/backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 6fd21c1506..f105fadceb 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -223,7 +223,7 @@ def build_sdist(sdist_directory, config_settings=None): for l in src: f.write(f"{pre}{l}") pre = " " - f.write("\nDescription-Content-Type: text/markdown\n\n") + f.write("Description-Content-Type: text/markdown\n\n") with open("README.md") as src: f.write(src.read()) run( From a23b2e06f1b77a683811d0eeee66ebcadace9336 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Fri, 5 Sep 2025 23:31:02 +0100 Subject: [PATCH 158/259] Modify regex to make it a valid POSIX Extended regular expression --- tests/unit/sys/test_timer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/sys/test_timer.cxx b/tests/unit/sys/test_timer.cxx index 4ec934658d..7641c5f8cf 100644 --- a/tests/unit/sys/test_timer.cxx +++ b/tests/unit/sys/test_timer.cxx @@ -271,7 +271,7 @@ TEST(TimerTest, ListAllInfo) { using namespace ::testing; EXPECT_THAT(cout_capture.str(), HasSubstr("Timer name |")); - EXPECT_THAT(cout_capture.str(), ContainsRegex("one *| 0\\.\\d+ | 1 | 0\\.\\d+")); - EXPECT_THAT(cout_capture.str(), ContainsRegex("two *| 0 * | 2 | 0\\.\\d+")); + EXPECT_THAT(cout_capture.str(), ContainsRegex("one *| 0\\.[0-9]+ | 1 | 0\\.[0-9]+")); + EXPECT_THAT(cout_capture.str(), ContainsRegex("two *| 0 * | 2 | 0\\.[0-9]+")); } #endif From 921901511a8f5ffefe1144a8c63697d797aec4de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 19:40:35 +0000 Subject: [PATCH 159/259] Bump actions/setup-python from 5 to 6 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/python-package.yml | 6 +++--- .github/workflows/tests.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 5a788f9eb0..fc5e84662c 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -22,7 +22,7 @@ jobs: fetch-depth: 0 submodules: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 - name: Install dependencies run: python -m pip install --upgrade pip && pip install --upgrade build && @@ -62,7 +62,7 @@ jobs: fetch-depth: 0 submodules: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 - name: Install dependencies run: python -m pip install --upgrade pip && pip install --upgrade build && @@ -111,7 +111,7 @@ jobs: fetch-depth: 0 submodules: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 - name: Install dependencies run: python -m pip install --upgrade pip && pip install --upgrade build && diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aa3db3adc1..0d73948d45 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -162,7 +162,7 @@ jobs: with: submodules: true - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: '3.x' From 679ea3ca62621529b10ecf450a1f29933ed86d27 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Mon, 15 Sep 2025 14:24:15 +0100 Subject: [PATCH 160/259] Disable test-backtrace for FreeBSD --- tests/integrated/test-backtrace/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-backtrace/CMakeLists.txt b/tests/integrated/test-backtrace/CMakeLists.txt index aa66eeed56..b20262f1b1 100644 --- a/tests/integrated/test-backtrace/CMakeLists.txt +++ b/tests/integrated/test-backtrace/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-backtrace SOURCES boutexcept.cxx REQUIRES BOUT_USE_BACKTRACE + CONFLICTS CMAKE_SYSTEM_NAME MATCHES "FreeBSD" USE_RUNTEST ) From 892e0cd762f831ff272ce13cbb19ddb51fb50f95 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Mon, 15 Sep 2025 14:49:36 +0100 Subject: [PATCH 161/259] Use std::filesystem instead of POSIX struct stat to be more portable --- src/bout++.cxx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/bout++.cxx b/src/bout++.cxx index 6de1c5713b..48ab96298b 100644 --- a/src/bout++.cxx +++ b/src/bout++.cxx @@ -67,11 +67,10 @@ const char DEFAULT_DIR[] = "data"; #include #include +#include #include #include -#include - // Value passed at compile time // Used for MD5SUM, BOUT_LOCALE_PATH, and REVISION #define BUILDFLAG1_(x) #x @@ -81,12 +80,6 @@ const char DEFAULT_DIR[] = "data"; #define INDIRECT0_BOUTMAIN(...) INDIRECT1_BOUTMAIN(#__VA_ARGS__) #define STRINGIFY(a) INDIRECT0_BOUTMAIN(a) -// Define S_ISDIR if not defined by system headers (that is, MSVC) -// Taken from https://github.com/curl/curl/blob/e59540139a398dc70fde6aec487b19c5085105af/lib/curl_setup.h#L748-L751 -#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif - #ifdef _MSC_VER #include inline auto getpid() -> int { return GetCurrentProcessId(); } @@ -506,9 +499,8 @@ auto parseCommandLineArgs(int argc, char** argv) -> CommandLineArgs { } void checkDataDirectoryIsAccessible(const std::string& data_dir) { - struct stat test; - if (stat(data_dir.c_str(), &test) == 0) { - if (!S_ISDIR(test.st_mode)) { + if (std::filesystem::exists(data_dir)) { + if (!std::filesystem::is_directory(data_dir)) { throw BoutException(_("DataDir \"{:s}\" is not a directory\n"), data_dir); } } else { From a00151e65cb9fca04a27dde21804894b63515d2c Mon Sep 17 00:00:00 2001 From: tomc271 Date: Mon, 15 Sep 2025 16:39:48 +0100 Subject: [PATCH 162/259] Exception messages are sent to stdout rather than stderr on FreeBSD --- tests/integrated/test-command-args/runtest | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/integrated/test-command-args/runtest b/tests/integrated/test-command-args/runtest index 6830959343..3a448e1725 100755 --- a/tests/integrated/test-command-args/runtest +++ b/tests/integrated/test-command-args/runtest @@ -5,10 +5,14 @@ import os import re import shutil import unittest +import platform + + +OUTPUT_FILE = "stdout.log" if platform.system() == "FreeBSD" else "stderr.log" class TestCommandLineArgs(unittest.TestCase): - command = "./command-args 2>stderr.log" + command = "./command-args >stdout.log 2>stderr.log" def makeDirAndCopyInput(self, path): os.mkdir(path) @@ -16,7 +20,7 @@ class TestCommandLineArgs(unittest.TestCase): def setUp(self): try: - os.remove("stderr.log") + os.remove(OUTPUT_FILE) except OSError: pass shutil.rmtree("./data", ignore_errors=True) @@ -29,7 +33,7 @@ class TestCommandLineArgs(unittest.TestCase): def testNoArgumentsNoDirectory(self): with self.assertRaises(RuntimeError): launch_safe(self.command, pipe=True, nproc=1, mthread=1) - with open("stderr.log") as f: + with open(OUTPUT_FILE) as f: contents = f.read() self.assertIn( '"data" does not exist', @@ -97,7 +101,7 @@ class TestCommandLineArgs(unittest.TestCase): launch_safe( self.command + " -d non_existent", pipe=True, nproc=1, mthread=1 ) - with open("stderr.log") as f: + with open(OUTPUT_FILE) as f: contents = f.read() self.assertIn( '"non_existent" does not exist', @@ -108,7 +112,7 @@ class TestCommandLineArgs(unittest.TestCase): def testDirectoryArgumentNonDirectory(self): with self.assertRaises(RuntimeError): launch_safe(self.command + " -d runtest", pipe=True, nproc=1, mthread=1) - with open("stderr.log") as f: + with open(OUTPUT_FILE) as f: contents = f.read() self.assertIn( '"runtest" is not a directory', @@ -175,21 +179,24 @@ class TestCommandLineArgs(unittest.TestCase): "--foo_flag", "some:option=value", ] - _, out = launch_safe( + launch_safe( self.command + " " + " ".join(extra_options), pipe=True, nproc=1, mthread=1 ) + + with open(OUTPUT_FILE) as f: + contents = f.read() - command_line_options = None - for line in out.splitlines(): - if line.lstrip().startswith("Command line"): - command_line_options = line - - for option in extra_options: - self.assertIn( - option, - command_line_options, - msg="FAIL: option {} not printed out".format(option), - ) + command_line_options = None + for line in contents.splitlines(): + if line.lstrip().startswith("Command line"): + command_line_options = line + + for option in extra_options: + self.assertIn( + option, + command_line_options, + msg="FAIL: option {} not printed out".format(option), + ) if __name__ == "__main__": From 07e8d959f37db4ef7508559865bba132a28bcd12 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 17 Sep 2025 12:29:46 +0100 Subject: [PATCH 163/259] Use the portable "/usr/bin/env bash" shebang instead of "/bin/bash" --- tests/integrated/test-bout-override-default-option/runtest | 2 +- tests/integrated/test-code-style/runtest | 2 +- tests/integrated/test-compile-examples-petsc/runtest | 2 +- tests/integrated/test-compile-examples/runtest | 2 +- tests/integrated/test-coordinates-initialization/runtest | 2 +- tests/integrated/test-drift-instability/qsubcase.sh | 2 +- tests/integrated/test-include/runtest | 2 +- tests/integrated/test-interchange-instability/qsubcase.sh | 2 +- tests/integrated/test-stopCheck/runtest | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/integrated/test-bout-override-default-option/runtest b/tests/integrated/test-bout-override-default-option/runtest index 42d75ca100..c13f4439b3 100755 --- a/tests/integrated/test-bout-override-default-option/runtest +++ b/tests/integrated/test-bout-override-default-option/runtest @@ -1,3 +1,3 @@ -#!/bin/bash +#!/usr/bin/env bash make && ./test-bout-override-default-option diff --git a/tests/integrated/test-code-style/runtest b/tests/integrated/test-code-style/runtest index cfd277d71b..d392f9110f 100755 --- a/tests/integrated/test-code-style/runtest +++ b/tests/integrated/test-code-style/runtest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #requires not make diff --git a/tests/integrated/test-compile-examples-petsc/runtest b/tests/integrated/test-compile-examples-petsc/runtest index cd61c30ef5..0f9625af40 100755 --- a/tests/integrated/test-compile-examples-petsc/runtest +++ b/tests/integrated/test-compile-examples-petsc/runtest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #requires: all_tests #requires: not make diff --git a/tests/integrated/test-compile-examples/runtest b/tests/integrated/test-compile-examples/runtest index 31650adeab..765ea2cbfd 100755 --- a/tests/integrated/test-compile-examples/runtest +++ b/tests/integrated/test-compile-examples/runtest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #requires: all_tests #requires: not make diff --git a/tests/integrated/test-coordinates-initialization/runtest b/tests/integrated/test-coordinates-initialization/runtest index 53cda495e6..60c3e3c980 100755 --- a/tests/integrated/test-coordinates-initialization/runtest +++ b/tests/integrated/test-coordinates-initialization/runtest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Cores: 3 diff --git a/tests/integrated/test-drift-instability/qsubcase.sh b/tests/integrated/test-drift-instability/qsubcase.sh index a7124dc81b..056095b18b 100755 --- a/tests/integrated/test-drift-instability/qsubcase.sh +++ b/tests/integrated/test-drift-instability/qsubcase.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Create a set of runs and submit to a queueing system e.g. Sun Grid Engine # diff --git a/tests/integrated/test-include/runtest b/tests/integrated/test-include/runtest index f70036a9e4..4fa8096c4b 100755 --- a/tests/integrated/test-include/runtest +++ b/tests/integrated/test-include/runtest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #requires: all_tests #Requires: not make diff --git a/tests/integrated/test-interchange-instability/qsubcase.sh b/tests/integrated/test-interchange-instability/qsubcase.sh index 9713809a61..ba3e22e7fa 100755 --- a/tests/integrated/test-interchange-instability/qsubcase.sh +++ b/tests/integrated/test-interchange-instability/qsubcase.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash QSUB=mpich2sub # Common values are qsub, mpisub NP=4 diff --git a/tests/integrated/test-stopCheck/runtest b/tests/integrated/test-stopCheck/runtest index aa0920d087..5cb8f0f1fb 100755 --- a/tests/integrated/test-stopCheck/runtest +++ b/tests/integrated/test-stopCheck/runtest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash make || exit From 17f61193d22c71a82a8df6fc7b6526dcab6185a9 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 17 Sep 2025 12:57:57 +0100 Subject: [PATCH 164/259] Prevent SignalHandlerTestDeathTest when OS is FreeBSD --- tests/unit/src/test_bout++.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/test_bout++.cxx b/tests/unit/src/test_bout++.cxx index b31be16a67..cef518756c 100644 --- a/tests/unit/src/test_bout++.cxx +++ b/tests/unit/src/test_bout++.cxx @@ -70,7 +70,7 @@ class SignalHandlerTest : public ::testing::Test { using SignalHandlerTestDeathTest = SignalHandlerTest; -#if !defined(__NVCC__) +#if !defined(__NVCC__) and !defined(__FreeBSD__) TEST_F(SignalHandlerTestDeathTest, SegFault) { bout::experimental::setupSignalHandler(bout::experimental::defaultSignalHandler); // This test is *incredibly* expensive, maybe as much as 1s, so only test the one signal From 0673cbc89cc5b266388f425b95ee5333b0cbf78d Mon Sep 17 00:00:00 2001 From: tomc271 <58003025+tomc271@users.noreply.github.com> Date: Wed, 17 Sep 2025 14:07:51 +0000 Subject: [PATCH 165/259] Apply black changes --- tests/integrated/test-command-args/runtest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-command-args/runtest b/tests/integrated/test-command-args/runtest index 3a448e1725..e30b00fca4 100755 --- a/tests/integrated/test-command-args/runtest +++ b/tests/integrated/test-command-args/runtest @@ -182,7 +182,7 @@ class TestCommandLineArgs(unittest.TestCase): launch_safe( self.command + " " + " ".join(extra_options), pipe=True, nproc=1, mthread=1 ) - + with open(OUTPUT_FILE) as f: contents = f.read() From 646d67315f6259fb4bee9296d4cf06846b515191 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Thu, 18 Sep 2025 14:06:55 +0100 Subject: [PATCH 166/259] Fix testCommandLineOptionsArePrinted Output always goes to stdout when no error. --- tests/integrated/test-command-args/runtest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-command-args/runtest b/tests/integrated/test-command-args/runtest index e30b00fca4..39939bb105 100755 --- a/tests/integrated/test-command-args/runtest +++ b/tests/integrated/test-command-args/runtest @@ -183,7 +183,7 @@ class TestCommandLineArgs(unittest.TestCase): self.command + " " + " ".join(extra_options), pipe=True, nproc=1, mthread=1 ) - with open(OUTPUT_FILE) as f: + with open("stdout.log") as f: contents = f.read() command_line_options = None From 370c42d8ade1e0457f5c83ec9c475c3fa9745071 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 30 Sep 2025 14:56:26 +0200 Subject: [PATCH 167/259] Preserve more when coping Field3D --- src/field/field3d.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 6fd5efb670..f2846fb7d5 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -66,7 +66,8 @@ Field3D::Field3D(Mesh* localmesh, CELL_LOC location_in, DirectionTypes direction /// later) Field3D::Field3D(const Field3D& f) : Field(f), data(f.data), yup_fields(f.yup_fields), ydown_fields(f.ydown_fields), - regionID(f.regionID) { + regionID(f.regionID), tracking_state(f.tracking_state), tracking(f.tracking), + selfname(f.selfname) { TRACE("Field3D(Field3D&)"); @@ -926,6 +927,10 @@ void swap(Field3D& first, Field3D& second) noexcept { swap(first.deriv, second.deriv); swap(first.yup_fields, second.yup_fields); swap(first.ydown_fields, second.ydown_fields); + swap(first.regionID, second.regionID); + swap(first.tracking_state, second.tracking_state); + swap(first.tracking, second.tracking); + swap(first.selfname, second.selfname); } const Region& From 107b518bba5ded63edc0ef4b2a58970168955334 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 30 Sep 2025 14:56:53 +0200 Subject: [PATCH 168/259] add resetRegionParallel to set default regions for parallel slices --- include/bout/field3d.hxx | 1 + src/field/field3d.cxx | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 1c1f2441eb..e776895870 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -338,6 +338,7 @@ public: const Region& getValidRegionWithDefault(const std::string& region_name) const; void setRegion(const std::string& region_name) override; void resetRegion() override; + void resetRegionParallel(); void setRegion(size_t id) override; void setRegion(std::optional id) override; std::optional getRegionID() const override { return regionID; }; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index f2846fb7d5..34a781cb49 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -946,6 +946,14 @@ void Field3D::setRegion(const std::string& region_name) { } void Field3D::resetRegion() { regionID.reset(); }; +void Field3D::resetRegionParallel() { + if (isFci()) { + for (int i = 0; i < fieldmesh->ystart; ++i) { + yup_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", i + 1)); + ydown_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", -i - 1)); + } + } +} void Field3D::setRegion(size_t id) { regionID = id; }; void Field3D::setRegion(std::optional id) { regionID = id; }; From 4789b413210d54647c1550a83682ea16e56cac00 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 30 Sep 2025 14:57:12 +0200 Subject: [PATCH 169/259] Set regions on parallel slices --- src/field/field3d.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 34a781cb49..2093fdba06 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -108,6 +108,7 @@ Field3DParallel::Field3DParallel(const BoutReal val, Mesh* localmesh) yup(i) = val; ydown(i) = val; } + resetRegionParallel(); } } @@ -165,11 +166,8 @@ void Field3D::splitParallelSlices() { // ParallelTransform, so we don't need a full constructor yup_fields.emplace_back(fieldmesh); ydown_fields.emplace_back(fieldmesh); - if (isFci()) { - yup_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", i + 1)); - ydown_fields[i].setRegion(fmt::format("RGN_YPAR_{:+d}", -i - 1)); - } } + resetRegionParallel(); } void Field3D::splitParallelSlicesAndAllocate() { splitParallelSlices(); @@ -395,6 +393,7 @@ Field3DParallel& Field3DParallel::operator=(const BoutReal val) { } } resetRegion(); + resetRegionParallel(); allocate(); From 6b993da4d02b2ed6db52f4404665198689990358 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 30 Sep 2025 14:57:27 +0200 Subject: [PATCH 170/259] Add check that parallel slices have valid region --- src/field/field3d.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 2093fdba06..94700d46a4 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -1004,6 +1004,12 @@ Options* Field3D::track(const BoutReal& change, std::string operation) { void Field3DParallel::ensureFieldAligned() { if (isFci()) { ASSERT2(hasParallelSlices()); + if (fieldmesh != nullptr) { + for (int i = 0; i < fieldmesh->ystart; ++i) { + ASSERT2(yup_fields[i].getRegionID().has_value()); + ASSERT2(ydown_fields[i].getRegionID().has_value()); + } + } } // else { // if (getDirectionY() != YDirectionType::Aligned) { // *this = toFieldAligned(*this); From 705414cd9f30369a41d0abc936ef7f883acc18a9 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 30 Sep 2025 15:12:50 +0200 Subject: [PATCH 171/259] Remove commented out code --- src/field/field3d.cxx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 94700d46a4..0857fcfb45 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -1010,9 +1010,5 @@ void Field3DParallel::ensureFieldAligned() { ASSERT2(ydown_fields[i].getRegionID().has_value()); } } - } // else { - // if (getDirectionY() != YDirectionType::Aligned) { - // *this = toFieldAligned(*this); - // } - // } + } } From cfb22cfbd4ad82cad5e820f68ae6301e782a1a18 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 10:19:23 +0100 Subject: [PATCH 172/259] Update translations --- locale/de/libbout.po | 346 +++++++++++++++++++++------------------- locale/es/libbout.po | 344 ++++++++++++++++++++------------------- locale/fr/libbout.po | 330 +++++++++++++++++++------------------- locale/libbout.pot | 326 ++++++++++++++++++------------------- locale/zh_CN/libbout.po | 334 +++++++++++++++++++------------------- locale/zh_TW/libbout.po | 346 ++++++++++++++++++++-------------------- 6 files changed, 1031 insertions(+), 995 deletions(-) diff --git a/locale/de/libbout.po b/locale/de/libbout.po index 0e0773b5db..242beb45ca 100644 --- a/locale/de/libbout.po +++ b/locale/de/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2019-02-06 17:32+0000\n" "Last-Translator: David \n" "Language-Team: German\n" @@ -18,7 +18,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.2.1\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, fuzzy, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " @@ -27,7 +27,7 @@ msgstr "" "\t -> `Core` Region iyseps2_1-iyseps1_1 ({:d}-{:d} = {:d}) muss ein " "Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, fuzzy, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " @@ -36,7 +36,7 @@ msgstr "" "\t -> `Core` Region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) muss ein " "Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, fuzzy, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " @@ -45,11 +45,11 @@ msgstr "" "\t -> `Core` Region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) muss ein " "Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "\t -> Wert OK\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, fuzzy, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" @@ -57,7 +57,7 @@ msgstr "" "\t -> `Leg` Region jyseps1_1+1 ({:d}) muss ein Vielfaches von MYSUB ({:d}) " "sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, fuzzy, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " @@ -66,7 +66,7 @@ msgstr "" "\t -> `Leg` Region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) muss ein " "Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, fuzzy, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " @@ -75,7 +75,7 @@ msgstr "" "\t -> `Leg` Region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) muss ein Vielfaches " "von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, fuzzy, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " @@ -84,12 +84,17 @@ msgstr "" "\t -> `Leg` Region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) muss ein " "Vielfaches von MYSUB ({:d}) sein\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, fuzzy, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "\t -> ny/NYPE ({:d}/{:d} = {:d}) muss >= MYG ({:d}) sein\n" #: ../src/bout++.cxx:575 +#, fuzzy, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "\tNetCDF Unterstützung ist aktiviert\n" + +#: ../src/bout++.cxx:583 #, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -98,28 +103,28 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, fuzzy, c++-format msgid "\tCandidate value: {:d}\n" msgstr "\tzu überprüfender Wert: {:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "\tKommandozeilenoptionen für diese Ausführung: " #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, fuzzy, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "\tWurde kompiliert mit den Optionen : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, fuzzy, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " @@ -128,14 +133,14 @@ msgstr "" "\tDas Gebiet wird in NXPE={:d} mal NYPE={:d} Gebiete der Größe localNx={:d} " "mal localNy={:d} aufgeteilt\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, fuzzy, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" "\tFEHLER: {:d} Punkte in der Y-Richtung können nicht gleichmässig zwischen " "{:d} Prozessen verteilt werden\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, fuzzy, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -156,31 +161,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "\tSchlüssel (Key) oder Wert nicht gesetzt in der Befehlszeile '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, fuzzy, c++-format msgid "\tFFT support {}\n" msgstr "\tNetCDF Unterstützung ist aktiviert\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "\tGittergröße: " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 #, fuzzy msgid "\tGuard cells (x,y,z): " msgstr "\tGuardzellen (x,y): " @@ -194,17 +199,17 @@ msgstr "" "\tDer Schlüssel darf nicht ':' enthalten\n" "\tZeile: {:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -214,98 +219,94 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "\t'=' darf nicht mehrfach vorkommen: '{:s}'\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, fuzzy, c++-format msgid "\tNetCDF support {}{}\n" msgstr "\tNetCDF Unterstützung ist aktiviert\n" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, fuzzy, c++-format -msgid "\tOpenMP parallelisation {}" -msgstr "\tOpenMP Parallelisierung ist deaktiviert\n" +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "\tOpenMP Parallelisierung mit {:d} Threads ist aktiviert\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\tOption " -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, fuzzy, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "\tOption '{:s}': Boolscherwert erwartet, '{:s}' gefunden\n" +msgid "\tOption {} = {}" +msgstr "\tOption " #: ../src/sys/options/options_ini.cxx:70 #, fuzzy, c++-format msgid "\tOptions file '{:s}' not found\n" msgstr "\tDie Optionendatei '{:s}' konnte nicht gefunden werden\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "\tParallele-NetCDF Unterstützung ist deaktiviert\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "\tParllele-NetCDF Unterstützung ist aktiviert\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "\tnz wird von der Griddatei gelesen\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "\tKontravariantevektoren werden gelesen " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "\tKovariantevektoren werden gelesen " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, fuzzy, c++-format msgid "\tSignal handling support {}\n" msgstr "\tSignalverarbeitung ist deaktiviert\n" @@ -315,7 +316,7 @@ msgstr "\tSignalverarbeitung ist deaktiviert\n" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "\tfertig\n" @@ -325,7 +326,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 #, fuzzy msgid "" "\n" @@ -345,7 +346,7 @@ msgstr "" " -v, --verbose\t\tWortreicherer Ausgabe\n" " -q, --quiet\t\tNur wichtigere Ausgaben anzeigen\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -353,7 +354,7 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, fuzzy, c++-format msgid "" "\n" @@ -362,7 +363,7 @@ msgstr "" "\n" "Simulation beendet um {:s}\n" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, fuzzy, c++-format msgid "" "\n" @@ -374,7 +375,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -402,7 +403,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -435,60 +436,60 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 #, fuzzy msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr " -c, --color\t\tFarbliche Ausgabe mit bout-log-color\n" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 #, fuzzy msgid ") overwritten with:" msgstr ") überschrieben mit {:s}" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "Alle genutzten Optionen\n" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, fuzzy, c++-format msgid "BOUT++ version {:s}\n" msgstr "BOUT++ Version {:s}\n" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 #, fuzzy msgid "Bad command line arguments:\n" msgstr "\t'=' darf nicht mehrfach vorkommen: '{:s}'\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "Randgebiete auf diesem Prozessor: " -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, fuzzy, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" "{:d} Punkte in der X-Richtung können nicht gleichmässig zwischen {:d} " "Prozessen verteilt werden\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, fuzzy, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -501,7 +502,7 @@ msgstr "" msgid "Command line" msgstr "Befehlszeile" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "Kompiliert mit:\n" @@ -510,16 +511,16 @@ msgstr "Kompiliert mit:\n" msgid "Compiled with flags" msgstr "\tWurde kompiliert mit den Optionen : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "Standardregionen werden erstellt" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, fuzzy, c++-format msgid "Could not create PID file {:s}" msgstr "Die Ausgabedatei '{:s}' konnte nicht geöffnet werden\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "" @@ -531,32 +532,32 @@ msgstr "" msgid "Could not open output file '{:s}'\n" msgstr "Die Ausgabedatei '{:s}' konnte nicht geöffnet werden\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, fuzzy, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "Der Ganzzahlen-Array '{:s}' konnte nicht gelesen werden\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" "Der Befehl 'bout-log-color' konnte nicht ausgeführt werden. Stellen Sie " "sicher, dass er sich in $PATH befindet.\n" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, fuzzy, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" "'Monitor' konnte nicht hinzugefügt werden: {:g} ist nicht ein Vielfaches von " "{:g}!" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -565,73 +566,73 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, fuzzy, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "Die Region '{:s}' ist nicht in regionMap2D" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, fuzzy, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "Die Region '{:s}' ist nicht in regionMap3D" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, fuzzy, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "Die Region '{:s}' ist nicht in regionMapPerp" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, fuzzy, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "" "Die Option {:s} = '{:s}' konnte nicht als ganze Zahl interpretiert werden." -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, fuzzy, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "Der Datenordner \"{:s}\" existiert nicht oder ist nicht lesbar\n" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, fuzzy, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "" "\"{:s}\" soll als Datenordner verwendet werden, ist jedoch kein Ordner\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "FEHLER: Der Integrator ist bereits initialisiert.\n" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, fuzzy, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "Es wurde ein Fehler während der Initialisierung gefunden: {:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "Es wurde ein Fehler beim Schreiben der Einstellungsdatei gefunden" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, fuzzy, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "Fehler: nx muss größer als 2 mal MXG sein (2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" "Der Integrator konnte nicht initialisiert werden. Der Prozess wird " "abgebrochen\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, fuzzy, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "Suche NXPE Wert (optimal = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "initialisiere den Integrator\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -644,48 +645,48 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "Lade das Gitter" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "Das Gitter muss nx enthalten" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "Das Gitter muss ny enthalten" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, fuzzy, c++-format msgid "Missing integer array {:s}\n" msgstr "Ganzzahlen-Array '{:s}' nicht gesetzt\n" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, fuzzy, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "Beendigung durch Monitor\n" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, fuzzy, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "Der Monitor signaliserte die Beendigung" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "Keine Randregionen auf diesem Prozessor" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 #, fuzzy msgid "No boundary regions; domain is periodic\n" msgstr "Keine Randregionen auf diesem Prozessor" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, fuzzy, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" @@ -693,7 +694,7 @@ msgstr "" "Anzahl an Prozessoren ({:d}) nicht teilbar durch Anzahl in x Richtung " "({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, fuzzy, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" @@ -702,26 +703,26 @@ msgstr "" "({:d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, fuzzy, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "Nur noch {:e} Sekunden verfügbar. Abbruch\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, fuzzy, c++-format msgid "Option {:s} has no value" msgstr "Der Option '{:s}' wurde kein Wert zugewiesen" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, fuzzy, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "Die Option {:s}:{:s} exisitiert nicht" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, fuzzy, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " @@ -730,12 +731,12 @@ msgstr "" "Optionen: Der Wert {2:s} wird mit dem Wert {1:s} gleichen Ursprungs ({0:s}) " "überschrieben." -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 #, fuzzy msgid "Possible boundary regions are: " msgstr "Keine Randregionen auf diesem Prozessor" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, fuzzy, c++-format msgid "" "Processor number: {:d} of {:d}\n" @@ -744,32 +745,32 @@ msgstr "" "Prozessorennummer: {:d} von {:d}\n" "\n" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, fuzzy, c++-format msgid "Registered region 2D {:s}" msgstr "2D Region '{:s}' hinzugefügt" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, fuzzy, c++-format msgid "Registered region 3D {:s}" msgstr "3D Region '{:s}' hinzugefügt" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, fuzzy, c++-format msgid "Registered region Perp {:s}" msgstr "Perp Region '{:s}' hinzugefügt" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, fuzzy, c++-format msgid "Revision: {:s}\n" msgstr "Revision: {:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "Dauer: " #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -781,7 +782,7 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" @@ -790,7 +791,7 @@ msgstr "" "Integrator\n" "\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -800,18 +801,18 @@ msgstr "" "Komm I/O Integrator\n" "\n" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, fuzzy, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" "Integriere mit einem `Monitor`-Zeitschritt von {1:e} für {0:d} Aufrufe.\n" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, fuzzy, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "Integriere {:d} Zeitschritte von je {:e}\n" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, fuzzy, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " @@ -820,7 +821,7 @@ msgstr "" "Der Integrator kann den Zeitschritt nicht von {:g} auf {:g} reduzieren, " "nachdem er initialisiert wurde!" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, fuzzy, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " @@ -829,27 +830,27 @@ 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:1480 +#: ../src/solver/solver.cxx:1494 #, fuzzy, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "Zeitliche Ableitung für Variable '{:s}' nicht gesetzt" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, fuzzy, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "Die Region '{:s}' ist bereits vorhanden in der regionMap2D" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, fuzzy, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "Die Region '{:s}' ist bereits vorhanden in der regionMap3D" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, fuzzy, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "Die Region '{:s}' ist bereits vorhanden in der regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -858,7 +859,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -866,31 +867,31 @@ msgstr "" "Unbekannte Paralleltransformation\n" "Gültige Optionen sind 'identity', 'shifted', 'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "Ungenutzte Optionen:\n" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, fuzzy, c++-format msgid "Usage is {:s} -d \n" msgstr "Benutzung: {:s} -d \n" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, fuzzy, c++-format msgid "Usage is {:s} -f \n" msgstr "Benutzung: {:s} -f \n" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, fuzzy, c++-format msgid "Usage is {:s} -l \n" msgstr "Benutzung: {:s} -f \n" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, fuzzy, c++-format msgid "Usage is {:s} -o \n" msgstr "Benutzung: {:s} -f \n" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, fuzzy, c++-format msgid "Usage is {} {} \n" msgstr "Benutzung: {:s} -f \n" @@ -901,7 +902,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, fuzzy, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -911,68 +912,73 @@ msgstr "" "[VAR=WERT]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 #, fuzzy msgid "User signalled to quit. Returning\n" msgstr "Beendigung durch Monitor\n" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, fuzzy, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" + +#: ../src/sys/options.cxx:426 #, fuzzy, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, fuzzy, c++-format msgid "Value for option {:s} is not an integer" msgstr "Wert der Option {:s} = {:e} ist keine Ganzzahl" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, fuzzy, c++-format msgid "Variable '{:s}' not initialised" msgstr "Variable '{:s}' ist nicht initialisiert" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, fuzzy, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " @@ -981,27 +987,27 @@ 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:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -1011,10 +1017,18 @@ msgid "Writing options to file {:s}\n" msgstr "Optionen werden in {:s} gespeichert\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "Vorgabe" +#, fuzzy, c++-format +#~ msgid "\tOpenMP parallelisation {}" +#~ msgstr "\tOpenMP Parallelisierung ist deaktiviert\n" + +#, fuzzy, c++-format +#~ msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +#~ msgstr "\tOption '{:s}': Boolscherwert erwartet, '{:s}' gefunden\n" + #~ msgid "\tChecking disabled\n" #~ msgstr "\tChecks sind deaktiviert\n" @@ -1022,10 +1036,6 @@ msgstr "Vorgabe" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\tChecks der Stufe {:d} sind aktiviert\n" -#, fuzzy -#~ msgid "\tOpenMP parallelisation enabled, using {:d} threads\n" -#~ msgstr "\tOpenMP Parallelisierung mit {:d} Threads ist aktiviert\n" - #~ msgid "\tSignal handling enabled\n" #~ msgstr "\tSignalverarbeitung ist aktiviert\n" @@ -1051,8 +1061,8 @@ msgstr "Vorgabe" #~ "überschrieben. Benötigt `restart`\n" #~ " VAR=WERT \t\tSetzt den Wert WERT für die Variable VAR\n" #~ "\n" -#~ "Weitere Eingabeparameter sind in dem Manual und dem Quellcode (z.B. {:s}." -#~ "cxx) des Physikmoduls definiert.\n" +#~ "Weitere Eingabeparameter sind in dem Manual und dem Quellcode (z.B. " +#~ "{:s}.cxx) des Physikmoduls definiert.\n" #, fuzzy #~ msgid "Couldn't get BoutReal from option {:s} = '{:s}'" diff --git a/locale/es/libbout.po b/locale/es/libbout.po index 8a3b22be61..68db78ada9 100644 --- a/locale/es/libbout.po +++ b/locale/es/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2019-02-11 12:46+0900\n" "Last-Translator: Marta \n" "Language-Team: Spanish\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, fuzzy, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " @@ -25,7 +25,7 @@ msgstr "" "\t -> La región `Core` jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) debe ser un " "múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, fuzzy, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " @@ -34,7 +34,7 @@ msgstr "" "\t -> La región `Core` jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) debe ser un " "múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, fuzzy, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " @@ -43,11 +43,11 @@ msgstr "" "\t -> La región `Core` jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) debe ser un " "múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "\t -> El valor es bueno\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, fuzzy, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" @@ -55,7 +55,7 @@ msgstr "" "\t -> La región `Leg` jyseps1_1+1 ({:d}) debe ser un múltiplo de MYSUB " "({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, fuzzy, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " @@ -64,7 +64,7 @@ msgstr "" "\t -> La región `Leg` jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) debe ser un " "múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, fuzzy, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " @@ -73,7 +73,7 @@ msgstr "" "\t -> La región `Leg` ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) debe ser un " "múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, fuzzy, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " @@ -82,12 +82,17 @@ msgstr "" "\t -> La región `Leg` ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) debe ser un " "múltiplo de MYSUB ({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, fuzzy, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "\t -> ny/NYPE ({:d}/{:d} = {:d}) debe ser >= MYG ({:d})\n" #: ../src/bout++.cxx:575 +#, fuzzy, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "\tSoporte netCDF activado\n" + +#: ../src/bout++.cxx:583 #, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -96,28 +101,28 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, fuzzy, c++-format msgid "\tCandidate value: {:d}\n" msgstr "\tValor candidato: {:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "\tParámetros de línea de comandos para esta ejecución :" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, fuzzy, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "\tCompilado con las opciones `flags` : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, fuzzy, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " @@ -126,14 +131,14 @@ msgstr "" "\tDominio separado (NXPE={:d}, NYPE={:d}) en los dominios (localNx={:d}, " "localNy={:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, fuzzy, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" "\tERROR: No se pueden separar {:d} Y puntos entre {:d} procesadores por " "igual\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, fuzzy, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -154,31 +159,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "\tEntrada o valor vacío en la línea de comandos '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, fuzzy, c++-format msgid "\tFFT support {}\n" msgstr "\tSoporte netCDF activado\n" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "\tTamaño de la malla (`grid`): " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 #, fuzzy msgid "\tGuard cells (x,y,z): " msgstr "\tProteger celdas (x,y): " @@ -192,17 +197,17 @@ msgstr "" "\tLa entrada no debe contener el carácter ':'\n" "\tLínea: {:s}" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -212,98 +217,95 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "\tMutilples '=' en el argumento de la línea de comandos '{:s}'\n" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, fuzzy, c++-format msgid "\tNetCDF support {}{}\n" msgstr "\tSoporte netCDF activado\n" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, fuzzy, c++-format -msgid "\tOpenMP parallelisation {}" -msgstr "\tParalelización en OpenMP desactivada\n" +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "" +"\tParalelización en OpenMP activada, usando {:d} procesos (`threads`)\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\tOpción " -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, fuzzy, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "\tOpción '{:s}': valor Booleano esperado. Se obtuvo '{:s}'\n" +msgid "\tOption {} = {}" +msgstr "\tOpción " #: ../src/sys/options/options_ini.cxx:70 #, fuzzy, c++-format msgid "\tOptions file '{:s}' not found\n" msgstr "\tOpciones de archivo '{:s}' no encontrados\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "\tSoporte para NetCDF paralelo desactivado\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "\tSoporte para NetCDF paralelo activado\n" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "\tLeer nz del archivo input de la malla `grid`\n" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "\tLeyendo vector contravariante " -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "\tLeyendo vector covariante " -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, fuzzy, c++-format msgid "\tSignal handling support {}\n" msgstr "\tGestión de señal desactivada\n" @@ -313,7 +315,7 @@ msgstr "\tGestión de señal desactivada\n" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "\tlisto\n" @@ -323,7 +325,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 #, fuzzy msgid "" "\n" @@ -343,7 +345,7 @@ msgstr "" " -v, --verbose\t\tAumentar verbosidad\n" " -q, --quiet\t\tDisminuir verbosidad\n" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -351,7 +353,7 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, fuzzy, c++-format msgid "" "\n" @@ -360,7 +362,7 @@ msgstr "" "\n" "Ejecución finalizada en : {:s}\n" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, fuzzy, c++-format msgid "" "\n" @@ -372,7 +374,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -400,7 +402,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -433,57 +435,57 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 #, fuzzy msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr " -c, --color\t\tSalida de color usando bout-log-color\n" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" msgstr "" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "Usando todas las opciones\n" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, fuzzy, c++-format msgid "BOUT++ version {:s}\n" msgstr "Versión de BOUT++ {:s}\n" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 #, fuzzy msgid "Bad command line arguments:\n" msgstr "\tMutilples '=' en el argumento de la línea de comandos '{:s}'\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "Regiones frontera en este procesador: " -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, fuzzy, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "No se pueden dividir {:d} X points entre {:d} procesadores por igual\n" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, fuzzy, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -496,7 +498,7 @@ msgstr "" msgid "Command line" msgstr "Línea de comandos" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "Opciones de tiempo de compilación:\n" @@ -505,16 +507,16 @@ msgstr "Opciones de tiempo de compilación:\n" msgid "Compiled with flags" msgstr "\tCompilado con las opciones `flags` : {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "Construyendo regiones por defecto" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, fuzzy, c++-format msgid "Could not create PID file {:s}" msgstr "No se pudo abrir el archivo de salida `output` '{:s}'\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "" @@ -526,30 +528,30 @@ msgstr "" msgid "Could not open output file '{:s}'\n" msgstr "No se pudo abrir el archivo de salida `output` '{:s}'\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, fuzzy, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "No se pudo leer la matriz de enteros '{:s}'\n" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" "No se pudo ejecutar bout-log-color. Asegúrese de que se encuentre en su " "PATH\n" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, fuzzy, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "No se pudo añadir el Monitor: {:g} no és multiplo de {:g}!" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -558,69 +560,69 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, fuzzy, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "No se pudo encontrar la región {:s} en regionMap2D" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, fuzzy, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "No se pudo encontrar la región {:s} en regionMap2D" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, fuzzy, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "No se pudo encontrar la región {:s} en regionMapPerp" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, fuzzy, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "No se pudo recuperar el entero de la opción {:s} = '{:s}'" -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, fuzzy, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "DataDir \"{:s}\" no existe o no es accessible\n" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, fuzzy, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "DataDir \"{:s}\" no es un directorio\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "ERROR: el Solver ya se encuentra inicializado\n" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, fuzzy, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "Error encontrado durante la inicialización:{:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "Error durante el paso de opciones" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, fuzzy, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "Error: nx debe ser mayor que 2 veces MXG (2 * {:d})" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "Fallo en inicializar el solver-> Abortando\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, fuzzy, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "Encontrando valor para NXPE (ideal = {:f})\n" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "Initializando el solver\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -633,48 +635,48 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "Cargando malla `mesh`" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "La malla `mesh` debe contener nx" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "La malla `mesh` debe contener ny" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, fuzzy, c++-format msgid "Missing integer array {:s}\n" msgstr "Fala la matriz entera {:s}\n" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, fuzzy, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "Monitor indicó salir\n" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, fuzzy, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "Monitor indicó salir" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "Sin regiones de frontera en este procesador" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 #, fuzzy msgid "No boundary regions; domain is periodic\n" msgstr "Sin regiones de frontera en este procesador" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, fuzzy, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" @@ -682,7 +684,7 @@ msgstr "" "Número de procesadores ({:d}) no divisible para NPs en la dirección x " "({:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, fuzzy, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" @@ -691,26 +693,26 @@ msgstr "" "({:d})\n" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, fuzzy, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "Solo faltan {:e} segundos. Saliendo\n" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, fuzzy, c++-format msgid "Option {:s} has no value" msgstr "Opción {:s} sin valor" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, fuzzy, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "Opción {:s}:{:s} no existe" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, fuzzy, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " @@ -719,12 +721,12 @@ msgstr "" "Opciones: Cambiando valor de la misma fuente ({:s}) al valor nuevo '{:s}' - " "valor anterior era '{:s}'." -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 #, fuzzy msgid "Possible boundary regions are: " msgstr "Sin regiones de frontera en este procesador" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, fuzzy, c++-format msgid "" "Processor number: {:d} of {:d}\n" @@ -733,32 +735,32 @@ msgstr "" "Procesador número: {:d} de {:d}\n" "\n" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, fuzzy, c++-format msgid "Registered region 2D {:s}" msgstr "Región 2D registrada {:s}" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, fuzzy, c++-format msgid "Registered region 3D {:s}" msgstr "Región 3D registrada {:s}" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, fuzzy, c++-format msgid "Registered region Perp {:s}" msgstr "Región Perp registrada {:s}" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, fuzzy, c++-format msgid "Revision: {:s}\n" msgstr "Revisión: {:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "Tiempo de ejecución : " #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -770,7 +772,7 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" @@ -779,7 +781,7 @@ msgstr "" "SOLVER\n" "\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -789,21 +791,21 @@ msgstr "" "Com I/O SOLVER\n" "\n" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, fuzzy, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" "Solver corriendo para {:d} outputs con intervalos de tiempo de monitor de " "{:e}\n" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, fuzzy, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" "Solver corriendo para {:d} outputs con intervalos de tiempo de output de " "{:e}\n" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, fuzzy, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " @@ -812,7 +814,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:1281 +#: ../src/solver/solver.cxx:1289 #, fuzzy, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " @@ -821,27 +823,27 @@ 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:1480 +#: ../src/solver/solver.cxx:1494 #, fuzzy, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "Derivada del tiempo para la variable '{:s}' no fijada" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, fuzzy, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "Intentando añadir una región ya existente {:s} a regionMap2D" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, fuzzy, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "Intentando añadir una región ya existente {:s} a regionMap3D" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, fuzzy, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "Intentando añadir una región ya existente {:s} a regionMapPerp" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -850,7 +852,7 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" @@ -858,31 +860,31 @@ msgstr "" "Opción paralleltransform desconocida.\n" "Opciones válidas son 'identity', 'shifted', 'fci'" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "Opciones sin usar:\n" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, fuzzy, c++-format msgid "Usage is {:s} -d \n" msgstr "Correcto uso es {:s} -d \n" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, fuzzy, c++-format msgid "Usage is {:s} -f \n" msgstr "Correcto uso es {:s} -f \n" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, fuzzy, c++-format msgid "Usage is {:s} -l \n" msgstr "Correcto uso es {:s} -l \n" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, fuzzy, c++-format msgid "Usage is {:s} -o \n" msgstr "Correcto uso es {:s} -o \n" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, fuzzy, c++-format msgid "Usage is {} {} \n" msgstr "Correcto uso es {:s} -l \n" @@ -893,7 +895,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, fuzzy, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -903,68 +905,73 @@ msgstr "" "[VAR=VALUE]\n" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 #, fuzzy msgid "User signalled to quit. Returning\n" msgstr "Monitor indicó salir\n" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, fuzzy, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "Valor para la opción {:s} = {:e} no es un entero" + +#: ../src/sys/options.cxx:426 #, fuzzy, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "Valor para la opción {:s} = {:e} no es un entero" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, fuzzy, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "Valor para la opción {:s} = {:e} no es un entero" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, fuzzy, c++-format 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:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, fuzzy, c++-format msgid "Variable '{:s}' not initialised" msgstr "Variable '{:s}' sin inicializar" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, fuzzy, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " @@ -973,27 +980,27 @@ 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:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -1003,10 +1010,18 @@ msgid "Writing options to file {:s}\n" msgstr "Escribiendo opciones a archivo {:s}\n" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "por defecto" +#, fuzzy, c++-format +#~ msgid "\tOpenMP parallelisation {}" +#~ msgstr "\tParalelización en OpenMP desactivada\n" + +#, fuzzy, c++-format +#~ msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +#~ msgstr "\tOpción '{:s}': valor Booleano esperado. Se obtuvo '{:s}'\n" + #~ msgid "\tChecking disabled\n" #~ msgstr "\tComprobación desactivada\n" @@ -1014,11 +1029,6 @@ msgstr "por defecto" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\tComprobación activada, nivel {:d}\n" -#, fuzzy -#~ msgid "\tOpenMP parallelisation enabled, using {:d} threads\n" -#~ msgstr "" -#~ "\tParalelización en OpenMP activada, usando {:d} procesos (`threads`)\n" - #~ msgid "\tSignal handling enabled\n" #~ msgstr "\tGestión de señal activada\n" diff --git a/locale/fr/libbout.po b/locale/fr/libbout.po index ae88b8953c..e9b5476696 100644 --- a/locale/fr/libbout.po +++ b/locale/fr/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2018-10-21 22:46+0100\n" "Last-Translator: \n" "Language-Team: French\n" @@ -17,65 +17,70 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -83,40 +88,40 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, c++-format msgid "\tCandidate value: {:d}\n" msgstr "" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -133,31 +138,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " msgstr "" @@ -168,17 +173,17 @@ msgid "" "\tLine: {:s}" msgstr "" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -188,35 +193,31 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, c++-format msgid "\tNetCDF support {}{}\n" msgstr "" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, c++-format -msgid "\tOpenMP parallelisation {}" +msgid "\tOpenMP parallelisation {}, using {} threads\n" msgstr "" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "" -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +msgid "\tOption {} = {}" msgstr "" #: ../src/sys/options/options_ini.cxx:70 @@ -224,62 +225,62 @@ msgstr "" msgid "\tOptions file '{:s}' not found\n" msgstr "" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "" -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "" -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, fuzzy, c++-format msgid "\tSignal handling support {}\n" msgstr "\tTraitement du signal désactivé\n" @@ -289,7 +290,7 @@ msgstr "\tTraitement du signal désactivé\n" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "" @@ -299,7 +300,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -310,7 +311,7 @@ msgid "" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -318,7 +319,7 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, fuzzy, c++-format msgid "" "\n" @@ -327,7 +328,7 @@ msgstr "" "\n" "L'exécution se termine à {:s}\n" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, fuzzy, c++-format msgid "" "\n" @@ -339,7 +340,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -367,7 +368,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -400,55 +401,55 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" msgstr "" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, c++-format msgid "BOUT++ version {:s}\n" msgstr "" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, fuzzy, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -461,7 +462,7 @@ msgstr "" msgid "Command line" msgstr "" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "" @@ -469,16 +470,16 @@ msgstr "" msgid "Compiled with flags" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, c++-format msgid "Could not create PID file {:s}" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "" @@ -488,28 +489,28 @@ msgstr "" msgid "Could not open output file '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -518,70 +519,70 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "" -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, fuzzy, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "" "Le répertoire de données \"{:s}\" n'existe pas ou n'est pas accessible\n" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, fuzzy, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "\"{:s}\" n'est pas un répertoire\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, fuzzy, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "Erreur rencontrée lors de l'initialisation : {:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "Échec d'initialisation du solutionneur -> Abandonner\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -591,122 +592,122 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, c++-format msgid "Option {:s} has no value" msgstr "" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" msgstr "" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, c++-format msgid "Revision: {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "Temps d'exécution : " #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -718,66 +719,66 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, fuzzy, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" "Le solveur fonctionne pour {:d} sorties avec un temps de moniteur de {:e}\n" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, fuzzy, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" "Le solveur fonctionne pour {:d} sorties avec un pas de sortie de {:e}\n" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -786,37 +787,37 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" @@ -827,7 +828,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -835,94 +836,99 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, fuzzy, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "\"{:s}\" n'est pas un répertoire\n" + +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -932,7 +938,7 @@ msgid "Writing options to file {:s}\n" msgstr "" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "" @@ -946,10 +952,6 @@ msgstr "" #~ msgid "\tSignal handling enabled\n" #~ msgstr "\tTraitement du signal activé\n" -#, fuzzy -#~ msgid "Option {:s} is not a section" -#~ msgstr "\"{:s}\" n'est pas un répertoire\n" - #, fuzzy #~ msgid "Error encountered during initialisation\n" #~ msgstr "Erreur rencontrée lors de l'initialisation\n" diff --git a/locale/libbout.pot b/locale/libbout.pot index 3895001ba0..2ef0618dd0 100644 --- a/locale/libbout.pot +++ b/locale/libbout.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,65 +17,70 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -83,40 +88,40 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, c++-format msgid "\tCandidate value: {:d}\n" msgstr "" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -133,31 +138,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " msgstr "" @@ -168,17 +173,17 @@ msgid "" "\tLine: {:s}" msgstr "" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -188,35 +193,31 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, c++-format msgid "\tNetCDF support {}{}\n" msgstr "" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, c++-format -msgid "\tOpenMP parallelisation {}" +msgid "\tOpenMP parallelisation {}, using {} threads\n" msgstr "" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "" -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +msgid "\tOption {} = {}" msgstr "" #: ../src/sys/options/options_ini.cxx:70 @@ -224,62 +225,62 @@ msgstr "" msgid "\tOptions file '{:s}' not found\n" msgstr "" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "" -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "" -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, c++-format msgid "\tSignal handling support {}\n" msgstr "" @@ -289,7 +290,7 @@ msgstr "" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "" @@ -299,7 +300,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -310,7 +311,7 @@ msgid "" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -318,14 +319,14 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, c++-format msgid "" "\n" "Run finished at : {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, c++-format msgid "" "\n" @@ -335,7 +336,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -363,7 +364,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -396,55 +397,55 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" msgstr "" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, c++-format msgid "BOUT++ version {:s}\n" msgstr "" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -455,7 +456,7 @@ msgstr "" msgid "Command line" msgstr "" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "" @@ -463,16 +464,16 @@ msgstr "" msgid "Compiled with flags" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, c++-format msgid "Could not create PID file {:s}" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "" @@ -482,28 +483,28 @@ msgstr "" msgid "Could not open output file '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -512,69 +513,69 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "" -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -584,122 +585,122 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, c++-format msgid "Option {:s} has no value" msgstr "" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" msgstr "" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, c++-format msgid "Revision: {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "" #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -709,64 +710,64 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -775,37 +776,37 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" @@ -816,7 +817,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -824,94 +825,99 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "" + +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -921,6 +927,6 @@ msgid "Writing options to file {:s}\n" msgstr "" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "" diff --git a/locale/zh_CN/libbout.po b/locale/zh_CN/libbout.po index 2c53b5392c..ecf8517d62 100644 --- a/locale/zh_CN/libbout.po +++ b/locale/zh_CN/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2018-10-22 22:56+0100\n" "Last-Translator: \n" "Language-Team: Chinese (simplified)\n" @@ -16,65 +16,70 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" #: ../src/bout++.cxx:575 #, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "" + +#: ../src/bout++.cxx:583 +#, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -82,40 +87,40 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, c++-format msgid "\tCandidate value: {:d}\n" msgstr "" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -132,31 +137,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " msgstr "" @@ -167,17 +172,17 @@ msgid "" "\tLine: {:s}" msgstr "" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -187,98 +192,94 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, c++-format msgid "\tNetCDF support {}{}\n" msgstr "" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, c++-format -msgid "\tOpenMP parallelisation {}" +msgid "\tOpenMP parallelisation {}, using {} threads\n" msgstr "" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\t选项 " -#: ../src/sys/options.cxx:447 -#, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "" +#: ../src/sys/options.cxx:369 +#, fuzzy, c++-format +msgid "\tOption {} = {}" +msgstr "\t选项 " #: ../src/sys/options/options_ini.cxx:70 #, c++-format msgid "\tOptions file '{:s}' not found\n" msgstr "" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 msgid "\tParallel NetCDF support disabled\n" msgstr "" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "" -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "" -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, fuzzy, c++-format msgid "\tSignal handling support {}\n" msgstr "\t测试关掉\n" @@ -288,7 +289,7 @@ msgstr "\t测试关掉\n" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "" @@ -298,7 +299,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -309,7 +310,7 @@ msgid "" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -317,7 +318,7 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, fuzzy, c++-format msgid "" "\n" @@ -326,7 +327,7 @@ msgstr "" "\n" "计算结束于 {:s}\n" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, fuzzy, c++-format msgid "" "\n" @@ -338,7 +339,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -366,7 +367,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -399,55 +400,55 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" msgstr "" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, c++-format msgid "BOUT++ version {:s}\n" msgstr "" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, fuzzy, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -460,7 +461,7 @@ msgstr "" msgid "Command line" msgstr "" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "" @@ -468,16 +469,16 @@ msgstr "" msgid "Compiled with flags" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, c++-format msgid "Could not create PID file {:s}" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "" @@ -487,28 +488,28 @@ msgstr "" msgid "Could not open output file '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -517,69 +518,69 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "" -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, fuzzy, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "\"{:s}\" 不存在或不可访问\n" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, fuzzy, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "\"{:s}\" 不是目录\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, fuzzy, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "启动时遇到错误 : {:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -589,122 +590,122 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, c++-format msgid "Option {:s} has no value" msgstr "" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" msgstr "" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, c++-format msgid "Revision: {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "计算时间" #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -716,64 +717,64 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" "\n" msgstr "" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -782,37 +783,37 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" @@ -823,7 +824,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -831,94 +832,99 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, fuzzy, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "\"{:s}\" 不是目录\n" + +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -928,7 +934,7 @@ msgid "Writing options to file {:s}\n" msgstr "" #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "" @@ -939,9 +945,5 @@ msgstr "" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\t测试打开,级别 {:d}\n" -#, fuzzy -#~ msgid "Option {:s} is not a section" -#~ msgstr "\"{:s}\" 不是目录\n" - #~ msgid "Error encountered during initialisation\n" #~ msgstr "启动时遇到错误\n" diff --git a/locale/zh_TW/libbout.po b/locale/zh_TW/libbout.po index de0230d68d..abf44db51f 100644 --- a/locale/zh_TW/libbout.po +++ b/locale/zh_TW/libbout.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: BOUT++ 4.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-12 09:17+0100\n" +"POT-Creation-Date: 2025-08-13 23:37+0100\n" "PO-Revision-Date: 2018-10-22 22:56+0100\n" "Last-Translator: \n" "Language-Team: Chinese (traditional)\n" @@ -16,64 +16,69 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:191 +#: ../src/mesh/impls/bout/boutmesh.cxx:182 #, c++-format msgid "" "\t -> Core region jyseps2_1-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:224 +#: ../src/mesh/impls/bout/boutmesh.cxx:215 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_1 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:199 +#: ../src/mesh/impls/bout/boutmesh.cxx:190 #, c++-format msgid "" "\t -> Core region jyseps2_2-jyseps1_2 ({:d}-{:d} = {:d}) must be a multiple " "of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:309 +#: ../src/mesh/impls/bout/boutmesh.cxx:300 msgid "\t -> Good value\n" msgstr "\t -> 好的號碼\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:180 +#: ../src/mesh/impls/bout/boutmesh.cxx:171 #, c++-format msgid "" "\t -> Leg region jyseps1_1+1 ({:d}) must be a multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:215 +#: ../src/mesh/impls/bout/boutmesh.cxx:206 #, c++-format msgid "" "\t -> leg region jyseps1_2-ny_inner+1 ({:d}-{:d}+1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:232 +#: ../src/mesh/impls/bout/boutmesh.cxx:223 #, c++-format msgid "" "\t -> leg region ny-jyseps2_2-1 ({:d}-{:d}-1 = {:d}) must be a multiple of " "MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:208 +#: ../src/mesh/impls/bout/boutmesh.cxx:199 #, c++-format msgid "" "\t -> leg region ny_inner-jyseps2_1-1 ({:d}-{:d}-1 = {:d}) must be a " "multiple of MYSUB ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:175 +#: ../src/mesh/impls/bout/boutmesh.cxx:166 #, c++-format msgid "\t -> ny/NYPE ({:d}/{:d} = {:d}) must be >= MYG ({:d})\n" msgstr "" #: ../src/bout++.cxx:575 +#, fuzzy, c++-format +msgid "\tADIOS2 support {}\n" +msgstr "\tOpenMP並行化已禁用\n" + +#: ../src/bout++.cxx:583 #, c++-format msgid "\tBacktrace in exceptions {}\n" msgstr "" @@ -82,40 +87,40 @@ msgstr "" #. Processors divide equally #. Mesh in X divides equally #. Mesh in Y divides equally -#: ../src/mesh/impls/bout/boutmesh.cxx:297 +#: ../src/mesh/impls/bout/boutmesh.cxx:288 #, fuzzy, c++-format msgid "\tCandidate value: {:d}\n" msgstr "\t候選人數目 {:d}\n" -#: ../src/bout++.cxx:576 +#: ../src/bout++.cxx:584 #, c++-format msgid "\tColour in logs {}\n" msgstr "" -#: ../src/bout++.cxx:594 +#: ../src/bout++.cxx:599 msgid "\tCommand line options for this run : " msgstr "" #. The stringify is needed here as BOUT_FLAGS_STRING may already contain quoted strings #. which could cause problems (e.g. terminate strings). -#: ../src/bout++.cxx:590 +#: ../src/bout++.cxx:595 #, fuzzy, c++-format msgid "\tCompiled with flags : {:s}\n" msgstr "\t用設置編譯: {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:324 +#: ../src/mesh/impls/bout/boutmesh.cxx:315 #, fuzzy, c++-format msgid "" "\tDomain split (NXPE={:d}, NYPE={:d}) into domains (localNx={:d}, " "localNy={:d})\n" msgstr "\t域 (NXPE={:d}, NYPE={:d}) 分裂成域 (localNx={:d}, localNy={:d})\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:364 +#: ../src/mesh/impls/bout/boutmesh.cxx:357 #, c++-format msgid "\tERROR: Cannot split {:d} Y points equally between {:d} processors\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:372 +#: ../src/mesh/impls/bout/boutmesh.cxx:365 #, c++-format msgid "\tERROR: Cannot split {:d} Z points equally between {:d} processors\n" msgstr "" @@ -132,31 +137,31 @@ msgstr "" msgid "\tEmpty key or value in command line '{:s}'\n" msgstr "\t命令行中的空鍵或值 '{:s}'\n" -#: ../src/bout++.cxx:582 +#: ../src/bout++.cxx:587 #, c++-format msgid "\tExtra debug output {}\n" msgstr "" -#: ../src/bout++.cxx:561 +#: ../src/bout++.cxx:568 #, c++-format msgid "\tFFT support {}\n" msgstr "" -#: ../src/bout++.cxx:585 +#: ../src/bout++.cxx:590 #, c++-format msgid "\tField name tracking {}\n" msgstr "" -#: ../src/bout++.cxx:583 +#: ../src/bout++.cxx:588 #, c++-format msgid "\tFloating-point exceptions {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:440 +#: ../src/mesh/impls/bout/boutmesh.cxx:476 msgid "\tGrid size: " msgstr "\t網格大小: " -#: ../src/mesh/impls/bout/boutmesh.cxx:463 +#: ../src/mesh/impls/bout/boutmesh.cxx:499 msgid "\tGuard cells (x,y,z): " msgstr "" @@ -167,17 +172,17 @@ msgid "" "\tLine: {:s}" msgstr "" -#: ../src/bout++.cxx:563 +#: ../src/bout++.cxx:570 #, c++-format msgid "\tLAPACK support {}\n" msgstr "" -#: ../src/bout++.cxx:586 +#: ../src/bout++.cxx:591 #, c++-format msgid "\tMessage stack {}\n" msgstr "" -#: ../src/bout++.cxx:560 +#: ../src/bout++.cxx:567 #, c++-format msgid "\tMetrics mode is {}\n" msgstr "" @@ -187,99 +192,95 @@ msgstr "" msgid "\tMultiple '=' in command-line argument '{:s}'\n" msgstr "" -#: ../src/bout++.cxx:562 +#: ../src/bout++.cxx:569 #, c++-format msgid "\tNatural language support {}\n" msgstr "" -#: ../src/bout++.cxx:567 +#: ../src/bout++.cxx:574 #, fuzzy, c++-format msgid "\tNetCDF support {}{}\n" msgstr "\tOpenMP並行化已禁用\n" -#: ../src/bout++.cxx:577 +#: ../src/bout++.cxx:585 #, fuzzy, c++-format -msgid "\tOpenMP parallelisation {}" -msgstr "\tOpenMP並行化已禁用\n" +msgid "\tOpenMP parallelisation {}, using {} threads\n" +msgstr "\t啟用OpenMP並行化。 使用{:d}個線程\n" #. Mark the option as used #. Option not found -#: ../src/sys/options.cxx:311 ../src/sys/options.cxx:380 -#: ../src/sys/options.cxx:415 ../src/sys/options.cxx:457 -#: ../src/sys/options.cxx:717 ../src/sys/options.cxx:744 -#: ../src/sys/options.cxx:771 ../include/bout/options.hxx:516 -#: ../include/bout/options.hxx:549 ../include/bout/options.hxx:573 -#: ../include/bout/options.hxx:820 +#: ../include/bout/options.hxx:586 ../include/bout/options.hxx:619 +#: ../include/bout/options.hxx:643 ../include/bout/options.hxx:896 msgid "\tOption " msgstr "\t選項 " -#: ../src/sys/options.cxx:447 +#: ../src/sys/options.cxx:369 #, fuzzy, c++-format -msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" -msgstr "\t選項 '{:s}': 布爾預期. 拿到 '{:s}'\n" +msgid "\tOption {} = {}" +msgstr "\t選項 " #: ../src/sys/options/options_ini.cxx:70 #, fuzzy, c++-format msgid "\tOptions file '{:s}' not found\n" msgstr "\t找不到選項文件 '{:s}'\n" -#: ../src/bout++.cxx:568 +#: ../src/bout++.cxx:576 #, c++-format msgid "\tPETSc support {}\n" msgstr "" -#: ../src/bout++.cxx:571 +#: ../src/bout++.cxx:579 #, c++-format msgid "\tPVODE support {}\n" msgstr "" -#: ../src/bout++.cxx:557 +#: ../src/bout++.cxx:564 #, fuzzy msgid "\tParallel NetCDF support disabled\n" msgstr "\tOpenMP並行化已禁用\n" -#: ../src/bout++.cxx:555 +#: ../src/bout++.cxx:562 msgid "\tParallel NetCDF support enabled\n" msgstr "" -#: ../src/bout++.cxx:569 +#: ../src/bout++.cxx:577 #, c++-format msgid "\tPretty function name support {}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:437 +#: ../src/mesh/impls/bout/boutmesh.cxx:473 msgid "\tRead nz from input grid file\n" msgstr "" -#: ../src/mesh/mesh.cxx:238 +#: ../src/mesh/mesh.cxx:249 msgid "\tReading contravariant vector " msgstr "" -#: ../src/mesh/mesh.cxx:231 ../src/mesh/mesh.cxx:252 +#: ../src/mesh/mesh.cxx:242 ../src/mesh/mesh.cxx:263 msgid "\tReading covariant vector " msgstr "" -#: ../src/bout++.cxx:548 +#: ../src/bout++.cxx:555 #, c++-format msgid "\tRuntime error checking {}" msgstr "" -#: ../src/bout++.cxx:573 +#: ../src/bout++.cxx:581 #, c++-format msgid "\tSLEPc support {}\n" msgstr "" -#: ../src/bout++.cxx:574 +#: ../src/bout++.cxx:582 #, c++-format msgid "\tSUNDIALS support {}\n" msgstr "" -#: ../src/bout++.cxx:572 +#: ../src/bout++.cxx:580 #, c++-format msgid "\tScore-P support {}\n" msgstr "" -#: ../src/bout++.cxx:584 +#: ../src/bout++.cxx:589 #, fuzzy, c++-format msgid "\tSignal handling support {}\n" msgstr "\t測試關掉\n" @@ -289,7 +290,7 @@ msgstr "\t測試關掉\n" msgid "\tUsing a timestep {:e}\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:577 +#: ../src/mesh/impls/bout/boutmesh.cxx:613 msgid "\tdone\n" msgstr "\t完\n" @@ -299,7 +300,7 @@ msgid "" "\tSplit Runge-Kutta-Legendre and SSP-RK3 solver\n" msgstr "" -#: ../src/bout++.cxx:371 +#: ../src/bout++.cxx:378 msgid "" "\n" " -d \t\tLook in for input/output files\n" @@ -310,7 +311,7 @@ msgid "" " -q, --quiet\t\t\tDecrease verbosity\n" msgstr "" -#: ../src/sys/expressionparser.cxx:302 +#: ../src/sys/expressionparser.cxx:341 #, c++-format msgid "" "\n" @@ -318,7 +319,7 @@ msgid "" " Did you mean '{0}'?" msgstr "" -#: ../src/solver/solver.cxx:580 +#: ../src/solver/solver.cxx:586 #, fuzzy, c++-format msgid "" "\n" @@ -327,7 +328,7 @@ msgstr "" "\n" "计算结束于 {:s}\n" -#: ../src/solver/solver.cxx:532 +#: ../src/solver/solver.cxx:540 #, fuzzy, c++-format msgid "" "\n" @@ -339,7 +340,7 @@ msgstr "" #. Raw string to help with the formatting of the message, and a #. separate variable so clang-format doesn't barf on the #. exception -#: ../src/sys/options.cxx:1102 +#: ../src/sys/options.cxx:1158 msgid "" "\n" "There were unused input options:\n" @@ -367,7 +368,7 @@ msgid "" "{}" msgstr "" -#: ../src/bout++.cxx:382 +#: ../src/bout++.cxx:389 #, c++-format msgid "" " --print-config\t\tPrint the compile-time configuration\n" @@ -400,55 +401,55 @@ msgid "" "model source (e.g. {:s}.cxx)\n" msgstr "" -#: ../src/bout++.cxx:379 +#: ../src/bout++.cxx:386 msgid " -c, --color\t\t\tColor output using bout-log-color\n" msgstr "" -#: ../include/bout/options.hxx:823 +#: ../include/bout/options.hxx:899 msgid ") overwritten with:" msgstr "" -#: ../src/bout++.cxx:550 +#: ../src/bout++.cxx:557 #, c++-format msgid ", level {}" msgstr "" -#: ../src/bout++.cxx:579 -#, c++-format -msgid ", using {} threads" -msgstr "" - #: ../tests/unit/src/test_bout++.cxx:352 msgid "4 of 8" msgstr "" -#: ../src/sys/options.cxx:868 +#: ../src/sys/options.cxx:895 msgid "All options used\n" msgstr "" -#: ../src/bout++.cxx:528 +#: ../src/bout++.cxx:535 #, fuzzy, c++-format msgid "BOUT++ version {:s}\n" msgstr "BOUT++ 版 {:s}\n" -#: ../src/bout++.cxx:143 +#: ../src/bout++.cxx:147 msgid "Bad command line arguments:\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:559 +#: ../src/sys/expressionparser.cxx:192 +#, c++-format +msgid "Boolean operator argument {:e} is not a bool" +msgstr "" + +#: ../src/mesh/impls/bout/boutmesh.cxx:595 msgid "Boundary regions in this processor: " msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:355 +#: ../src/mesh/impls/bout/boutmesh.cxx:348 #, c++-format msgid "Cannot split {:d} X points equally between {:d} processors\n" msgstr "" -#: ../src/bout++.cxx:818 +#: ../src/bout++.cxx:829 msgid "Check if a file exists, and exit if it does." msgstr "" -#: ../src/bout++.cxx:533 +#: ../src/bout++.cxx:540 #, fuzzy, c++-format msgid "" "Code compiled on {:s} at {:s}\n" @@ -461,7 +462,7 @@ msgstr "" msgid "Command line" msgstr "" -#: ../src/bout++.cxx:544 ../tests/unit/src/test_bout++.cxx:358 +#: ../src/bout++.cxx:551 ../tests/unit/src/test_bout++.cxx:358 msgid "Compile-time options:\n" msgstr "編譯選項:\n" @@ -470,16 +471,16 @@ msgstr "編譯選項:\n" msgid "Compiled with flags" msgstr "\t用設置編譯: {:s}\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:568 +#: ../src/mesh/impls/bout/boutmesh.cxx:604 msgid "Constructing default regions" msgstr "" -#: ../src/bout++.cxx:520 +#: ../src/bout++.cxx:527 #, fuzzy, c++-format msgid "Could not create PID file {:s}" msgstr "無法打開輸出文件 '{:s}'\n" -#: ../src/mesh/impls/bout/boutmesh.cxx:318 +#: ../src/mesh/impls/bout/boutmesh.cxx:309 msgid "" "Could not find a valid value for NXPE. Try a different number of processors." msgstr "無法找到NXPE的有效值。 嘗試不同數量的處理器。" @@ -489,28 +490,28 @@ msgstr "無法找到NXPE的有效值。 嘗試不同數量的處理器。" msgid "Could not open output file '{:s}'\n" msgstr "無法打開輸出文件 '{:s}'\n" -#: ../src/bout++.cxx:652 +#: ../src/bout++.cxx:657 #, c++-format msgid "Could not open {:s}/{:s}.{:d} for writing" msgstr "" #. Error reading -#: ../src/mesh/mesh.cxx:532 +#: ../src/mesh/mesh.cxx:543 #, c++-format msgid "Could not read integer array '{:s}'\n" msgstr "" #. Failed . Probably not important enough to stop the simulation -#: ../src/bout++.cxx:632 +#: ../src/bout++.cxx:637 msgid "Could not run bout-log-color. Make sure it is in your PATH\n" msgstr "" -#: ../src/solver/solver.cxx:765 +#: ../src/solver/solver.cxx:772 #, c++-format msgid "Couldn't add Monitor: {:g} is not a multiple of {:g}!" msgstr "" -#: ../src/sys/expressionparser.cxx:273 +#: ../src/sys/expressionparser.cxx:312 #, c++-format msgid "" "Couldn't find generator '{}'. BOUT++ expressions are now case-sensitive, so " @@ -519,69 +520,69 @@ msgid "" "{}" msgstr "" -#: ../src/mesh/mesh.cxx:568 +#: ../src/mesh/mesh.cxx:587 #, c++-format msgid "Couldn't find region {:s} in regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:560 +#: ../src/mesh/mesh.cxx:571 ../src/mesh/mesh.cxx:579 #, c++-format msgid "Couldn't find region {:s} in regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:576 +#: ../src/mesh/mesh.cxx:595 #, c++-format msgid "Couldn't find region {:s} in regionMapPerp" msgstr "" #. Convert any exceptions to something a bit more useful -#: ../src/sys/options.cxx:336 +#: ../src/sys/options.cxx:361 #, c++-format msgid "Couldn't get {} from option {:s} = '{:s}': {}" msgstr "" -#: ../src/bout++.cxx:508 +#: ../src/bout++.cxx:515 #, fuzzy, c++-format msgid "DataDir \"{:s}\" does not exist or is not accessible\n" msgstr "\"{:s}\" 不存在或不可訪問\n" -#: ../src/bout++.cxx:505 +#: ../src/bout++.cxx:512 #, fuzzy, c++-format msgid "DataDir \"{:s}\" is not a directory\n" msgstr "\"{:s}\" 不是目錄\n" -#: ../src/solver/solver.cxx:665 +#: ../src/solver/solver.cxx:671 msgid "ERROR: Solver is already initialised\n" msgstr "" -#: ../src/bout++.cxx:209 +#: ../src/bout++.cxx:216 #, fuzzy, c++-format msgid "Error encountered during initialisation: {:s}\n" msgstr "啟動時遇到錯誤 : {:s}\n" -#: ../src/bout++.cxx:744 +#: ../src/bout++.cxx:751 msgid "Error whilst writing settings" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:332 +#: ../src/mesh/impls/bout/boutmesh.cxx:323 #, c++-format msgid "Error: nx must be greater than 2 times MXG (2 * {:d})" msgstr "" -#: ../src/solver/solver.cxx:512 +#: ../src/solver/solver.cxx:520 msgid "Failed to initialise solver-> Aborting\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:290 +#: ../src/mesh/impls/bout/boutmesh.cxx:281 #, c++-format msgid "Finding value for NXPE (ideal = {:f})\n" msgstr "" -#: ../src/solver/solver.cxx:668 +#: ../src/solver/solver.cxx:674 msgid "Initialising solver\n" msgstr "初始化求解器\n" -#: ../src/bout++.cxx:494 +#: ../src/bout++.cxx:501 msgid "" "Input and output file for settings must be different.\n" "Provide -o to avoid this issue.\n" @@ -591,122 +592,122 @@ msgstr "" msgid "Invalid command line option '-' found - maybe check whitespace?" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:400 +#: ../src/mesh/impls/bout/boutmesh.cxx:436 msgid "Loading mesh" msgstr "加載網格" -#: ../src/mesh/impls/bout/boutmesh.cxx:415 +#: ../src/mesh/impls/bout/boutmesh.cxx:451 msgid "Mesh must contain nx" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:419 +#: ../src/mesh/impls/bout/boutmesh.cxx:455 msgid "Mesh must contain ny" msgstr "" #. Not found -#: ../src/mesh/mesh.cxx:536 +#: ../src/mesh/mesh.cxx:547 #, c++-format msgid "Missing integer array {:s}\n" msgstr "" -#: ../src/solver/solver.cxx:905 +#: ../src/solver/solver.cxx:911 #, c++-format msgid "Monitor signalled to quit (exception {})\n" msgstr "" -#: ../src/solver/solver.cxx:883 +#: ../src/solver/solver.cxx:889 #, c++-format msgid "Monitor signalled to quit (return code {})" msgstr "" -#: ../src/bout++.cxx:823 +#: ../src/bout++.cxx:834 msgid "Name of file whose existence triggers a stop" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:565 +#: ../src/mesh/impls/bout/boutmesh.cxx:601 msgid "No boundary regions in this processor" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:550 +#: ../src/mesh/impls/bout/boutmesh.cxx:586 msgid "No boundary regions; domain is periodic\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:254 +#: ../src/mesh/impls/bout/boutmesh.cxx:245 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in x direction ({:d})\n" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:267 +#: ../src/mesh/impls/bout/boutmesh.cxx:258 #, c++-format msgid "" "Number of processors ({:d}) not divisible by NPs in y direction ({:d})\n" msgstr "" #. Less than 2 time-steps left -#: ../src/bout++.cxx:896 +#: ../src/bout++.cxx:908 #, c++-format msgid "Only {:e} seconds ({:.2f} steps) left. Quitting\n" msgstr "" -#: ../src/sys/options.cxx:303 ../src/sys/options.cxx:345 -#: ../src/sys/options.cxx:393 ../src/sys/options.cxx:428 -#: ../src/sys/options.cxx:703 ../src/sys/options.cxx:730 -#: ../src/sys/options.cxx:757 +#: ../src/sys/options.cxx:382 ../src/sys/options.cxx:398 +#: ../src/sys/options.cxx:441 ../src/sys/options.cxx:471 +#: ../src/sys/options.cxx:745 ../src/sys/options.cxx:767 +#: ../src/sys/options.cxx:789 #, fuzzy, c++-format msgid "Option {:s} has no value" msgstr "\"{:s}\" 不是目錄\n" #. Doesn't exist -#: ../src/sys/options.cxx:159 +#: ../src/sys/options.cxx:172 #, fuzzy, c++-format msgid "Option {:s}:{:s} does not exist" msgstr "選項{:s}:{:s}不存在" -#: ../include/bout/options.hxx:828 +#: ../include/bout/options.hxx:904 #, c++-format msgid "" "Options: Setting a value from same source ({:s}) to new value '{:s}' - old " "value was '{:s}'." msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:552 +#: ../src/mesh/impls/bout/boutmesh.cxx:588 msgid "Possible boundary regions are: " msgstr "" -#: ../src/bout++.cxx:538 +#: ../src/bout++.cxx:545 #, c++-format msgid "" "Processor number: {:d} of {:d}\n" "\n" msgstr "" -#: ../src/mesh/mesh.cxx:609 +#: ../src/mesh/mesh.cxx:642 #, c++-format msgid "Registered region 2D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:599 +#: ../src/mesh/mesh.cxx:632 #, c++-format msgid "Registered region 3D {:s}" msgstr "" -#: ../src/mesh/mesh.cxx:619 +#: ../src/mesh/mesh.cxx:652 #, c++-format msgid "Registered region Perp {:s}" msgstr "" -#: ../src/bout++.cxx:529 +#: ../src/bout++.cxx:536 #, fuzzy, c++-format msgid "Revision: {:s}\n" msgstr "版: {:s}\n" -#: ../src/solver/solver.cxx:581 +#: ../src/solver/solver.cxx:587 msgid "Run time : " msgstr "計算時間" #. / Run the solver -#: ../src/solver/solver.cxx:525 +#: ../src/solver/solver.cxx:533 msgid "" "Running simulation\n" "\n" @@ -718,7 +719,7 @@ msgstr "" msgid "Signal" msgstr "" -#: ../src/bout++.cxx:865 +#: ../src/bout++.cxx:876 msgid "" "Sim Time | RHS evals | Wall Time | Calc Inv Comm I/O SOLVER\n" "\n" @@ -727,7 +728,7 @@ msgstr "" "間整合\n" "\n" -#: ../src/bout++.cxx:868 +#: ../src/bout++.cxx:879 msgid "" "Sim Time | RHS_e evals | RHS_I evals | Wall Time | Calc Inv " "Comm I/O SOLVER\n" @@ -737,51 +738,51 @@ msgstr "" "通訊 輸入輸出 時間整合\n" "\n" -#: ../src/solver/solver.cxx:506 +#: ../src/solver/solver.cxx:514 #, c++-format msgid "Solver running for {:d} outputs with monitor timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:502 +#: ../src/solver/solver.cxx:510 #, c++-format msgid "Solver running for {:d} outputs with output timestep of {:e}\n" msgstr "" -#: ../src/solver/solver.cxx:781 +#: ../src/solver/solver.cxx:788 #, c++-format msgid "" "Solver::addMonitor: Cannot reduce timestep (from {:g} to {:g}) after init is " "called!" msgstr "" -#: ../src/solver/solver.cxx:1281 +#: ../src/solver/solver.cxx:1289 #, c++-format msgid "" "Time derivative at wrong location - Field is at {:s}, derivative is at {:s} " "for field '{:s}'\n" msgstr "" -#: ../src/solver/solver.cxx:1480 +#: ../src/solver/solver.cxx:1494 #, c++-format msgid "Time derivative for variable '{:s}' not set" msgstr "" -#: ../src/mesh/mesh.cxx:605 +#: ../src/mesh/mesh.cxx:638 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap2D" msgstr "" -#: ../src/mesh/mesh.cxx:595 +#: ../src/mesh/mesh.cxx:614 #, c++-format msgid "Trying to add an already existing region {:s} to regionMap3D" msgstr "" -#: ../src/mesh/mesh.cxx:616 +#: ../src/mesh/mesh.cxx:649 #, c++-format msgid "Trying to add an already existing region {:s} to regionMapPerp" msgstr "" -#: ../src/sys/options.cxx:99 ../src/sys/options.cxx:138 +#: ../src/sys/options.cxx:112 ../src/sys/options.cxx:151 #, c++-format msgid "" "Trying to index Option '{0}' with '{1}', but '{0}' is a value, not a " @@ -790,37 +791,37 @@ msgid "" "rename one of them.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:1462 +#: ../src/mesh/coordinates.cxx:1464 msgid "" "Unrecognised paralleltransform option.\n" "Valid choices are 'identity', 'shifted', 'fci'" msgstr "" -#: ../src/sys/options.cxx:872 +#: ../src/sys/options.cxx:899 msgid "Unused options:\n" msgstr "" -#: ../src/bout++.cxx:439 +#: ../src/bout++.cxx:446 #, c++-format msgid "Usage is {:s} -d \n" msgstr "" -#: ../src/bout++.cxx:448 +#: ../src/bout++.cxx:455 #, c++-format msgid "Usage is {:s} -f \n" msgstr "" -#: ../src/bout++.cxx:466 +#: ../src/bout++.cxx:473 #, c++-format msgid "Usage is {:s} -l \n" msgstr "" -#: ../src/bout++.cxx:457 +#: ../src/bout++.cxx:464 #, c++-format msgid "Usage is {:s} -o \n" msgstr "" -#: ../src/bout++.cxx:353 +#: ../src/bout++.cxx:360 #, c++-format msgid "Usage is {} {} \n" msgstr "" @@ -831,7 +832,7 @@ msgstr "" #. Print help message -- note this will be displayed once per processor as we've not #. started MPI yet. -#: ../src/bout++.cxx:367 +#: ../src/bout++.cxx:374 #, c++-format msgid "" "Usage: {:s} [-d ] [-f ] [restart [append]] " @@ -839,94 +840,99 @@ msgid "" msgstr "" #. restart file should be written by physics model -#: ../src/solver/solver.cxx:921 +#: ../src/solver/solver.cxx:927 msgid "User signalled to quit. Returning\n" msgstr "" -#: ../src/sys/options.cxx:373 +#: ../src/sys/options.cxx:486 +#, fuzzy, c++-format +msgid "Value for option {:s} = {:e} is not a bool" +msgstr "\"{:s}\" 不是目錄\n" + +#: ../src/sys/options.cxx:426 #, c++-format msgid "Value for option {:s} = {:e} is not an integer" msgstr "" -#: ../src/sys/options.cxx:408 +#: ../src/sys/options.cxx:456 #, c++-format msgid "Value for option {:s} cannot be converted to a BoutReal" msgstr "" -#: ../src/sys/options.cxx:581 +#: ../src/sys/options.cxx:623 #, c++-format msgid "Value for option {:s} cannot be converted to a Field2D" msgstr "" -#: ../src/sys/options.cxx:529 +#: ../src/sys/options.cxx:571 #, c++-format msgid "Value for option {:s} cannot be converted to a Field3D" msgstr "" -#: ../src/sys/options.cxx:663 +#: ../src/sys/options.cxx:705 #, c++-format msgid "Value for option {:s} cannot be converted to a FieldPerp" msgstr "" -#: ../src/sys/options.cxx:451 +#: ../src/sys/options.cxx:491 #, c++-format msgid "Value for option {:s} cannot be converted to a bool" msgstr "" -#: ../src/sys/options.cxx:709 +#: ../src/sys/options.cxx:751 #, c++-format msgid "Value for option {:s} cannot be converted to an Array" msgstr "" -#: ../src/sys/options.cxx:736 +#: ../src/sys/options.cxx:773 #, c++-format msgid "Value for option {:s} cannot be converted to an Matrix" msgstr "" -#: ../src/sys/options.cxx:763 +#: ../src/sys/options.cxx:795 #, c++-format msgid "Value for option {:s} cannot be converted to an Tensor" msgstr "" #. Another type which can't be converted -#: ../src/sys/options.cxx:365 +#: ../src/sys/options.cxx:418 #, c++-format msgid "Value for option {:s} is not an integer" msgstr "" -#: ../src/solver/solver.cxx:1232 ../src/solver/solver.cxx:1238 +#: ../src/solver/solver.cxx:1240 ../src/solver/solver.cxx:1246 #, c++-format msgid "Variable '{:s}' not initialised" msgstr "" -#: ../src/mesh/impls/bout/boutmesh.cxx:431 +#: ../src/mesh/impls/bout/boutmesh.cxx:467 #, c++-format msgid "" "WARNING: Number of toroidal points should be 2^n for efficient FFT " "performance -- consider changing MZ ({:d}) if using FFTs\n" msgstr "" -#: ../src/mesh/coordinates.cxx:633 +#: ../src/mesh/coordinates.cxx:635 msgid "WARNING: extrapolating input mesh quantities into x-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:410 +#: ../src/mesh/coordinates.cxx:412 msgid "" "WARNING: extrapolating input mesh quantities into x-boundary cells. Set " "option extrapolate_x=false to disable this.\n" msgstr "" -#: ../src/mesh/coordinates.cxx:638 +#: ../src/mesh/coordinates.cxx:640 msgid "WARNING: extrapolating input mesh quantities into y-boundary cells\n" msgstr "" -#: ../src/mesh/coordinates.cxx:415 +#: ../src/mesh/coordinates.cxx:417 msgid "" "WARNING: extrapolating input mesh quantities into y-boundary cells. Set " "option extrapolate_y=false to disable this.\n" msgstr "" -#: ../src/bout++.cxx:814 +#: ../src/bout++.cxx:825 msgid "Wall time limit in hours. By default (< 0), no limit" msgstr "" @@ -936,10 +942,18 @@ msgid "Writing options to file {:s}\n" msgstr "寫選項到文件 " #. / The source label given to default values -#: ../src/sys/options.cxx:15 +#: ../src/sys/options.cxx:34 msgid "default" msgstr "默认设置" +#, fuzzy, c++-format +#~ msgid "\tOpenMP parallelisation {}" +#~ msgstr "\tOpenMP並行化已禁用\n" + +#, fuzzy, c++-format +#~ msgid "\tOption '{:s}': Boolean expected. Got '{:s}'\n" +#~ msgstr "\t選項 '{:s}': 布爾預期. 拿到 '{:s}'\n" + #~ msgid "\tChecking disabled\n" #~ msgstr "\t測試關掉\n" @@ -947,13 +961,5 @@ msgstr "默认设置" #~ msgid "\tChecking enabled, level {:d}\n" #~ msgstr "\t測試打開,级别 {:d}\n" -#, fuzzy -#~ msgid "\tOpenMP parallelisation enabled, using {:d} threads\n" -#~ msgstr "\t啟用OpenMP並行化。 使用{:d}個線程\n" - -#, fuzzy -#~ msgid "Option {:s} is not a section" -#~ msgstr "\"{:s}\" 不是目錄\n" - #~ msgid "Error encountered during initialisation\n" #~ msgstr "啟動時遇到錯誤\n" From 84f60c5d8497ee35882218b0f632913c89582fa1 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 10:49:46 +0100 Subject: [PATCH 173/259] Tweak citations updater, mention in docs --- bin/update_citations.py | 10 ++++++++++ manual/RELEASE_HOWTO.md | 5 ++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/bin/update_citations.py b/bin/update_citations.py index c7771a3611..63f597f588 100755 --- a/bin/update_citations.py +++ b/bin/update_citations.py @@ -1,4 +1,11 @@ #!/usr/bin/env python3 +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "ruamel-yaml", +# "unidecode", +# ] +# /// import argparse import subprocess from collections import defaultdict @@ -242,6 +249,9 @@ def update_citations(): new_authors = [] for author in unrecognised_authors: + if " " not in author: + # This is just a GitHub handle, skip + continue first_name, last_name = author.rsplit(maxsplit=1) new_authors.append({"family-names": last_name, "given-names": first_name}) diff --git a/manual/RELEASE_HOWTO.md b/manual/RELEASE_HOWTO.md index d8ced2afb5..72d1fb3f88 100644 --- a/manual/RELEASE_HOWTO.md +++ b/manual/RELEASE_HOWTO.md @@ -31,9 +31,8 @@ Before merging PR: - [ ] Update [`CHANGELOG.md`][changelog]: - Run [bout-changelog-generator.py LAST_RELEASE NEXT_RELEASE][bin/bout-changelog-generator.py] - See the docs for how to get the token -- [ ] Get list of authors: - - [ ] `git log --format='%aN' | sort | uniq` - - [ ] Compare to list in [`CITATION.cff`][citation], add new authors +- [ ] Run [`update_citations.py`][bin/update_citations.py] to add new + authors to [`CITATION.cff`](CITATION.cff) - [ ] Prep a new Zenodo release: - https://doi.org/10.5281/zenodo.1423212 - "New Version" From 265bbb9d2c4d3918f00d5999127a81c1775022b1 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 10:50:06 +0100 Subject: [PATCH 174/259] Add new authors --- CITATION.cff | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CITATION.cff b/CITATION.cff index 81f5c35e82..6a9881b379 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -197,6 +197,22 @@ authors: - family-names: Kryjak given-names: Mike + - family-names: Powell + given-names: Seimon + - family-names: Ağgül + given-names: Mustafa + - family-names: Parry + given-names: Owen + - family-names: Podhorszki + given-names: Norbert + - family-names: Falgout + given-names: Rob + - family-names: Li + given-names: Nami + - family-names: Body + given-names: Tom + - family-names: Tsagkaridis + given-names: Malamas version: 5.1.1 date-released: 2023-04-10 repository-code: https://github.com/boutproject/BOUT-dev From 7e96b3f9609d34b8e5e75ce3de10047b9b584cfd Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 10:55:14 +0100 Subject: [PATCH 175/259] Add dependencies to changelog updater --- bin/bout-changelog-generator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/bout-changelog-generator.py b/bin/bout-changelog-generator.py index cfb9a30bb0..d5ad11892e 100755 --- a/bin/bout-changelog-generator.py +++ b/bin/bout-changelog-generator.py @@ -1,4 +1,10 @@ #! /usr/bin/env python3 +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "pygithub", +# ] +# /// import argparse import os From 7678b8ab7723ece7dcf3c48d2dd8b728e206d6f7 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 11:19:52 +0100 Subject: [PATCH 176/259] Tweak version updater, mention in docs --- bin/update_version_number_in_files.py | 5 ----- manual/RELEASE_HOWTO.md | 10 ++-------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/bin/update_version_number_in_files.py b/bin/update_version_number_in_files.py index 85df930aea..ec9a31bc32 100755 --- a/bin/update_version_number_in_files.py +++ b/bin/update_version_number_in_files.py @@ -66,11 +66,6 @@ def update_version_number_in_file(relative_filepath, pattern, new_version_number def bump_version_numbers( new_version_number: VersionNumber, next_version_number: VersionNumber ): - update_version_number_in_file( - "configure.ac", - r"^AC_INIT\(\[BOUT\+\+\],\[(\d+\.\d+\.\d+)\]", - new_version_number, - ) update_version_number_in_file( "CITATION.cff", r"^version: (\d+\.\d+\.\d+)", new_version_number ) diff --git a/manual/RELEASE_HOWTO.md b/manual/RELEASE_HOWTO.md index 72d1fb3f88..d0a6ddb231 100644 --- a/manual/RELEASE_HOWTO.md +++ b/manual/RELEASE_HOWTO.md @@ -29,7 +29,7 @@ Before merging PR: - Be aware that this *will* update the timestamps and *possibly* reorder file paths in the .po and .pot files - [ ] Update [`CHANGELOG.md`][changelog]: - - Run [bout-changelog-generator.py LAST_RELEASE NEXT_RELEASE][bin/bout-changelog-generator.py] + - Run [`bout-changelog-generator.py LAST_RELEASE NEXT_RELEASE`][bin/bout-changelog-generator.py] - See the docs for how to get the token - [ ] Run [`update_citations.py`][bin/update_citations.py] to add new authors to [`CITATION.cff`](CITATION.cff) @@ -43,13 +43,7 @@ Before merging PR: - [ ] Change DOI in [`README.md`][README] to new DOI - [ ] Change date-released in [`CITATION.cff`][citation] - [ ] Check `abidiff` to see if `soname` needs bumping in `makefile`: -- [ ] Change version number, removing prerelease tag in: - - [ ] [`configure.ac`][configure]: `AC_INIT` - - [ ] [`CITATION.cff`][citation]: `version` - - [ ] [`manual/sphinx/conf.py`][sphinx_conf]: `version` and `release` - - [ ] [`manual/doxygen/Doxyfile_readthedocs`][Doxyfile_readthedocs]: `PROJECT_NUMBER` - - [ ] [`manual/doxygen/Doxyfile`][Doxyfile]: `PROJECT_NUMBER` - - [ ] [`CMakeLists.txt`][CMakeLists]: `_bout_previous_version`, `_bout_next_version` +- [ ] Run [`update_version_number.py LAST_RELEASE NEXT_RELEASE`][bin/update_version_number.py] - [ ] Update what version of PETSc and SUNDIALS we support (upper bound) From ad1d5147894557608a6a28639fbed5256df7f2e8 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 11:20:07 +0100 Subject: [PATCH 177/259] Bump version to 5.2.0 --- CITATION.cff | 2 +- CMakeLists.txt | 4 ++-- manual/doxygen/Doxyfile | 2 +- manual/doxygen/Doxyfile_readthedocs | 2 +- manual/sphinx/conf.py | 4 ++-- tools/pylib/_boutpp_build/backend.py | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 6a9881b379..496f8a3154 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -213,7 +213,7 @@ authors: given-names: Tom - family-names: Tsagkaridis given-names: Malamas -version: 5.1.1 +version: 5.2.0 date-released: 2023-04-10 repository-code: https://github.com/boutproject/BOUT-dev url: http://boutproject.github.io/ diff --git a/CMakeLists.txt b/CMakeLists.txt index c45fca3b72..5c49e434e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,8 @@ endif() # CMake currently doesn't support proper semver # Set the version here, strip any extra tags to use in `project` # We try to use git to get a full description, inspired by setuptools_scm -set(_bout_previous_version "5.1.1") -set(_bout_next_version "5.2.0") +set(_bout_previous_version "5.2.0") +set(_bout_next_version "5.2.1") execute_process( COMMAND "git" describe --tags --match=v${_bout_previous_version} COMMAND sed -e s/${_bout_previous_version}-/${_bout_next_version}.dev/ -e s/-/+/ diff --git a/manual/doxygen/Doxyfile b/manual/doxygen/Doxyfile index 0e3c6f6945..e7998854b0 100644 --- a/manual/doxygen/Doxyfile +++ b/manual/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = BOUT++ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 5.1.1 +PROJECT_NUMBER = 5.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/manual/doxygen/Doxyfile_readthedocs b/manual/doxygen/Doxyfile_readthedocs index 5c67187248..73060bb6b4 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.1.1 +PROJECT_NUMBER = 5.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/manual/sphinx/conf.py b/manual/sphinx/conf.py index 55d059feba..3aa6e94dc3 100755 --- a/manual/sphinx/conf.py +++ b/manual/sphinx/conf.py @@ -184,9 +184,9 @@ def __getattr__(cls, name): # built documents. # # The short X.Y version. -version = "5.1" +version = "5.2" # The full version, including alpha/beta/rc tags. -release = "5.1.1" +release = "5.2.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/tools/pylib/_boutpp_build/backend.py b/tools/pylib/_boutpp_build/backend.py index 3df29d276d..ae3162cf11 100755 --- a/tools/pylib/_boutpp_build/backend.py +++ b/tools/pylib/_boutpp_build/backend.py @@ -35,8 +35,8 @@ def getversion(): version = os.environ["BOUT_PRETEND_VERSION"] return version - _bout_previous_version = "v5.1.1" - _bout_next_version = "v5.2.0" + _bout_previous_version = "v5.2.0" + _bout_next_version = "v5.2.1" try: try: From 0cb29717831fec0bf858a756261efaac34afbdef Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 11:26:20 +0100 Subject: [PATCH 178/259] Update changelog --- CHANGELOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d346d47e8..41e3e2c47b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog -## [v6.0.0](https://github.com/boutproject/BOUT-dev/tree/next) -[Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.1.0...next) +## [v5.2.0](https://github.com/boutproject/BOUT-dev/tree/v5.2.0 + +[Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.1.1...v5.2.0) ### Breaking changes @@ -16,6 +17,67 @@ confusing. Now, monitors are called with the current number of completed monitor-steps. +## Changes + +- Fixes for FreeBSD [\#3172][https://github.com/boutproject/BOUT-dev/pull/3172] ([tomc271][https://github.com/tomc271]) +- snes: Print a warning if the coloring is non-symmetric. [\#3159][https://github.com/boutproject/BOUT-dev/pull/3159] ([bendudson][https://github.com/bendudson]) +- Cmake fix from master [\#3152][https://github.com/boutproject/BOUT-dev/pull/3152] ([oparry-ukaea][https://github.com/oparry-ukaea]) +- Bump ZedThree/clang-tidy-review from 0.20.1 to 0.21.0 [\#3150][https://github.com/boutproject/BOUT-dev/pull/3150] ([ZedThree][https://github.com/ZedThree]) +- SNES solver: Added a PID controller to update the timestep [\#3146][https://github.com/boutproject/BOUT-dev/pull/3146] ([malamast][https://github.com/malamast]) +- Fix name clash in some examples and MMS tests [\#3145][https://github.com/boutproject/BOUT-dev/pull/3145] ([ZedThree][https://github.com/ZedThree]) +- Handle absolute paths to options file [\#3142][https://github.com/boutproject/BOUT-dev/pull/3142] ([bendudson][https://github.com/bendudson]) +- Revert eliminate hypre boundary equations [\#3136][https://github.com/boutproject/BOUT-dev/pull/3136] ([ZedThree][https://github.com/ZedThree]) +- CI: Switch to released fedora [\#3134][https://github.com/boutproject/BOUT-dev/pull/3134] ([dschwoerer][https://github.com/dschwoerer]) +- Generalise FakeMeshFixture to allow configurable grid spacing via templating [\#3132][https://github.com/boutproject/BOUT-dev/pull/3132] ([tomc271][https://github.com/tomc271]) +- Fixes for ELM-PB preconditioner [\#3128][https://github.com/boutproject/BOUT-dev/pull/3128] ([Steven-Roberts][https://github.com/Steven-Roberts]) +- Fix cast for new petsc [\#3117][https://github.com/boutproject/BOUT-dev/pull/3117] ([dschwoerer][https://github.com/dschwoerer]) +- Fix bug where ARKODE considered all problems linear [\#3114][https://github.com/boutproject/BOUT-dev/pull/3114] ([Steven-Roberts][https://github.com/Steven-Roberts]) +- cvode: Add linear_solver option [\#3112][https://github.com/boutproject/BOUT-dev/pull/3112] ([bendudson][https://github.com/bendudson]) +- periodicX communication fixes [\#3109][https://github.com/boutproject/BOUT-dev/pull/3109] ([bendudson][https://github.com/bendudson]) +- beuler solver timestep and Jacobian calculation [\#3107][https://github.com/boutproject/BOUT-dev/pull/3107] ([bendudson][https://github.com/bendudson]) +- Feature/snes stencil [\#3104][https://github.com/boutproject/BOUT-dev/pull/3104] ([seimtpow][https://github.com/seimtpow]) +- Add attributes to ADIOS2 output to "define" dimensions as names. We n… [\#3098][https://github.com/boutproject/BOUT-dev/pull/3098] ([pnorbert][https://github.com/pnorbert]) +- CI: Avoid issues with special characters [\#3090][https://github.com/boutproject/BOUT-dev/pull/3090] ([dschwoerer][https://github.com/dschwoerer]) +- CI: Fix clang format [\#3086][https://github.com/boutproject/BOUT-dev/pull/3086] ([dschwoerer][https://github.com/dschwoerer]) +- Small updates for FCI output [\#3085][https://github.com/boutproject/BOUT-dev/pull/3085] ([bendudson][https://github.com/bendudson]) +- Eliminate boundary equations to improve HYPRE solves [\#3082][https://github.com/boutproject/BOUT-dev/pull/3082] ([rfalgout][https://github.com/rfalgout]) +- Elm-pb example with relaxing phi [\#3081][https://github.com/boutproject/BOUT-dev/pull/3081] ([bendudson][https://github.com/bendudson]) +- CI: Show more output of dnf5 to help debugging [\#3071][https://github.com/boutproject/BOUT-dev/pull/3071] ([dschwoerer][https://github.com/dschwoerer]) +- Fix clang tidy review [\#3070][https://github.com/boutproject/BOUT-dev/pull/3070] ([ZedThree][https://github.com/ZedThree]) +- CMake: Bump downloaded SUNDIALS version [\#3067][https://github.com/boutproject/BOUT-dev/pull/3067] ([ZedThree][https://github.com/ZedThree]) +- Use isfinite, fix pvode linking [\#3063][https://github.com/boutproject/BOUT-dev/pull/3063] ([bendudson][https://github.com/bendudson]) +- Make iteration more robust and give more options in LaplaceNaulin [\#3061][https://github.com/boutproject/BOUT-dev/pull/3061] ([johnomotani][https://github.com/johnomotani]) +- Fixes zoidberg [\#3054][https://github.com/boutproject/BOUT-dev/pull/3054] ([dschwoerer][https://github.com/dschwoerer]) +- Fix finalise in boutpp [\#3053][https://github.com/boutproject/BOUT-dev/pull/3053] ([dschwoerer][https://github.com/dschwoerer]) +- Avoid some warnings for 3D Metrics [\#3052][https://github.com/boutproject/BOUT-dev/pull/3052] ([dschwoerer][https://github.com/dschwoerer]) +- Minor fixes for the python backend [\#3051][https://github.com/boutproject/BOUT-dev/pull/3051] ([dschwoerer][https://github.com/dschwoerer]) +- Cleanup BOUT_HOST_DEVICE qualifiers [\#3040][https://github.com/boutproject/BOUT-dev/pull/3040] ([ggeorgakoudis][https://github.com/ggeorgakoudis]) +- Deprecate options that are only used as default for other options [\#3038][https://github.com/boutproject/BOUT-dev/pull/3038] ([dschwoerer][https://github.com/dschwoerer]) +- Avoid using the wrong grid by accident [\#3036][https://github.com/boutproject/BOUT-dev/pull/3036] ([dschwoerer][https://github.com/dschwoerer]) +- Use PEP 625 compatible archive name (next) [\#3035][https://github.com/boutproject/BOUT-dev/pull/3035] ([dschwoerer][https://github.com/dschwoerer]) +- CI: Increase check level for debug run + unit test fixes [\#3033][https://github.com/boutproject/BOUT-dev/pull/3033] ([dschwoerer][https://github.com/dschwoerer]) +- Avoid `#define` conflict with sundials [\#3031][https://github.com/boutproject/BOUT-dev/pull/3031] ([dschwoerer][https://github.com/dschwoerer]) +- Ensure PETSc headers are included after `bout/petsclib.hxx` [\#3024][https://github.com/boutproject/BOUT-dev/pull/3024] ([ZedThree][https://github.com/ZedThree]) +- Fix minor HYPRE and ADIOS2 compilation issues [\#3022][https://github.com/boutproject/BOUT-dev/pull/3022] ([ZedThree][https://github.com/ZedThree]) +- Fix recompilation cascade [\#3021][https://github.com/boutproject/BOUT-dev/pull/3021] ([ZedThree][https://github.com/ZedThree]) +- Move `invert3x3` out of general purpose `utils.hxx` header [\#3018][https://github.com/boutproject/BOUT-dev/pull/3018] ([ZedThree][https://github.com/ZedThree]) +- Replace deprecated `boututils.file_import` [\#3017][https://github.com/boutproject/BOUT-dev/pull/3017] ([ZedThree][https://github.com/ZedThree]) +- CI: clang-tidy-review tweaks [\#3016][https://github.com/boutproject/BOUT-dev/pull/3016] ([ZedThree][https://github.com/ZedThree]) +- Backward Euler solver improvements [\#3009][https://github.com/boutproject/BOUT-dev/pull/3009] ([bendudson][https://github.com/bendudson]) +- Fix circular header dependency: mesh.hxx <-> griddata.hxx [\#3008][https://github.com/boutproject/BOUT-dev/pull/3008] ([ZedThree][https://github.com/ZedThree]) +- Fix exception message [\#3003][https://github.com/boutproject/BOUT-dev/pull/3003] ([dschwoerer][https://github.com/dschwoerer]) +- Ensure pointer is checked before dereferencing [\#3002][https://github.com/boutproject/BOUT-dev/pull/3002] ([dschwoerer][https://github.com/dschwoerer]) +- Fix: preserve regionID [\#3000][https://github.com/boutproject/BOUT-dev/pull/3000] ([dschwoerer][https://github.com/dschwoerer]) +- Lazy grid loading [\#2991][https://github.com/boutproject/BOUT-dev/pull/2991] ([dschwoerer][https://github.com/dschwoerer]) +- Fix compilation warnings with SUNDIALS 7.1.0 [\#2990][https://github.com/boutproject/BOUT-dev/pull/2990] ([Steven-Roberts][https://github.com/Steven-Roberts]) +- Add LC gitlab CI for GPU build/run tests [\#2989][https://github.com/boutproject/BOUT-dev/pull/2989] ([ggeorgakoudis][https://github.com/ggeorgakoudis]) +- BoutMask non-const operator[](Ind3D) [\#2988][https://github.com/boutproject/BOUT-dev/pull/2988] ([bendudson][https://github.com/bendudson]) +- Use consistently signed char [\#2987][https://github.com/boutproject/BOUT-dev/pull/2987] ([dschwoerer][https://github.com/dschwoerer]) +- naulin laplace: Acceptance tolerances after maxits [\#2983][https://github.com/boutproject/BOUT-dev/pull/2983] ([bendudson][https://github.com/bendudson]) +- Merge v5.1.1 into `next` [\#2978][https://github.com/boutproject/BOUT-dev/pull/2978] ([ZedThree][https://github.com/ZedThree]) +- CI: Bump all ubuntu images [\#2977][https://github.com/boutproject/BOUT-dev/pull/2977] ([ZedThree][https://github.com/ZedThree]) +- Read 2D variables into Field3D [\#2975][https://github.com/boutproject/BOUT-dev/pull/2975] ([bendudson][https://github.com/bendudson]) + ## [v5.1.1](https://github.com/boutproject/BOUT-dev/tree/v5.1.1) [Full Changelog](https://github.com/boutproject/BOUT-dev/compare/v5.1.0...v5.1.1) From 36f19fa96d4844e01bdcd26c4886ff0bccf23607 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 13:50:13 +0100 Subject: [PATCH 179/259] CI: Don't run clang-{tidy,format} on RC branches --- .github/workflows/clang-format.yml | 2 ++ .github/workflows/clang-tidy-review.yml | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 60cf5b6d6f..3d325dcdde 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -8,6 +8,8 @@ on: jobs: clang-format: + # Release candidate branches tend to have big PRs which causes all sorts of problems + if: !endsWith(github.head_ref, '-rc') runs-on: ubuntu-latest steps: # Checkout the pull request branch, also include all history diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 743eefe703..e7ac33d8ad 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -5,9 +5,6 @@ on: paths: - '**.cxx' - '**.hxx' - branches-ignore: - # Release candidate branches tend to have big PRs which causes all sorts of problems - - 'v*rc' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -15,6 +12,8 @@ concurrency: jobs: review: + # Release candidate branches tend to have big PRs which causes all sorts of problems + if: !endsWith(github.head_ref, '-rc') runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 From aaa46000c2aa423996769b2eb3be4aaa8fea40d2 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 14:06:09 +0100 Subject: [PATCH 180/259] Fix reorder warning from snes --- src/solver/impls/snes/snes.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 2bb163f324..7965107b38 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -115,12 +115,12 @@ SNESSolver::SNESSolver(Options* opts) .doc("Convergence tolerance in terms of the norm of the change in " "the solution between steps") .withDefault(1e-8)), - maxits((*options)["max_nonlinear_iterations"] - .doc("Maximum number of nonlinear iterations per SNES solve") - .withDefault(50)), maxf((*options)["maxf"] .doc("Maximum number of function evaluations per SNES solve") .withDefault(10000)), + maxits((*options)["max_nonlinear_iterations"] + .doc("Maximum number of nonlinear iterations per SNES solve") + .withDefault(50)), lower_its((*options)["lower_its"] .doc("Iterations below which the next timestep is increased") .withDefault(static_cast(maxits * 0.5))), From e48cc34dde4ecb737071e444b530deb7caa0647a Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 14:06:27 +0100 Subject: [PATCH 181/259] Fix some easy clang-tidy snes warnings --- src/solver/impls/snes/snes.cxx | 14 +++++++------- src/solver/impls/snes/snes.hxx | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 7965107b38..de6c54388d 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -57,6 +57,7 @@ class ColoringStencil { } }; +namespace { /* * PETSc callback function, which evaluates the nonlinear * function to be solved by SNES. @@ -64,7 +65,7 @@ class ColoringStencil { * This function assumes the context void pointer is a pointer * to an SNESSolver object. */ -static PetscErrorCode FormFunction(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { +PetscErrorCode FormFunction(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, false); } @@ -73,7 +74,7 @@ static PetscErrorCode FormFunction(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { * * This function can be a linearised form of FormFunction */ -static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { +PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { return static_cast(ctx)->snes_function(x, f, true); } @@ -82,21 +83,20 @@ static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -static PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, +PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, true); } -static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { - int ierr; - +PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { // Get the context SNESSolver* s; - ierr = PCShellGetContext(pc, reinterpret_cast(&s)); + int ierr = PCShellGetContext(pc, reinterpret_cast(&s)); CHKERRQ(ierr); PetscFunctionReturn(s->precon(x, y)); } +} SNESSolver::SNESSolver(Options* opts) : Solver(opts), diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index bd942f09ff..31deae6f06 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -57,7 +57,7 @@ BOUT_ENUM_CLASS(BoutSnesEquationForm, pseudo_transient, rearranged_backward_eule class SNESSolver : public Solver { public: explicit SNESSolver(Options* opts = nullptr); - ~SNESSolver() = default; + ~SNESSolver() override = default; int init() override; int run() override; From a855c0613423fafaff80eec4db1c37bd533600a7 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 14:06:51 +0100 Subject: [PATCH 182/259] Bump bundled fmt --- externalpackages/fmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/fmt b/externalpackages/fmt index 2ac6c5ca8b..486e7ba579 160000 --- a/externalpackages/fmt +++ b/externalpackages/fmt @@ -1 +1 @@ -Subproject commit 2ac6c5ca8b3dfbcb1cc5cf49a8cc121e3984559c +Subproject commit 486e7ba579a2c677772d004ecd0311142ba481be From e2cd97c7166e333f561f2677960e1c7e5390f462 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 16:16:30 +0100 Subject: [PATCH 183/259] Fix deprecation warning --- include/bout/invertable_operator.hxx | 56 +++++++++++++--------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/include/bout/invertable_operator.hxx b/include/bout/invertable_operator.hxx index fe139986be..9b9dbba41a 100644 --- a/include/bout/invertable_operator.hxx +++ b/include/bout/invertable_operator.hxx @@ -219,21 +219,18 @@ public: localmesh->LocalNy, localmesh->LocalNz, localmesh->maxregionblocksize); } } - if (localmesh->firstY() or localmesh->lastY()) { - for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { - if (not localmesh->periodicY(ix)) { - if (localmesh->firstY()) { - nocorner3D += - Region(ix, ix, 0, localmesh->ystart - 1, 0, - localmesh->LocalNz - 1, localmesh->LocalNy, - localmesh->LocalNz, localmesh->maxregionblocksize); - } - if (localmesh->lastY()) { - nocorner3D += Region( - ix, ix, localmesh->LocalNy - localmesh->ystart, - localmesh->LocalNy - 1, 0, localmesh->LocalNz - 1, localmesh->LocalNy, - localmesh->LocalNz, localmesh->maxregionblocksize); - } + for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { + if (not localmesh->periodicY(ix)) { + if (localmesh->firstY(ix)) { + nocorner3D += Region( + ix, ix, 0, localmesh->ystart - 1, 0, localmesh->LocalNz - 1, + localmesh->LocalNy, localmesh->LocalNz, localmesh->maxregionblocksize); + } + if (localmesh->lastY(ix)) { + nocorner3D += Region( + ix, ix, localmesh->LocalNy - localmesh->ystart, localmesh->LocalNy - 1, + 0, localmesh->LocalNz - 1, localmesh->LocalNy, localmesh->LocalNz, + localmesh->maxregionblocksize); } } } @@ -259,20 +256,17 @@ public: 0, 0, localmesh->LocalNy, 1, localmesh->maxregionblocksize); } } - if (localmesh->firstY() or localmesh->lastY()) { - for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { - if (not localmesh->periodicY(ix)) { - if (localmesh->firstY()) { - nocorner2D += - Region(ix, ix, 0, localmesh->ystart - 1, 0, 0, - localmesh->LocalNy, 1, localmesh->maxregionblocksize); - } - if (localmesh->lastY()) { - nocorner2D += - Region(ix, ix, localmesh->LocalNy - localmesh->ystart, - localmesh->LocalNy - 1, 0, 0, localmesh->LocalNy, 1, - localmesh->maxregionblocksize); - } + for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { + if (not localmesh->periodicY(ix)) { + if (localmesh->firstY(ix)) { + nocorner2D += + Region(ix, ix, 0, localmesh->ystart - 1, 0, 0, + localmesh->LocalNy, 1, localmesh->maxregionblocksize); + } + if (localmesh->lastY(ix)) { + nocorner2D += Region( + ix, ix, localmesh->LocalNy - localmesh->ystart, localmesh->LocalNy - 1, + 0, 0, localmesh->LocalNy, 1, localmesh->maxregionblocksize); } } } @@ -575,7 +569,7 @@ public: }; #endif // PETSC -}; // namespace inversion -}; // namespace bout +}; // namespace inversion +}; // namespace bout #endif // HEADER GUARD From 89b085549b7518931d109a5614950914934bd12d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 17:10:32 +0100 Subject: [PATCH 184/259] Remove `boututils` from requirements; bump `boutdata` --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 52d3076d58..078eecac6d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,5 @@ scipy>=1.14.1 netcdf4>=1.7.1 matplotlib>=3.7.0 Cython>=3.0.0 -boututils>=0.2.1 -boutdata>=0.2.1 +boutdata>=0.3.0 zoidberg>=0.2.2 From 1704a4a7dfb2beb6624af4bc0fcd7c50e89990b4 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 17:13:57 +0100 Subject: [PATCH 185/259] Suppress warning from `nodiscard` function --- tests/unit/sys/test_options.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/sys/test_options.cxx b/tests/unit/sys/test_options.cxx index 448b49fc19..a9a3bf4af4 100644 --- a/tests/unit/sys/test_options.cxx +++ b/tests/unit/sys/test_options.cxx @@ -1099,7 +1099,7 @@ value6 = 12 } TEST_F(OptionsTest, InvalidFormat) { - EXPECT_THROW(fmt::format("{:nope}", Options{}), fmt::format_error); + EXPECT_THROW([[maybe_unused]] auto none = fmt::format("{:nope}", Options{}), fmt::format_error); } TEST_F(OptionsTest, FormatValue) { From 8c26fe36ebfe792b841340541e97e82592e9aab5 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 17:42:20 +0100 Subject: [PATCH 186/259] Add shim for ARKodeGetNumRhsEvals --- src/solver/impls/arkode/arkode.cxx | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/solver/impls/arkode/arkode.cxx b/src/solver/impls/arkode/arkode.cxx index 6f20ce11a6..0151f90167 100644 --- a/src/solver/impls/arkode/arkode.cxx +++ b/src/solver/impls/arkode/arkode.cxx @@ -72,6 +72,18 @@ int arkode_pre(BoutReal t, N_Vector yy, N_Vector yp, N_Vector rvec, N_Vector zve int arkode_jac(N_Vector v, N_Vector Jv, BoutReal t, N_Vector y, N_Vector fy, void* user_data, N_Vector tmp); + +#if SUNDIALS_VERSION_LESS_THAN(7, 2, 0) +// Shim for backwards compatibility +int ARKodeGetNumRhsEvals(void* arkode_mem, int partition_index, long int* num_rhs_evals) { + long int temp = 0; + if (partition_index == 0) { + return ARKStepGetNumRhsEvals(arkode_mem, num_rhs_evals, &temp); + } else { + return ARKStepGetNumRhsEvals(arkode_mem, &temp, num_rhs_evals); + } +} +#endif } // namespace // NOLINTEND(readability-identifier-length) @@ -417,8 +429,7 @@ int ArkodeSolver::init() { if (hasPreconditioner()) { output.write("\tUsing user-supplied preconditioner\n"); - if (ARKodeSetPreconditioner(arkode_mem, nullptr, arkode_pre) - != ARKLS_SUCCESS) { + if (ARKodeSetPreconditioner(arkode_mem, nullptr, arkode_pre) != ARKLS_SUCCESS) { throw BoutException("ARKodeSetPreconditioner failed\n"); } } else { @@ -516,12 +527,13 @@ int ArkodeSolver::run() { } // Get additional diagnostics - long int temp_long_int, temp_long_int2; + long int temp_long_int = 0; ARKodeGetNumSteps(arkode_mem, &temp_long_int); nsteps = int(temp_long_int); - ARKStepGetNumRhsEvals(arkode_mem, &temp_long_int, &temp_long_int2); + ARKodeGetNumRhsEvals(arkode_mem, 0, &temp_long_int); nfe_evals = int(temp_long_int); - nfi_evals = int(temp_long_int2); + ARKodeGetNumRhsEvals(arkode_mem, 1, &temp_long_int); + nfi_evals = int(temp_long_int); if (treatment == Treatment::ImEx or treatment == Treatment::Implicit) { ARKodeGetNumNonlinSolvIters(arkode_mem, &temp_long_int); nniters = int(temp_long_int); From ef744eaeca6b41b26d45ffbcb14b27449e44b527 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 09:56:07 +0100 Subject: [PATCH 187/259] tests: Ruff fixes for FCI runtest --- tests/MMS/spatial/fci/runtest | 86 +++++++++++++++-------------------- 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index a93f4d3aff..1f0b297ebc 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -6,17 +6,26 @@ # Cores: 2 # requires: zoidberg -from boututils.run_wrapper import build_and_log, launch_safe -from boutdata.collect import collect +import pathlib +import pickle +import sys + import boutconfig as conf +import zoidberg as zb +from boutdata.collect import collect +from boututils.run_wrapper import build_and_log, launch_safe +from numpy import arange, array, linspace, log, polyfit +from scipy.interpolate import RectBivariateSpline as RBS -from numpy import array, log, polyfit, linspace, arange -import pickle +def myRBS(a, b, c): + mx, _ = c.shape + kx = max(mx - 1, 1) + kx = min(kx, 3) + return RBS(a, b, c, kx=kx) -from sys import stdout -import zoidberg as zb +zb.poloidal_grid.RectBivariateSpline = myRBS nx = 3 # Not changed for these tests @@ -31,7 +40,6 @@ directory = "data" nproc = 2 mthread = 2 - success = True error_2 = {} @@ -51,7 +59,8 @@ for nslice in nslices: # Which central difference scheme to use and its expected order order = nslice * 2 - method_orders[nslice] = {"name": "C{}".format(order), "order": order} + name = f"C{order}" + method_orders[nslice] = {"name": name, "order": order} for n in nlist: # Define the magnetic field using new poloidal gridding method @@ -71,40 +80,26 @@ for nslice in nslices: # Create the grid grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) # Make and write maps - from scipy.interpolate import RectBivariateSpline as RBS - - def myRBS(a, b, c): - mx, my = c.shape - kx = max(mx - 1, 1) - kx = min(kx, 3) - return RBS(a, b, c, kx=kx) - - zb.poloidal_grid.RectBivariateSpline = myRBS maps = zb.make_maps(grid, field, nslice=nslice, quiet=True, MXG=1) zb.write_maps( grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True ) - args = " MZ={} MYG={} mesh:paralleltransform:y_periodic={} mesh:ddy:first={}".format( - n, nslice, yperiodic, method_orders[nslice]["name"] - ) - # Command to run - cmd = "./fci_mms " + args + args = f" MZ={n} MYG={nslice} mesh:paralleltransform:y_periodic={yperiodic} mesh:ddy:first={name}" + cmd = f"./fci_mms {args}" - print("Running command: " + cmd) + print(f"Running command: {cmd}") # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) # Save output to log file - with open("run.log." + str(n), "w") as f: - f.write(out) + pathlib.Path(f"run.log.{n}").write_text(out) if s: - print("Run failed!\nOutput was:\n") - print(out) - exit(s) + print(f"Run failed!\nOutput was:\n{out}") + sys.exit(s) # Collect data l_2 = collect( @@ -122,25 +117,25 @@ for nslice in nslices: error_2[nslice].append(l_2) error_inf[nslice].append(l_inf) - print("Errors : l-2 {:f} l-inf {:f}".format(l_2, l_inf)) + print(f"Errors : l-2 {l_2:f} l-inf {l_inf:f}") dx = 1.0 / array(nlist) # Calculate convergence order fit = polyfit(log(dx), log(error_2[nslice]), 1) order = fit[0] - stdout.write("Convergence order = {:f} (fit)".format(order)) + print(f"Convergence order = {order:f} (fit)", end="") order = log(error_2[nslice][-2] / error_2[nslice][-1]) / log(dx[-2] / dx[-1]) - stdout.write(", {:f} (small spacing)".format(order)) + print(f", {order:f} (small spacing)") # Should be close to the expected order - if order > method_orders[nslice]["order"] * 0.95: + if order > order * 0.95: print("............ PASS\n") else: print("............ FAIL\n") success = False - failures.append(method_orders[nslice]["name"]) + failures.append(name) with open("fci_mms.pkl", "wb") as output: @@ -150,7 +145,7 @@ with open("fci_mms.pkl", "wb") as output: pickle.dump(error_inf[nslice], output) # Do we want to show the plot as well as save it to file. -showPlot = True +show_plot = True if False: try: @@ -160,18 +155,9 @@ if False: fig, ax = plt.subplots(1, 1) for nslice in nslices: - ax.plot( - dx, - error_2[nslice], - "-", - label="{} $l_2$".format(method_orders[nslice]["name"]), - ) - ax.plot( - dx, - error_inf[nslice], - "--", - label="{} $l_\\inf$".format(method_orders[nslice]["name"]), - ) + name = method_orders[nslice]["name"] + ax.plot(dx, error_2[nslice], "-", label=f"{name} $l_2$") + ax.plot(dx, error_inf[nslice], "--", label=f"{name} $l_\\inf$") ax.legend(loc="upper left") ax.grid() ax.set_yscale("log") @@ -184,7 +170,7 @@ if False: print("Plot saved to fci_mms.pdf") - if showPlot: + if show_plot: plt.show() plt.close() except ImportError: @@ -192,9 +178,9 @@ if False: if success: print("All tests passed") - exit(0) + sys.exit(0) else: print("Some tests failed:") for failure in failures: - print("\t" + failure) - exit(1) + print(f"\t{failure}") + sys.exit(1) From d889ecf1d624dad8b84df1b6925af556b583feae Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 12:05:01 +0100 Subject: [PATCH 188/259] tests: Expand FCI MMS test to `Grad2_par2` --- CMakeLists.txt | 1 + tests/MMS/spatial/fci/data/BOUT.inp | 5 +- tests/MMS/spatial/fci/fci_mms.cxx | 48 ++++++++++----- tests/MMS/spatial/fci/mms.py | 5 +- tests/MMS/spatial/fci/runtest | 96 +++++++++++++++-------------- 5 files changed, 90 insertions(+), 65 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c49e434e4..db7e75ddd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,6 +374,7 @@ if (zoidberg_FOUND EQUAL 0) else() set(zoidberg_FOUND OFF) endif() +message(STATUS "Found Zoidberg for FCI tests: ${zoidberg_FOUND}") option(BOUT_GENERATE_FIELDOPS "Automatically re-generate the Field arithmetic operators from the Python templates. \ Requires Python3, clang-format, and Jinja2. Turn this OFF to skip generating them if, for example, \ diff --git a/tests/MMS/spatial/fci/data/BOUT.inp b/tests/MMS/spatial/fci/data/BOUT.inp index 3906fcafef..228ad295ff 100644 --- a/tests/MMS/spatial/fci/data/BOUT.inp +++ b/tests/MMS/spatial/fci/data/BOUT.inp @@ -1,7 +1,6 @@ - input_field = sin(y - 2*z) + sin(y - z) - -solution = (6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y - z)) + 0.628318530717959*cos(y - 2*z) + 0.628318530717959*cos(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) +grad_par_solution = (6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y - z)) + 0.628318530717959*cos(y - 2*z) + 0.628318530717959*cos(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) +grad2_par2_solution = (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0))/sqrt((0.01*x + 0.045)^2 + 1.0) MXG = 1 MYG = 1 diff --git a/tests/MMS/spatial/fci/fci_mms.cxx b/tests/MMS/spatial/fci/fci_mms.cxx index 18405a7f88..48b18f04ef 100644 --- a/tests/MMS/spatial/fci/fci_mms.cxx +++ b/tests/MMS/spatial/fci/fci_mms.cxx @@ -1,5 +1,4 @@ #include "bout/bout.hxx" -#include "bout/derivs.hxx" #include "bout/field_factory.hxx" int main(int argc, char** argv) { @@ -8,29 +7,50 @@ int main(int argc, char** argv) { using bout::globals::mesh; Field3D input{FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh)}; - Field3D solution{FieldFactory::get()->create3D("solution", Options::getRoot(), mesh)}; // Communicate to calculate parallel transform mesh->communicate(input); - Field3D result{Grad_par(input)}; - Field3D error{result - solution}; - Options dump; // Add mesh geometry variables mesh->outputVars(dump); - dump["l_2"] = sqrt(mean(SQ(error), true, "RGN_NOBNDRY")); - dump["l_inf"] = max(abs(error), true, "RGN_NOBNDRY"); + auto* factory = FieldFactory::get(); + { + Field3D solution{factory->create3D("grad_par_solution", Options::getRoot(), mesh)}; + Field3D result{Grad_par(input)}; + Field3D error{result - solution}; + + dump["grad_par_l_2"] = sqrt(mean(SQ(error), true, "RGN_NOBNDRY")); + dump["grad_par_l_inf"] = max(abs(error), true, "RGN_NOBNDRY"); - dump["result"] = result; - dump["error"] = error; - dump["input"] = input; - dump["solution"] = solution; + dump["grad_par_result"] = result; + dump["grad_par_error"] = error; + dump["grad_par_input"] = input; + dump["grad_par_solution"] = solution; - for (int slice = 1; slice < mesh->ystart; ++slice) { - dump[fmt::format("input.ynext(-{})", slice)] = input.ynext(-slice); - dump[fmt::format("input.ynext({})", slice)] = input.ynext(slice); + for (int slice = 1; slice < mesh->ystart; ++slice) { + dump[fmt::format("grad_par_input.ynext(-{})", slice)] = input.ynext(-slice); + dump[fmt::format("grad_par_input.ynext({})", slice)] = input.ynext(slice); + } + } + { + Field3D solution{factory->create3D("grad2_par2_solution", Options::getRoot(), mesh)}; + Field3D result{Grad2_par2(input)}; + Field3D error{result - solution}; + + dump["grad2_par2_l_2"] = sqrt(mean(SQ(error), true, "RGN_NOBNDRY")); + dump["grad2_par2_l_inf"] = max(abs(error), true, "RGN_NOBNDRY"); + + dump["grad2_par2_result"] = result; + dump["grad2_par2_error"] = error; + dump["grad2_par2_input"] = input; + dump["grad2_par2_solution"] = solution; + + for (int slice = 1; slice < mesh->ystart; ++slice) { + dump[fmt::format("grad2_par2_input.ynext(-{})", slice)] = input.ynext(-slice); + dump[fmt::format("grad2_par2_input.ynext({})", slice)] = input.ynext(slice); + } } bout::writeDefaultOutputFile(dump); diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index 1e71135c90..ae48ef8f06 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -30,5 +30,6 @@ def FCI_ddy(f): ############################################ # Equations solved -print("input = " + exprToStr(f)) -print("solution = " + exprToStr(FCI_ddy(f))) +print(f"input_field = {exprToStr(f)}") +print(f"grad_par_solution = {exprToStr(FCI_ddy(f))}") +print(f"grad2_par2_solution = {exprToStr(FCI_ddy(FCI_ddy(f)))}") diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 1f0b297ebc..27b18baafd 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -9,6 +9,7 @@ import pathlib import pickle import sys +from collections import defaultdict import boutconfig as conf import zoidberg as zb @@ -19,6 +20,7 @@ from scipy.interpolate import RectBivariateSpline as RBS def myRBS(a, b, c): + """RectBivariateSpline, but automatically tune spline degree for small arrays""" mx, _ = c.shape kx = max(mx - 1, 1) kx = min(kx, 3) @@ -27,6 +29,13 @@ def myRBS(a, b, c): zb.poloidal_grid.RectBivariateSpline = myRBS + +def quiet_collect(name: str): + return collect( + name, tind=[1, 1], info=False, path=directory, xguards=False, yguards=False, + ) + + nx = 3 # Not changed for these tests # Resolution in y and z @@ -50,12 +59,29 @@ method_orders = {} yperiodic = True failures = [] +operators = ("grad_par", "grad2_par2") build_and_log("FCI MMS test") + +def assert_convergence(error, dx, name, order) -> bool: + fit = polyfit(log(dx), log(error), 1) + order = fit[0] + print(f"{name} convergence order = {order:f} (fit)", end="") + + order = log(error[-2] / error[-1]) / log(dx[-2] / dx[-1]) + print(f", {order:f} (small spacing)", end="") + + # Should be close to the expected order + success = order > order * 0.95 + print(f" ............ {'PASS' if success else 'FAIL'}") + + return success + + for nslice in nslices: - error_2[nslice] = [] - error_inf[nslice] = [] + error_2[nslice] = defaultdict(list) + error_inf[nslice] = defaultdict(list) # Which central difference scheme to use and its expected order order = nslice * 2 @@ -79,70 +105,48 @@ for nslice in nslices: # Create the grid grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) - # Make and write maps maps = zb.make_maps(grid, field, nslice=nslice, quiet=True, MXG=1) zb.write_maps( - grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True + grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True, ) # Command to run args = f" MZ={n} MYG={nslice} mesh:paralleltransform:y_periodic={yperiodic} mesh:ddy:first={name}" cmd = f"./fci_mms {args}" - print(f"Running command: {cmd}") # Launch using MPI - s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) + status, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) # Save output to log file pathlib.Path(f"run.log.{n}").write_text(out) - if s: + if status: print(f"Run failed!\nOutput was:\n{out}") - sys.exit(s) + sys.exit(status) # Collect data - l_2 = collect( - "l_2", tind=[1, 1], info=False, path=directory, xguards=False, yguards=False - ) - l_inf = collect( - "l_inf", - tind=[1, 1], - info=False, - path=directory, - xguards=False, - yguards=False, - ) + for operator in operators: + l_2 = quiet_collect(f"{operator}_l_2") + l_inf = quiet_collect(f"{operator}_l_inf") - error_2[nslice].append(l_2) - error_inf[nslice].append(l_inf) + error_2[nslice][operator].append(l_2) + error_inf[nslice][operator].append(l_inf) - print(f"Errors : l-2 {l_2:f} l-inf {l_inf:f}") + print(f"{operator} errors: l-2 {l_2:f} l-inf {l_inf:f}") dx = 1.0 / array(nlist) + for operator in operators: + test_name = f"{operator} {name}" + success &= assert_convergence(error_2[nslice][operator], dx, test_name, order) + if not success: + failures.append(test_name) - # Calculate convergence order - fit = polyfit(log(dx), log(error_2[nslice]), 1) - order = fit[0] - print(f"Convergence order = {order:f} (fit)", end="") - - order = log(error_2[nslice][-2] / error_2[nslice][-1]) / log(dx[-2] / dx[-1]) - print(f", {order:f} (small spacing)") - - # Should be close to the expected order - if order > order * 0.95: - print("............ PASS\n") - else: - print("............ FAIL\n") - success = False - failures.append(name) - -with open("fci_mms.pkl", "wb") as output: +with pathlib.Path("fci_mms.pkl").open("wb") as output: pickle.dump(nlist, output) - for nslice in nslices: - pickle.dump(error_2[nslice], output) - pickle.dump(error_inf[nslice], output) + pickle.dump(error_2, output) + pickle.dump(error_inf, output) # Do we want to show the plot as well as save it to file. show_plot = True @@ -177,10 +181,10 @@ if False: print("No matplotlib") if success: - print("All tests passed") - sys.exit(0) + print("\nAll tests passed") else: - print("Some tests failed:") + print("\nSome tests failed:") for failure in failures: print(f"\t{failure}") - sys.exit(1) + +sys.exit(0 if success else 1) From 122c39af83c07340f331c6d39ab6ed27c8163a47 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 15:10:32 +0100 Subject: [PATCH 189/259] tests: Generalise FCI MMS test to allow for more cases --- tests/MMS/spatial/fci/runtest | 302 +++++++++++++++++++++------------- 1 file changed, 188 insertions(+), 114 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 27b18baafd..c575f1afbc 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -6,10 +6,12 @@ # Cores: 2 # requires: zoidberg +import argparse +import json import pathlib -import pickle import sys -from collections import defaultdict +from time import time +from typing import Any import boutconfig as conf import zoidberg as zb @@ -18,6 +20,16 @@ from boututils.run_wrapper import build_and_log, launch_safe from numpy import arange, array, linspace, log, polyfit from scipy.interpolate import RectBivariateSpline as RBS +# Global parameters +DIRECTORY = "data" +NPROC = 2 +MTHREAD = 2 +OPERATORS = ("grad_par", "grad2_par2") +NX = 3 +# Resolution in y and z +NLIST = [8, 16, 32, 64, 128] +dx = 1.0 / array(NLIST) + def myRBS(a, b, c): """RectBivariateSpline, but automatically tune spline degree for small arrays""" @@ -30,38 +42,16 @@ def myRBS(a, b, c): zb.poloidal_grid.RectBivariateSpline = myRBS -def quiet_collect(name: str): +def quiet_collect(name: str) -> float: + # Index to return a plain (numpy) float rather than `BoutArray` return collect( - name, tind=[1, 1], info=False, path=directory, xguards=False, yguards=False, - ) - - -nx = 3 # Not changed for these tests - -# Resolution in y and z -nlist = [8, 16, 32, 64, 128] - -# Number of parallel slices (in each direction) -nslices = [1] - -directory = "data" - -nproc = 2 -mthread = 2 - -success = True - -error_2 = {} -error_inf = {} -method_orders = {} - -# Run with periodic Y? -yperiodic = True - -failures = [] -operators = ("grad_par", "grad2_par2") - -build_and_log("FCI MMS test") + name, + tind=[1, 1], + info=False, + path=DIRECTORY, + xguards=False, + yguards=False, + )[()] def assert_convergence(error, dx, name, order) -> bool: @@ -74,117 +64,201 @@ def assert_convergence(error, dx, name, order) -> bool: # Should be close to the expected order success = order > order * 0.95 - print(f" ............ {'PASS' if success else 'FAIL'}") + print(f"\t............ {'PASS' if success else 'FAIL'}") return success -for nslice in nslices: - error_2[nslice] = defaultdict(list) - error_inf[nslice] = defaultdict(list) +def run_fci_operators( + nslice: int, nz: int, yperiodic: bool, name: str +) -> dict[str, float]: + # Define the magnetic field using new poloidal gridding method + # Note that the Bz and Bzprime parameters here must be the same as in mms.py + field = zb.field.Slab(Bz=0.05, Bzprime=0.1) + # Create rectangular poloidal grids + poloidal_grid = zb.poloidal_grid.RectangularPoloidalGrid(NX, nz, 0.1, 1.0, MXG=1) + # Set the ylength and y locations + ylength = 10.0 + + if yperiodic: + ycoords = linspace(0.0, ylength, nz, endpoint=False) + else: + # Doesn't include the end points + ycoords = (arange(nz) + 0.5) * ylength / float(nz) + + # Create the grid + grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) + maps = zb.make_maps(grid, field, nslice=nslice, quiet=True, MXG=1) + zb.write_maps( + grid, + field, + maps, + new_names=False, + metric2d=conf.isMetric2D(), + quiet=True, + ) - # Which central difference scheme to use and its expected order - order = nslice * 2 - name = f"C{order}" - method_orders[nslice] = {"name": name, "order": order} - - for n in nlist: - # Define the magnetic field using new poloidal gridding method - # Note that the Bz and Bzprime parameters here must be the same as in mms.py - field = zb.field.Slab(Bz=0.05, Bzprime=0.1) - # Create rectangular poloidal grids - poloidal_grid = zb.poloidal_grid.RectangularPoloidalGrid(nx, n, 0.1, 1.0, MXG=1) - # Set the ylength and y locations - ylength = 10.0 - - if yperiodic: - ycoords = linspace(0.0, ylength, n, endpoint=False) - else: - # Doesn't include the end points - ycoords = (arange(n) + 0.5) * ylength / float(n) - - # Create the grid - grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) - maps = zb.make_maps(grid, field, nslice=nslice, quiet=True, MXG=1) - zb.write_maps( - grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True, - ) + # Command to run + args = f"MZ={nz} MYG={nslice} mesh:paralleltransform:y_periodic={yperiodic} mesh:ddy:first={name}" + cmd = f"./fci_mms {args}" + print(f"Running command: {cmd}", end="") + + # Launch using MPI + start = time() + status, out = launch_safe(cmd, nproc=NPROC, mthread=MTHREAD, pipe=True) + print(f" ... done in {time() - start:.3}s") + + # Save output to log file + pathlib.Path(f"run.log.{nz}").write_text(out) + + if status: + print(f"Run failed!\nOutput was:\n{out}") + sys.exit(status) + + return { + operator: { + "l_2": quiet_collect(f"{operator}_l_2"), + "l_inf": quiet_collect(f"{operator}_l_inf"), + } + for operator in OPERATORS + } - # Command to run - args = f" MZ={n} MYG={nslice} mesh:paralleltransform:y_periodic={yperiodic} mesh:ddy:first={name}" - cmd = f"./fci_mms {args}" - print(f"Running command: {cmd}") - # Launch using MPI - status, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) +def transpose( + errors: list[dict[str, dict[str, float]]], +) -> dict[str, dict[str, list[float]]]: + """Turn a list of {operator: error} into a dict of {operator: [errors]}""" - # Save output to log file - pathlib.Path(f"run.log.{n}").write_text(out) + kinds = ("l_2", "l_inf") + result = {operator: {kind: [] for kind in kinds} for operator in OPERATORS} + for error in errors: + for k, v in error.items(): + for kind in kinds: + result[k][kind].append(v[kind]) + return result - if status: - print(f"Run failed!\nOutput was:\n{out}") - sys.exit(status) - # Collect data - for operator in operators: - l_2 = quiet_collect(f"{operator}_l_2") - l_inf = quiet_collect(f"{operator}_l_inf") +def check_fci_operators(case: dict) -> bool: + failures = [] - error_2[nslice][operator].append(l_2) - error_inf[nslice][operator].append(l_inf) + nslice = case["nslice"] + yperiodic = case["yperiodic"] + name = case["name"] + order = case["order"] + + all_errors = [] + + for n in NLIST: + errors = run_fci_operators(nslice, n, yperiodic, name) + all_errors.append(errors) + + for operator in OPERATORS: + l_2 = errors[operator]["l_2"] + l_inf = errors[operator]["l_inf"] print(f"{operator} errors: l-2 {l_2:f} l-inf {l_inf:f}") - dx = 1.0 / array(nlist) - for operator in operators: + final_errors = transpose(all_errors) + for operator in OPERATORS: test_name = f"{operator} {name}" - success &= assert_convergence(error_2[nslice][operator], dx, test_name, order) + success = assert_convergence( + final_errors[operator]["l_2"], dx, test_name, order + ) if not success: failures.append(test_name) + return final_errors, failures -with pathlib.Path("fci_mms.pkl").open("wb") as output: - pickle.dump(nlist, output) - pickle.dump(error_2, output) - pickle.dump(error_inf, output) - -# Do we want to show the plot as well as save it to file. -show_plot = True -if False: +def make_plots(cases): try: - # Plot using matplotlib if available import matplotlib.pyplot as plt + except ImportError: + print("No matplotlib") + return - fig, ax = plt.subplots(1, 1) + fig, axes = plt.subplots(1, len(OPERATORS), figsize=(9, 4)) - for nslice in nslices: - name = method_orders[nslice]["name"] - ax.plot(dx, error_2[nslice], "-", label=f"{name} $l_2$") - ax.plot(dx, error_inf[nslice], "--", label=f"{name} $l_\\inf$") + for ax, operator in zip(axes, OPERATORS): + for name, case in cases.items(): + ax.loglog(dx, case[operator]["l_2"], "-", label=f"{name} $l_2$") + ax.loglog(dx, case[operator]["l_inf"], "--", label=f"{name} $l_\\inf$") ax.legend(loc="upper left") ax.grid() - ax.set_yscale("log") - ax.set_xscale("log") - ax.set_title("error scaling") + ax.set_title(f"Error scaling for {operator}") ax.set_xlabel(r"Mesh spacing $\delta x$") ax.set_ylabel("Error norm") - plt.savefig("fci_mms.pdf") + fig.tight_layout() + fig.savefig("fci_mms.pdf") + print("Plot saved to fci_mms.pdf") - print("Plot saved to fci_mms.pdf") + if args.show_plots: + plt.show() + plt.close() - if show_plot: - plt.show() - plt.close() - except ImportError: - print("No matplotlib") -if success: - print("\nAll tests passed") -else: - print("\nSome tests failed:") - for failure in failures: - print(f"\t{failure}") +def make_case(nslice: int, yperiodic: bool) -> dict[str, Any]: + """ + nslice: + Number of parallel slices (in each direction) + yperiodic: + Run with periodic Y + """ + order = nslice * 2 + return { + "nslice": nslice, + # Which central difference scheme to use and its expected order + "order": order, + "name": f"C{order}", + "yperiodic": yperiodic, + } + + +if __name__ == "__main__": + build_and_log("FCI MMS test") + + parser = argparse.ArgumentParser("Error scaling test for FCI operators") + parser.add_argument( + "--make-plots", action="store_true", help="Create plots of error scaling" + ) + parser.add_argument( + "--show-plots", + action="store_true", + help="Stop and show plots, implies --make-plots", + ) + parser.add_argument( + "--dump-errors", + type=str, + help="Output file to dump errors as JSON", + default="fci_operator_errors.json", + ) + + args = parser.parse_args() + + success = True + failures = [] + cases = { + "nslice=1": make_case(nslice=1, yperiodic=True), + } + + for case in cases.values(): + error2, failures_ = check_fci_operators(case) + case.update(error2) + failures.extend(failures_) + success &= len(failures) == 0 + + if args.dump_errors: + pathlib.Path(args.dump_errors).write_text(json.dumps(cases)) + + if args.make_plots or args.show_plots: + make_plots(cases) + + if success: + print("\nAll tests passed") + else: + print("\nSome tests failed:") + for failure in failures: + print(f"\t{failure}") -sys.exit(0 if success else 1) + sys.exit(0 if success else 1) From 1a0af583dda4ede5de417fec227a764c1de29b9d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 15:30:58 +0100 Subject: [PATCH 190/259] tests: Add test for FCI `Div_par` --- tests/MMS/spatial/fci/data/BOUT.inp | 1 + tests/MMS/spatial/fci/fci_mms.cxx | 67 +++++++++++++---------------- tests/MMS/spatial/fci/mms.py | 4 ++ tests/MMS/spatial/fci/runtest | 2 +- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/tests/MMS/spatial/fci/data/BOUT.inp b/tests/MMS/spatial/fci/data/BOUT.inp index 228ad295ff..aba82e9882 100644 --- a/tests/MMS/spatial/fci/data/BOUT.inp +++ b/tests/MMS/spatial/fci/data/BOUT.inp @@ -1,6 +1,7 @@ input_field = sin(y - 2*z) + sin(y - z) grad_par_solution = (6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y - z)) + 0.628318530717959*cos(y - 2*z) + 0.628318530717959*cos(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) grad2_par2_solution = (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0))/sqrt((0.01*x + 0.045)^2 + 1.0) +div_par_solution = (0.01*x + 0.045)*(-12.5663706143592*cos(y - 2*z) - 6.28318530717959*cos(y - z) + 0.628318530717959*(cos(y - 2*z) + cos(y - z))/(0.01*x + 0.045))/sqrt((0.01*x + 0.045)^2 + 1.0) MXG = 1 MYG = 1 diff --git a/tests/MMS/spatial/fci/fci_mms.cxx b/tests/MMS/spatial/fci/fci_mms.cxx index 48b18f04ef..bc995424c6 100644 --- a/tests/MMS/spatial/fci/fci_mms.cxx +++ b/tests/MMS/spatial/fci/fci_mms.cxx @@ -1,6 +1,33 @@ #include "bout/bout.hxx" +#include "bout/difops.hxx" +#include "bout/field3d.hxx" #include "bout/field_factory.hxx" +#include + +namespace { +auto fci_op_test(const std::string& name, Options& dump, const Field3D& input, + const Field3D& result) { + auto* mesh = input.getMesh(); + Field3D solution{FieldFactory::get()->create3D(fmt::format("{}_solution", name), + Options::getRoot(), mesh)}; + Field3D error{result - solution}; + + dump[fmt::format("{}_l_2", name)] = sqrt(mean(SQ(error), true, "RGN_NOBNDRY")); + dump[fmt::format("{}_l_inf", name)] = max(abs(error), true, "RGN_NOBNDRY"); + + dump[fmt::format("{}_result", name)] = result; + dump[fmt::format("{}_error", name)] = error; + dump[fmt::format("{}_input", name)] = input; + dump[fmt::format("{}_solution", name)] = solution; + + for (int slice = 1; slice < mesh->ystart; ++slice) { + dump[fmt::format("{}_input.ynext(-{})", name, slice)] = input.ynext(-slice); + dump[fmt::format("{}_input.ynext({})", name, slice)] = input.ynext(slice); + } +} +} // namespace + int main(int argc, char** argv) { BoutInitialise(argc, argv); @@ -15,43 +42,9 @@ int main(int argc, char** argv) { // Add mesh geometry variables mesh->outputVars(dump); - auto* factory = FieldFactory::get(); - { - Field3D solution{factory->create3D("grad_par_solution", Options::getRoot(), mesh)}; - Field3D result{Grad_par(input)}; - Field3D error{result - solution}; - - dump["grad_par_l_2"] = sqrt(mean(SQ(error), true, "RGN_NOBNDRY")); - dump["grad_par_l_inf"] = max(abs(error), true, "RGN_NOBNDRY"); - - dump["grad_par_result"] = result; - dump["grad_par_error"] = error; - dump["grad_par_input"] = input; - dump["grad_par_solution"] = solution; - - for (int slice = 1; slice < mesh->ystart; ++slice) { - dump[fmt::format("grad_par_input.ynext(-{})", slice)] = input.ynext(-slice); - dump[fmt::format("grad_par_input.ynext({})", slice)] = input.ynext(slice); - } - } - { - Field3D solution{factory->create3D("grad2_par2_solution", Options::getRoot(), mesh)}; - Field3D result{Grad2_par2(input)}; - Field3D error{result - solution}; - - dump["grad2_par2_l_2"] = sqrt(mean(SQ(error), true, "RGN_NOBNDRY")); - dump["grad2_par2_l_inf"] = max(abs(error), true, "RGN_NOBNDRY"); - - dump["grad2_par2_result"] = result; - dump["grad2_par2_error"] = error; - dump["grad2_par2_input"] = input; - dump["grad2_par2_solution"] = solution; - - for (int slice = 1; slice < mesh->ystart; ++slice) { - dump[fmt::format("grad2_par2_input.ynext(-{})", slice)] = input.ynext(-slice); - dump[fmt::format("grad2_par2_input.ynext({})", slice)] = input.ynext(slice); - } - } + fci_op_test("grad_par", dump, input, Grad_par(input)); + fci_op_test("grad2_par2", dump, input, Grad2_par2(input)); + fci_op_test("div_par", dump, input, Div_par(input)); bout::writeDefaultOutputFile(dump); diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index ae48ef8f06..5f5d48bee2 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -26,6 +26,9 @@ def FCI_ddy(f): return (Bt * diff(f, y) * 2.0 * pi / Ly + Bpx * diff(f, z) * 2.0 * pi / Lz) / B +def FCI_div_par(f): + return Bpx * FCI_ddy(f / Bpx) + ############################################ # Equations solved @@ -33,3 +36,4 @@ def FCI_ddy(f): print(f"input_field = {exprToStr(f)}") print(f"grad_par_solution = {exprToStr(FCI_ddy(f))}") print(f"grad2_par2_solution = {exprToStr(FCI_ddy(FCI_ddy(f)))}") +print(f"div_par_solution = {exprToStr(FCI_div_par(f))}") diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index c575f1afbc..c98d924e7b 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -24,7 +24,7 @@ from scipy.interpolate import RectBivariateSpline as RBS DIRECTORY = "data" NPROC = 2 MTHREAD = 2 -OPERATORS = ("grad_par", "grad2_par2") +OPERATORS = ("grad_par", "grad2_par2", "div_par") NX = 3 # Resolution in y and z NLIST = [8, 16, 32, 64, 128] From 1e912bdefa9c08dbd2ba7989fdc20320240eef1d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 15:47:01 +0100 Subject: [PATCH 191/259] tests: Make MMS script update input in-place --- tests/MMS/spatial/fci/data/BOUT.inp | 7 +++--- tests/MMS/spatial/fci/mms.py | 36 +++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/tests/MMS/spatial/fci/data/BOUT.inp b/tests/MMS/spatial/fci/data/BOUT.inp index aba82e9882..0088a000f4 100644 --- a/tests/MMS/spatial/fci/data/BOUT.inp +++ b/tests/MMS/spatial/fci/data/BOUT.inp @@ -3,13 +3,12 @@ grad_par_solution = (6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y grad2_par2_solution = (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0))/sqrt((0.01*x + 0.045)^2 + 1.0) div_par_solution = (0.01*x + 0.045)*(-12.5663706143592*cos(y - 2*z) - 6.28318530717959*cos(y - z) + 0.628318530717959*(cos(y - 2*z) + cos(y - z))/(0.01*x + 0.045))/sqrt((0.01*x + 0.045)^2 + 1.0) -MXG = 1 -MYG = 1 -NXPE = 1 - [mesh] symmetricglobalx = true file = fci.grid.nc +MXG = 1 +MYG = 1 +NXPE = 1 [mesh:ddy] first = C2 diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index 5f5d48bee2..e434ea3ecf 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -3,11 +3,15 @@ # Generate manufactured solution and sources for FCI test # -from boutdata.mms import * +from math import pi +import warnings -from sympy import sin, cos, sqrt +from boututils.boutwarnings import AlwaysWarning +from boutdata.data import BoutOptionsFile +from boutdata.mms import diff, exprToStr, x, y, z +from sympy import sin, sqrt, Expr -from math import pi +warnings.simplefilter("ignore", AlwaysWarning) f = sin(y - z) + sin(y - 2 * z) @@ -23,17 +27,31 @@ B = sqrt(Bpx**2 + Bt**2) -def FCI_ddy(f): +def FCI_ddy(f: Expr) -> Expr: return (Bt * diff(f, y) * 2.0 * pi / Ly + Bpx * diff(f, z) * 2.0 * pi / Lz) / B -def FCI_div_par(f): + +def FCI_div_par(f: Expr) -> Expr: return Bpx * FCI_ddy(f / Bpx) ############################################ # Equations solved -print(f"input_field = {exprToStr(f)}") -print(f"grad_par_solution = {exprToStr(FCI_ddy(f))}") -print(f"grad2_par2_solution = {exprToStr(FCI_ddy(FCI_ddy(f)))}") -print(f"div_par_solution = {exprToStr(FCI_div_par(f))}") +input_field = exprToStr(f) +grad_par_solution = exprToStr(FCI_ddy(f)) +grad2_par2_solution = exprToStr(FCI_ddy(FCI_ddy(f))) +div_par_solution = exprToStr(FCI_div_par(f)) + +print(f"input_field = {input_field}") +print(f"grad_par_solution = {grad_par_solution}") +print(f"grad2_par2_solution = {grad2_par2_solution}") +print(f"div_par_solution = {div_par_solution}") +print(f"div_par_K_grad_par_solution = {div_par_K_grad_par_solution}") + +options = BoutOptionsFile("data/BOUT.inp") +options["input_field"] = input_field +options["grad_par_solution"] = grad_par_solution +options["grad2_par2_solution"] = grad2_par2_solution +options["div_par_solution"] = div_par_solution +options.write("data/BOUT.inp", overwrite=True) From 560b005cb95826a4e86c6d1003def6edd3e3e803 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 16:34:44 +0100 Subject: [PATCH 192/259] tests: Add test for FCI `Div_par_K_Grad_par` --- tests/MMS/spatial/fci/data/BOUT.inp | 2 ++ tests/MMS/spatial/fci/fci_mms.cxx | 5 ++++- tests/MMS/spatial/fci/mms.py | 23 ++++++++++++++++++----- tests/MMS/spatial/fci/runtest | 5 +++-- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/MMS/spatial/fci/data/BOUT.inp b/tests/MMS/spatial/fci/data/BOUT.inp index 0088a000f4..a64fc087f5 100644 --- a/tests/MMS/spatial/fci/data/BOUT.inp +++ b/tests/MMS/spatial/fci/data/BOUT.inp @@ -2,6 +2,8 @@ input_field = sin(y - 2*z) + sin(y - z) grad_par_solution = (6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y - z)) + 0.628318530717959*cos(y - 2*z) + 0.628318530717959*cos(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) grad2_par2_solution = (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0))/sqrt((0.01*x + 0.045)^2 + 1.0) div_par_solution = (0.01*x + 0.045)*(-12.5663706143592*cos(y - 2*z) - 6.28318530717959*cos(y - z) + 0.628318530717959*(cos(y - 2*z) + cos(y - z))/(0.01*x + 0.045))/sqrt((0.01*x + 0.045)^2 + 1.0) +div_par_K_grad_par_solution = (0.01*x + 0.045)*(6.28318530717959*sin(y - z) - 0.628318530717959*sin(y - z)/(0.01*x + 0.045))*(6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y - z)) + 0.628318530717959*cos(y - 2*z) + 0.628318530717959*cos(y - z))/((0.01*x + 0.045)^2 + 1.0) + (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0))*cos(y - z)/sqrt((0.01*x + 0.045)^2 + 1.0) +K = cos(y - z) [mesh] symmetricglobalx = true diff --git a/tests/MMS/spatial/fci/fci_mms.cxx b/tests/MMS/spatial/fci/fci_mms.cxx index bc995424c6..a0b70e9da6 100644 --- a/tests/MMS/spatial/fci/fci_mms.cxx +++ b/tests/MMS/spatial/fci/fci_mms.cxx @@ -2,6 +2,7 @@ #include "bout/difops.hxx" #include "bout/field3d.hxx" #include "bout/field_factory.hxx" +#include "bout/options.hxx" #include @@ -34,9 +35,10 @@ int main(int argc, char** argv) { using bout::globals::mesh; Field3D input{FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh)}; + Field3D K{FieldFactory::get()->create3D("K", Options::getRoot(), mesh)}; // Communicate to calculate parallel transform - mesh->communicate(input); + mesh->communicate(input, K); Options dump; // Add mesh geometry variables @@ -45,6 +47,7 @@ int main(int argc, char** argv) { fci_op_test("grad_par", dump, input, Grad_par(input)); fci_op_test("grad2_par2", dump, input, Grad2_par2(input)); fci_op_test("div_par", dump, input, Div_par(input)); + fci_op_test("div_par_K_grad_par", dump, input, Div_par_K_Grad_par(K, input)); bout::writeDefaultOutputFile(dump); diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index e434ea3ecf..79ec661507 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -9,11 +9,12 @@ from boututils.boutwarnings import AlwaysWarning from boutdata.data import BoutOptionsFile from boutdata.mms import diff, exprToStr, x, y, z -from sympy import sin, sqrt, Expr +from sympy import sin, cos, sqrt, Expr warnings.simplefilter("ignore", AlwaysWarning) f = sin(y - z) + sin(y - 2 * z) +K = cos(z - y) Lx = 0.1 Ly = 10.0 @@ -27,23 +28,33 @@ B = sqrt(Bpx**2 + Bt**2) -def FCI_ddy(f: Expr) -> Expr: +def FCI_grad_par(f: Expr) -> Expr: return (Bt * diff(f, y) * 2.0 * pi / Ly + Bpx * diff(f, z) * 2.0 * pi / Lz) / B +def FCI_grad2_par2(f: Expr) -> Expr: + return FCI_grad_par(FCI_grad_par(f)) + + def FCI_div_par(f: Expr) -> Expr: - return Bpx * FCI_ddy(f / Bpx) + return Bpx * FCI_grad_par(f / Bpx) + + +def FCI_div_par_K_grad_par(f: Expr, K: Expr) -> Expr: + return (K * FCI_grad2_par2(f)) + (FCI_div_par(K) * FCI_grad_par(f)) ############################################ # Equations solved input_field = exprToStr(f) -grad_par_solution = exprToStr(FCI_ddy(f)) -grad2_par2_solution = exprToStr(FCI_ddy(FCI_ddy(f))) +grad_par_solution = exprToStr(FCI_grad_par(f)) +grad2_par2_solution = exprToStr(FCI_grad2_par2(f)) div_par_solution = exprToStr(FCI_div_par(f)) +div_par_K_grad_par_solution = exprToStr(FCI_div_par_K_grad_par(f, K)) print(f"input_field = {input_field}") +print(f"K = {K}") print(f"grad_par_solution = {grad_par_solution}") print(f"grad2_par2_solution = {grad2_par2_solution}") print(f"div_par_solution = {div_par_solution}") @@ -51,7 +62,9 @@ def FCI_div_par(f: Expr) -> Expr: options = BoutOptionsFile("data/BOUT.inp") options["input_field"] = input_field +options["K"] = K options["grad_par_solution"] = grad_par_solution options["grad2_par2_solution"] = grad2_par2_solution options["div_par_solution"] = div_par_solution +options["div_par_K_grad_par_solution"] = div_par_K_grad_par_solution options.write("data/BOUT.inp", overwrite=True) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index c98d924e7b..5a19877a45 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -24,7 +24,7 @@ from scipy.interpolate import RectBivariateSpline as RBS DIRECTORY = "data" NPROC = 2 MTHREAD = 2 -OPERATORS = ("grad_par", "grad2_par2", "div_par") +OPERATORS = ("grad_par", "grad2_par2", "div_par", "div_par_K_grad_par") NX = 3 # Resolution in y and z NLIST = [8, 16, 32, 64, 128] @@ -177,7 +177,8 @@ def make_plots(cases): print("No matplotlib") return - fig, axes = plt.subplots(1, len(OPERATORS), figsize=(9, 4)) + num_operators = len(OPERATORS) + fig, axes = plt.subplots(1, num_operators, figsize=(num_operators * 4, 4)) for ax, operator in zip(axes, OPERATORS): for name, case in cases.items(): From 8910b61ef3ef36d9892893396b44b82dddc27a4f Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 7 Oct 2025 17:30:48 +0100 Subject: [PATCH 193/259] Many small fixes for FCI - Include all relevant headers, remove unused ones, add some forward declarations - Make data `private` instead of `protected` - Add getter instead of `const` member - Change member reference to pointer - Move ctor to .cxx file - Use `std::array` instead of C array - Bunch of other small clang-tidy fixes --- src/mesh/parallel/fci.cxx | 178 ++++++++++++++++++++++++++------------ src/mesh/parallel/fci.hxx | 83 ++++++------------ 2 files changed, 150 insertions(+), 111 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 659df8600d..99ca35bb40 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -37,79 +37,99 @@ **************************************************************************/ #include "fci.hxx" + +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/field2d.hxx" +#include "bout/field3d.hxx" +#include "bout/field_data.hxx" +#include "bout/mesh.hxx" +#include "bout/msg_stack.hxx" +#include "bout/options.hxx" #include "bout/parallel_boundary_op.hxx" #include "bout/parallel_boundary_region.hxx" -#include -#include -#include -#include -#include +#include "bout/paralleltransform.hxx" +#include "bout/region.hxx" + +#include +#include +#include +#include +#include +#include #include +#include + +using namespace std::string_view_literals; -FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& UNUSED(dy), Options& options, - int offset_, const std::shared_ptr& inner_boundary, +FCIMap::FCIMap(Mesh& mesh, [[maybe_unused]] const Coordinates::FieldMetric& dy, + Options& options, int offset, + const std::shared_ptr& inner_boundary, const std::shared_ptr& outer_boundary, bool zperiodic) - : map_mesh(mesh), offset(offset_), - region_no_boundary(map_mesh.getRegion("RGN_NOBNDRY")), + : map_mesh(&mesh), offset_(offset), + region_no_boundary(map_mesh->getRegion("RGN_NOBNDRY")), corner_boundary_mask(map_mesh) { - TRACE("Creating FCIMAP for direction {:d}", offset); + TRACE("Creating FCIMAP for direction {:d}", offset_); - if (offset == 0) { + if (offset_ == 0) { throw BoutException( "FCIMap called with offset = 0; You probably didn't mean to do that"); } auto& interpolation_options = options["xzinterpolation"]; - interp = - XZInterpolationFactory::getInstance().create(&interpolation_options, &map_mesh); - interp->setYOffset(offset); + interp = XZInterpolationFactory::getInstance().create(&interpolation_options, map_mesh); + interp->setYOffset(offset_); interp_corner = - XZInterpolationFactory::getInstance().create(&interpolation_options, &map_mesh); - interp_corner->setYOffset(offset); + XZInterpolationFactory::getInstance().create(&interpolation_options, map_mesh); + interp_corner->setYOffset(offset_); // Index-space coordinates of forward/backward points - Field3D xt_prime{&map_mesh}, zt_prime{&map_mesh}; + Field3D xt_prime{map_mesh}; + Field3D zt_prime{map_mesh}; // Real-space coordinates of grid points - Field3D R{&map_mesh}, Z{&map_mesh}; + Field3D R{map_mesh}; + Field3D Z{map_mesh}; // Real-space coordinates of forward/backward points - Field3D R_prime{&map_mesh}, Z_prime{&map_mesh}; + Field3D R_prime{map_mesh}; + Field3D Z_prime{map_mesh}; - map_mesh.get(R, "R", 0.0, false); - map_mesh.get(Z, "Z", 0.0, false); + map_mesh->get(R, "R", 0.0, false); + map_mesh->get(Z, "Z", 0.0, false); // Get a unique name for a field based on the sign/magnitude of the offset - const auto parallel_slice_field_name = [&](std::string field) -> std::string { - const std::string direction = (offset > 0) ? "forward" : "backward"; + const auto parallel_slice_field_name = [&](std::string_view field) -> std::string { + const auto direction = (offset_ > 0) ? "forward"sv : "backward"sv; // We only have a suffix for parallel slices beyond the first // This is for backwards compatibility - const std::string slice_suffix = - (std::abs(offset) > 1) ? "_" + std::to_string(std::abs(offset)) : ""; - return direction + "_" + field + slice_suffix; + const auto slice_suffix = + (std::abs(offset_) > 1) ? fmt::format("_{}", std::abs(offset_)) : ""; + return fmt::format("{}_{}{}", direction, field, slice_suffix); }; // If we can't read in any of these fields, things will silently not // work, so best throw - if (map_mesh.get(xt_prime, parallel_slice_field_name("xt_prime"), 0.0, false) != 0) { + if (map_mesh->get(xt_prime, parallel_slice_field_name("xt_prime"), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("xt_prime")); } - if (map_mesh.get(zt_prime, parallel_slice_field_name("zt_prime"), 0.0, false) != 0) { + if (map_mesh->get(zt_prime, parallel_slice_field_name("zt_prime"), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("zt_prime")); } - if (map_mesh.get(R_prime, parallel_slice_field_name("R"), 0.0, false) != 0) { + if (map_mesh->get(R_prime, parallel_slice_field_name("R"), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("R")); } - if (map_mesh.get(Z_prime, parallel_slice_field_name("Z"), 0.0, false) != 0) { + if (map_mesh->get(Z_prime, parallel_slice_field_name("Z"), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("Z")); @@ -157,7 +177,7 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& UNUSED(dy), Options& interp->calcWeights(xt_prime, zt_prime); } - const int ncz = map_mesh.LocalNz; + const int ncz = map_mesh->LocalNz; BoutMask to_remove(map_mesh); // Serial loop because call to BoundaryRegionPar::addPoint @@ -165,15 +185,16 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& UNUSED(dy), Options& BOUT_FOR_SERIAL(i, xt_prime.getRegion("RGN_NOBNDRY")) { // z is periodic, so make sure the z-index wraps around if (zperiodic) { - zt_prime[i] = zt_prime[i] - - ncz * (static_cast(zt_prime[i] / static_cast(ncz))); + zt_prime[i] = + zt_prime[i] + - (ncz * (static_cast(zt_prime[i] / static_cast(ncz)))); if (zt_prime[i] < 0.0) { zt_prime[i] += ncz; } } - if ((xt_prime[i] >= map_mesh.xstart) and (xt_prime[i] <= map_mesh.xend)) { + if ((xt_prime[i] >= map_mesh->xstart) and (xt_prime[i] <= map_mesh->xend)) { // Not a boundary continue; } @@ -213,7 +234,7 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& UNUSED(dy), Options& const BoutReal dR_dz = 0.5 * (R[i_zp] - R[i_zm]); const BoutReal dZ_dz = 0.5 * (Z[i_zp] - Z[i_zm]); - const BoutReal det = dR_dx * dZ_dz - dR_dz * dZ_dx; // Determinant of 2x2 matrix + const BoutReal det = (dR_dx * dZ_dz) - (dR_dz * dZ_dx); // Determinant of 2x2 matrix const BoutReal dR = R_prime[i] - R[i]; const BoutReal dZ = Z_prime[i] - Z[i]; @@ -226,9 +247,9 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& UNUSED(dy), Options& // outer boundary. However, if any of the surrounding points are negative, // that also means inner. So to differentiate between inner and outer we // need at least 2 points in the domain. - ASSERT2(map_mesh.xend - map_mesh.xstart >= 2); - auto boundary = (xt_prime[i] < map_mesh.xstart) ? inner_boundary : outer_boundary; - boundary->add_point(x, y, z, x + dx, y + 0.5 * offset, + ASSERT2(map_mesh->xend - map_mesh->xstart >= 2); + auto boundary = (xt_prime[i] < map_mesh->xstart) ? inner_boundary : outer_boundary; + boundary->add_point(x, y, z, x + dx, y + (0.5 * offset_), z + dz, // Intersection point in local index space 0.5, // Distance to intersection 1 // Default to that there is a point in the other direction @@ -238,13 +259,14 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& UNUSED(dy), Options& interp->setRegion(region_no_boundary); - const auto region = fmt::format("RGN_YPAR_{:+d}", offset); - if (not map_mesh.hasRegion3D(region)) { + const auto region = fmt::format("RGN_YPAR_{:+d}", offset_); + if (not map_mesh->hasRegion3D(region)) { // The valid region for this slice - map_mesh.addRegion3D( - region, Region(map_mesh.xstart, map_mesh.xend, map_mesh.ystart + offset, - map_mesh.yend + offset, 0, map_mesh.LocalNz - 1, - map_mesh.LocalNy, map_mesh.LocalNz)); + map_mesh->addRegion3D(region, Region(map_mesh->xstart, map_mesh->xend, + map_mesh->ystart + offset_, + map_mesh->yend + offset_, 0, + map_mesh->LocalNz - 1, map_mesh->LocalNy, + map_mesh->LocalNz)); } } @@ -252,7 +274,7 @@ Field3D FCIMap::integrate(Field3D& f) const { TRACE("FCIMap::integrate"); ASSERT1(f.getDirectionY() == YDirectionType::Standard); - ASSERT1(&map_mesh == f.getMesh()); + ASSERT1(map_mesh == f.getMesh()); // Cell centre values Field3D centre = interp->interpolate(f); @@ -267,7 +289,7 @@ Field3D FCIMap::integrate(Field3D& f) const { #endif BOUT_FOR(i, region_no_boundary) { - const auto inext = i.yp(offset); + const auto inext = i.yp(offset_); const BoutReal f_c = centre[inext]; const auto izm = i.zm(); const int x = i.x(); @@ -276,7 +298,7 @@ Field3D FCIMap::integrate(Field3D& f) const { const int zm = izm.z(); if (corner_boundary_mask(x, y, z) || corner_boundary_mask(x - 1, y, z) || corner_boundary_mask(x, y, zm) || corner_boundary_mask(x - 1, y, zm) - || (x == map_mesh.xstart)) { + || (x == map_mesh->xstart)) { // One of the corners leaves the domain. // Use the cell centre value, since boundary conditions are not // currently applied to corners. @@ -297,10 +319,60 @@ Field3D FCIMap::integrate(Field3D& f) const { return result; } +FCITransform::FCITransform(Mesh& mesh, const Coordinates::FieldMetric& dy, bool zperiodic, + Options* opt) + : ParallelTransform(mesh, opt), R{&mesh}, Z{&mesh} { + + // check the coordinate system used for the grid data source + FCITransform::checkInputGrid(); + + // Real-space coordinates of grid cells + mesh.get(R, "R", 0.0, false); + mesh.get(Z, "Z", 0.0, false); + + auto forward_boundary_xin = + std::make_shared("FCI_forward", BNDRY_PAR_FWD_XIN, +1, &mesh); + auto backward_boundary_xin = + std::make_shared("FCI_backward", BNDRY_PAR_BKWD_XIN, -1, &mesh); + auto forward_boundary_xout = + std::make_shared("FCI_forward", BNDRY_PAR_FWD_XOUT, +1, &mesh); + auto backward_boundary_xout = + std::make_shared("FCI_backward", BNDRY_PAR_BKWD_XOUT, -1, &mesh); + + // Add the boundary region to the mesh's vector of parallel boundaries + mesh.addBoundaryPar(forward_boundary_xin, BoundaryParType::xin_fwd); + mesh.addBoundaryPar(backward_boundary_xin, BoundaryParType::xin_bwd); + mesh.addBoundaryPar(forward_boundary_xout, BoundaryParType::xout_fwd); + mesh.addBoundaryPar(backward_boundary_xout, BoundaryParType::xout_bwd); + + field_line_maps.reserve(static_cast(mesh.ystart) * 2); + for (int offset = 1; offset < mesh.ystart + 1; ++offset) { + field_line_maps.emplace_back(mesh, dy, options, offset, forward_boundary_xin, + forward_boundary_xout, zperiodic); + field_line_maps.emplace_back(mesh, dy, options, -offset, backward_boundary_xin, + backward_boundary_xout, zperiodic); + } + ASSERT0(mesh.ystart == 1); + const std::array bndries = {forward_boundary_xin, forward_boundary_xout, + backward_boundary_xin, backward_boundary_xout}; + for (const auto& bndry : bndries) { + for (const auto& bndry2 : bndries) { + if (bndry->dir == bndry2->dir) { + continue; + } + for (bndry->first(); !bndry->isDone(); bndry->next()) { + if (bndry2->contains(*bndry)) { + bndry->setValid(0); + } + } + } + } +} + void FCITransform::checkInputGrid() { std::string parallel_transform; if (mesh.isDataSourceGridFile() - && !mesh.get(parallel_transform, "parallel_transform")) { + && (mesh.get(parallel_transform, "parallel_transform") == 0)) { if (parallel_transform != "fci") { throw BoutException( "Incorrect parallel transform type '" + parallel_transform @@ -308,8 +380,8 @@ void FCITransform::checkInputGrid() { "to generate metric components for FCITransform. Should be 'fci'."); } } // else: parallel_transform variable not found in grid input, indicates older input - // file or grid from options so must rely on the user having ensured the type is - // correct + // file or grid from options so must rely on the user having ensured the type is + // correct } void FCITransform::calcParallelSlices(Field3D& f) { @@ -325,8 +397,8 @@ void FCITransform::calcParallelSlices(Field3D& f) { // Interpolate f onto yup and ydown fields for (const auto& map : field_line_maps) { - f.ynext(map.offset) = map.interpolate(f); - f.ynext(map.offset).setRegion(fmt::format("RGN_YPAR_{:+d}", map.offset)); + f.ynext(map.offset()) = map.interpolate(f); + f.ynext(map.offset()).setRegion(fmt::format("RGN_YPAR_{:+d}", map.offset())); } } @@ -343,7 +415,7 @@ void FCITransform::integrateParallelSlices(Field3D& f) { // Integrate f onto yup and ydown fields for (const auto& map : field_line_maps) { - f.ynext(map.offset) = map.integrate(f); + f.ynext(map.offset()) = map.integrate(f); } } diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index 1a02f558e1..65529a4c4e 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -26,6 +26,11 @@ #ifndef BOUT_FCITRANSFORM_H #define BOUT_FCITRANSFORM_H +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutexception.hxx" +#include "bout/coordinates.hxx" +#include "bout/region.hxx" #include #include #include @@ -33,25 +38,26 @@ #include #include +#include #include +class BoundaryRegionPar; +class FieldPerp; +class Field2D; +class Field3D; +class Options; + /// Field line map - contains the coefficients for interpolation class FCIMap { /// Interpolation objects std::unique_ptr interp; // Cell centre std::unique_ptr interp_corner; // Cell corner at (x+1, z+1) -public: - FCIMap() = delete; - FCIMap(Mesh& mesh, const Coordinates::FieldMetric& dy, Options& options, int offset, - const std::shared_ptr& inner_boundary, - const std::shared_ptr& outer_boundary, bool zperiodic); - // The mesh this map was created on - Mesh& map_mesh; + Mesh* map_mesh; /// Direction of map - const int offset; + int offset_; /// region containing all points where the field line has not left the /// domain @@ -59,8 +65,17 @@ public: /// If any of the integration area has left the domain BoutMask corner_boundary_mask; +public: + FCIMap() = delete; + FCIMap(Mesh& mesh, const Coordinates::FieldMetric& dy, Options& options, int offset, + const std::shared_ptr& inner_boundary, + const std::shared_ptr& outer_boundary, bool zperiodic); + + /// Direction of map + int offset() const { return offset_; } + Field3D interpolate(Field3D& f) const { - ASSERT1(&map_mesh == f.getMesh()); + ASSERT1(map_mesh == f.getMesh()); return interp->interpolate(f); } @@ -72,55 +87,7 @@ class FCITransform : public ParallelTransform { public: FCITransform() = delete; FCITransform(Mesh& mesh, const Coordinates::FieldMetric& dy, bool zperiodic = true, - Options* opt = nullptr) - : ParallelTransform(mesh, opt), R{&mesh}, Z{&mesh} { - - // check the coordinate system used for the grid data source - FCITransform::checkInputGrid(); - - // Real-space coordinates of grid cells - mesh.get(R, "R", 0.0, false); - mesh.get(Z, "Z", 0.0, false); - - auto forward_boundary_xin = - std::make_shared("FCI_forward", BNDRY_PAR_FWD_XIN, +1, &mesh); - auto backward_boundary_xin = std::make_shared( - "FCI_backward", BNDRY_PAR_BKWD_XIN, -1, &mesh); - auto forward_boundary_xout = - std::make_shared("FCI_forward", BNDRY_PAR_FWD_XOUT, +1, &mesh); - auto backward_boundary_xout = std::make_shared( - "FCI_backward", BNDRY_PAR_BKWD_XOUT, -1, &mesh); - - // Add the boundary region to the mesh's vector of parallel boundaries - mesh.addBoundaryPar(forward_boundary_xin, BoundaryParType::xin_fwd); - mesh.addBoundaryPar(backward_boundary_xin, BoundaryParType::xin_bwd); - mesh.addBoundaryPar(forward_boundary_xout, BoundaryParType::xout_fwd); - mesh.addBoundaryPar(backward_boundary_xout, BoundaryParType::xout_bwd); - - field_line_maps.reserve(mesh.ystart * 2); - for (int offset = 1; offset < mesh.ystart + 1; ++offset) { - field_line_maps.emplace_back(mesh, dy, options, offset, forward_boundary_xin, - forward_boundary_xout, zperiodic); - field_line_maps.emplace_back(mesh, dy, options, -offset, backward_boundary_xin, - backward_boundary_xout, zperiodic); - } - ASSERT0(mesh.ystart == 1); - std::shared_ptr bndries[]{ - forward_boundary_xin, forward_boundary_xout, backward_boundary_xin, - backward_boundary_xout}; - for (auto& bndry : bndries) { - for (const auto& bndry2 : bndries) { - if (bndry->dir == bndry2->dir) { - continue; - } - for (bndry->first(); !bndry->isDone(); bndry->next()) { - if (bndry2->contains(*bndry)) { - bndry->setValid(0); - } - } - } - } - } + Options* opt = nullptr); void calcParallelSlices(Field3D& f) override; From d170ca8a69c817b8f8290eea122d03679d889638 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 8 Oct 2025 10:11:22 +0100 Subject: [PATCH 194/259] tests: Fix for 3D metric in FCI test The Div_par operators use parallel slices of B -- with 2D metrics, these are just the field itself, in 3D we need the actual slices. While `Coordinates::geometry` does communicate the fields, it puts off calculating the parallel slices because that needs the fully constructed `Coordinates`. Upcoming changes should fix this and remove the need to explicitly communicate `Coordinates` members. --- src/mesh/coordinates.cxx | 2 +- tests/MMS/spatial/fci/fci_mms.cxx | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 34c524d1e7..3233f25e07 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1588,7 +1588,7 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, // Need Bxy at location of f, which might be different from location of this // Coordinates object - auto Bxy_floc = f.getCoordinates()->Bxy; + const auto& Bxy_floc = f.getCoordinates()->Bxy; if (!f.hasParallelSlices()) { // No yup/ydown fields. The Grad_par operator will diff --git a/tests/MMS/spatial/fci/fci_mms.cxx b/tests/MMS/spatial/fci/fci_mms.cxx index a0b70e9da6..b30ec05e9a 100644 --- a/tests/MMS/spatial/fci/fci_mms.cxx +++ b/tests/MMS/spatial/fci/fci_mms.cxx @@ -1,4 +1,5 @@ #include "bout/bout.hxx" +#include "bout/build_config.hxx" #include "bout/difops.hxx" #include "bout/field3d.hxx" #include "bout/field_factory.hxx" @@ -37,7 +38,13 @@ int main(int argc, char** argv) { Field3D input{FieldFactory::get()->create3D("input_field", Options::getRoot(), mesh)}; Field3D K{FieldFactory::get()->create3D("K", Options::getRoot(), mesh)}; - // Communicate to calculate parallel transform + // Communicate to calculate parallel transform. + if constexpr (bout::build::use_metric_3d) { + // Div_par operators require B parallel slices: + // Coordinates::geometry doesn't ensure this (yet) + auto& Bxy = mesh->getCoordinates()->Bxy; + mesh->communicate(Bxy); + } mesh->communicate(input, K); Options dump; From bdef58e2f17de77cae473cbbe308b28e9e5e40ba Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 8 Oct 2025 11:18:59 +0100 Subject: [PATCH 195/259] tests: Add test for FCI `Laplace_par` --- tests/MMS/spatial/fci/data/BOUT.inp | 1 + tests/MMS/spatial/fci/fci_mms.cxx | 1 + tests/MMS/spatial/fci/mms.py | 7 +++++++ tests/MMS/spatial/fci/runtest | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/MMS/spatial/fci/data/BOUT.inp b/tests/MMS/spatial/fci/data/BOUT.inp index a64fc087f5..f7a5d15287 100644 --- a/tests/MMS/spatial/fci/data/BOUT.inp +++ b/tests/MMS/spatial/fci/data/BOUT.inp @@ -4,6 +4,7 @@ grad2_par2_solution = (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01 div_par_solution = (0.01*x + 0.045)*(-12.5663706143592*cos(y - 2*z) - 6.28318530717959*cos(y - z) + 0.628318530717959*(cos(y - 2*z) + cos(y - z))/(0.01*x + 0.045))/sqrt((0.01*x + 0.045)^2 + 1.0) div_par_K_grad_par_solution = (0.01*x + 0.045)*(6.28318530717959*sin(y - z) - 0.628318530717959*sin(y - z)/(0.01*x + 0.045))*(6.28318530717959*(0.01*x + 0.045)*(-2*cos(y - 2*z) - cos(y - z)) + 0.628318530717959*cos(y - 2*z) + 0.628318530717959*cos(y - z))/((0.01*x + 0.045)^2 + 1.0) + (6.28318530717959*(0.01*x + 0.045)*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0))*cos(y - z)/sqrt((0.01*x + 0.045)^2 + 1.0) K = cos(y - z) +laplace_par_solution = (0.01*x + 0.045)*(6.28318530717959*(6.28318530717959*(0.01*x + 0.045)*(-4*sin(y - 2*z) - sin(y - z)) + 1.25663706143592*sin(y - 2*z) + 0.628318530717959*sin(y - z))/sqrt((0.01*x + 0.045)^2 + 1.0) + 0.628318530717959*(6.28318530717959*(0.01*x + 0.045)*(2*sin(y - 2*z) + sin(y - z)) - 0.628318530717959*sin(y - 2*z) - 0.628318530717959*sin(y - z))/((0.01*x + 0.045)*sqrt((0.01*x + 0.045)^2 + 1.0)))/sqrt((0.01*x + 0.045)^2 + 1.0) [mesh] symmetricglobalx = true diff --git a/tests/MMS/spatial/fci/fci_mms.cxx b/tests/MMS/spatial/fci/fci_mms.cxx index b30ec05e9a..b9d335a3c4 100644 --- a/tests/MMS/spatial/fci/fci_mms.cxx +++ b/tests/MMS/spatial/fci/fci_mms.cxx @@ -55,6 +55,7 @@ int main(int argc, char** argv) { fci_op_test("grad2_par2", dump, input, Grad2_par2(input)); fci_op_test("div_par", dump, input, Div_par(input)); fci_op_test("div_par_K_grad_par", dump, input, Div_par_K_Grad_par(K, input)); + fci_op_test("laplace_par", dump, input, Laplace_par(input)); bout::writeDefaultOutputFile(dump); diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index 79ec661507..178c158572 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -44,6 +44,10 @@ def FCI_div_par_K_grad_par(f: Expr, K: Expr) -> Expr: return (K * FCI_grad2_par2(f)) + (FCI_div_par(K) * FCI_grad_par(f)) +def FCI_Laplace_par(f: Expr) -> Expr: + return FCI_div_par(FCI_grad_par(f)) + + ############################################ # Equations solved @@ -52,6 +56,7 @@ def FCI_div_par_K_grad_par(f: Expr, K: Expr) -> Expr: grad2_par2_solution = exprToStr(FCI_grad2_par2(f)) div_par_solution = exprToStr(FCI_div_par(f)) div_par_K_grad_par_solution = exprToStr(FCI_div_par_K_grad_par(f, K)) +Laplace_par_solution = exprToStr(FCI_Laplace_par(f)) print(f"input_field = {input_field}") print(f"K = {K}") @@ -59,6 +64,7 @@ def FCI_div_par_K_grad_par(f: Expr, K: Expr) -> Expr: print(f"grad2_par2_solution = {grad2_par2_solution}") print(f"div_par_solution = {div_par_solution}") print(f"div_par_K_grad_par_solution = {div_par_K_grad_par_solution}") +print(f"laplace_par_solution = {Laplace_par_solution}") options = BoutOptionsFile("data/BOUT.inp") options["input_field"] = input_field @@ -67,4 +73,5 @@ def FCI_div_par_K_grad_par(f: Expr, K: Expr) -> Expr: options["grad2_par2_solution"] = grad2_par2_solution options["div_par_solution"] = div_par_solution options["div_par_K_grad_par_solution"] = div_par_K_grad_par_solution +options["laplace_par_solution"] = Laplace_par_solution options.write("data/BOUT.inp", overwrite=True) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 5a19877a45..612486bdf4 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -24,7 +24,7 @@ from scipy.interpolate import RectBivariateSpline as RBS DIRECTORY = "data" NPROC = 2 MTHREAD = 2 -OPERATORS = ("grad_par", "grad2_par2", "div_par", "div_par_K_grad_par") +OPERATORS = ("grad_par", "grad2_par2", "div_par", "div_par_K_grad_par", "laplace_par") NX = 3 # Resolution in y and z NLIST = [8, 16, 32, 64, 128] From 969997c376497a5074dddcb14a3bfbb9802dab2c Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 8 Oct 2025 11:22:57 +0100 Subject: [PATCH 196/259] Reduce duplication in FCI mms script --- tests/MMS/spatial/fci/mms.py | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index 178c158572..b28e337ac0 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -51,27 +51,19 @@ def FCI_Laplace_par(f: Expr) -> Expr: ############################################ # Equations solved -input_field = exprToStr(f) -grad_par_solution = exprToStr(FCI_grad_par(f)) -grad2_par2_solution = exprToStr(FCI_grad2_par2(f)) -div_par_solution = exprToStr(FCI_div_par(f)) -div_par_K_grad_par_solution = exprToStr(FCI_div_par_K_grad_par(f, K)) -Laplace_par_solution = exprToStr(FCI_Laplace_par(f)) - -print(f"input_field = {input_field}") -print(f"K = {K}") -print(f"grad_par_solution = {grad_par_solution}") -print(f"grad2_par2_solution = {grad2_par2_solution}") -print(f"div_par_solution = {div_par_solution}") -print(f"div_par_K_grad_par_solution = {div_par_K_grad_par_solution}") -print(f"laplace_par_solution = {Laplace_par_solution}") - options = BoutOptionsFile("data/BOUT.inp") -options["input_field"] = input_field -options["K"] = K -options["grad_par_solution"] = grad_par_solution -options["grad2_par2_solution"] = grad2_par2_solution -options["div_par_solution"] = div_par_solution -options["div_par_K_grad_par_solution"] = div_par_K_grad_par_solution -options["laplace_par_solution"] = Laplace_par_solution + +for name, expr in ( + ("input_field", f), + ("K", K), + ("grad_par_solution", FCI_grad_par(f)), + ("grad2_par2_solution", FCI_grad2_par2(f)), + ("div_par_solution", FCI_div_par(f)), + ("div_par_K_grad_par_solution", FCI_div_par_K_grad_par(f, K)), + ("laplace_par_solution", FCI_Laplace_par(f)), +): + expr_str = exprToStr(expr) + print(f"{name} = {expr_str}") + options[name] = expr_str + options.write("data/BOUT.inp", overwrite=True) From 3468db4a26c3fd8584595f4dce5904ee928856a5 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 8 Oct 2025 11:25:56 +0100 Subject: [PATCH 197/259] Remove circular include --- include/bout/difops.hxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/bout/difops.hxx b/include/bout/difops.hxx index 71053d454a..c2fdac195d 100644 --- a/include/bout/difops.hxx +++ b/include/bout/difops.hxx @@ -40,7 +40,9 @@ #include "bout/field3d.hxx" #include "bout/bout_types.hxx" -#include "bout/solver.hxx" +#include "bout/coordinates.hxx" + +class Solver; /*! * Parallel derivative (central differencing) in Y From aee8ecc5356c18501bb6376c345a54fd33dede6e Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 8 Oct 2025 16:48:20 +0100 Subject: [PATCH 198/259] tests: Add cases for FCI interpolation methods --- tests/MMS/spatial/fci/runtest | 44 +++++++++++++++-------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 612486bdf4..6ac0b0bca8 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -99,7 +99,7 @@ def run_fci_operators( ) # Command to run - args = f"MZ={nz} MYG={nslice} mesh:paralleltransform:y_periodic={yperiodic} mesh:ddy:first={name}" + args = f"MZ={nz} MYG={nslice} mesh:paralleltransform:y_periodic={yperiodic} {name}" cmd = f"./fci_mms {args}" print(f"Running command: {cmd}", end="") @@ -138,18 +138,18 @@ def transpose( return result -def check_fci_operators(case: dict) -> bool: +def check_fci_operators(name: str, case: dict) -> bool: failures = [] nslice = case["nslice"] yperiodic = case["yperiodic"] - name = case["name"] order = case["order"] + args = case["args"] all_errors = [] for n in NLIST: - errors = run_fci_operators(nslice, n, yperiodic, name) + errors = run_fci_operators(nslice, n, yperiodic, args) all_errors.append(errors) for operator in OPERATORS: @@ -170,7 +170,7 @@ def check_fci_operators(case: dict) -> bool: return final_errors, failures -def make_plots(cases): +def make_plots(cases: dict[str, dict]): try: import matplotlib.pyplot as plt except ImportError: @@ -199,23 +199,6 @@ def make_plots(cases): plt.close() -def make_case(nslice: int, yperiodic: bool) -> dict[str, Any]: - """ - nslice: - Number of parallel slices (in each direction) - yperiodic: - Run with periodic Y - """ - order = nslice * 2 - return { - "nslice": nslice, - # Which central difference scheme to use and its expected order - "order": order, - "name": f"C{order}", - "yperiodic": yperiodic, - } - - if __name__ == "__main__": build_and_log("FCI MMS test") @@ -240,11 +223,22 @@ if __name__ == "__main__": success = True failures = [] cases = { - "nslice=1": make_case(nslice=1, yperiodic=True), + "nslice=1 hermitespline": { + "nslice": 1, + "order": 2, + "yperiodic": True, + "args": "mesh:ddy:first=C2 mesh:paralleltransform:xzinterpolation:type=hermitespline", + }, + "nslice=1 lagrange4pt": { + "nslice": 1, + "order": 2, + "yperiodic": True, + "args": "mesh:ddy:first=C2 mesh:paralleltransform:xzinterpolation:type=lagrange4pt", + }, } - for case in cases.values(): - error2, failures_ = check_fci_operators(case) + for name, case in cases.items(): + error2, failures_ = check_fci_operators(name, case) case.update(error2) failures.extend(failures_) success &= len(failures) == 0 From 8e9c0fc38a59132a0c50744d9ff2189f39c94e62 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 9 Oct 2025 17:23:45 +0100 Subject: [PATCH 199/259] tests: Increase nx for hermitespline interpolation boundary problem --- src/mesh/interpolation/hermite_spline_xz.cxx | 16 +++++++++++++++- tests/MMS/spatial/fci/runtest | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/mesh/interpolation/hermite_spline_xz.cxx b/src/mesh/interpolation/hermite_spline_xz.cxx index a8e5df7cdf..2fdcade3c9 100644 --- a/src/mesh/interpolation/hermite_spline_xz.cxx +++ b/src/mesh/interpolation/hermite_spline_xz.cxx @@ -72,7 +72,19 @@ void XZHermiteSpline::calcWeights(const Field3D& delta_x, const Field3D& delta_z BoutReal t_x = delta_x(x, y, z) - static_cast(i_corner(x, y, z)); BoutReal t_z = delta_z(x, y, z) - static_cast(k_corner(x, y, z)); - // NOTE: A (small) hack to avoid one-sided differences + // NOTE: A (small) hack to avoid one-sided differences. We need at + // least 2 interior points due to an awkwardness with the + // boundaries. The splines need derivatives in x, but we don't + // know the value in the boundaries, so _any_ interpolation in the + // last interior cell can't be done. Instead, we fudge the + // interpolation in the last cell to be at the extreme right-hand + // edge of the previous cell (that is, exactly on the last + // interior point). However, this doesn't work with only one + // interior point, because we have to do something similar to the + // _first_ cell, and these two fudges cancel out and we end up + // indexing into the boundary anyway. + // TODO(peter): Can we remove this if we apply (dirichlet?) BCs to + // the X derivatives? Note that we need at least _2_ if (i_corner(x, y, z) >= localmesh->xend) { i_corner(x, y, z) = localmesh->xend - 1; t_x = 1.0; @@ -152,6 +164,8 @@ Field3D XZHermiteSpline::interpolate(const Field3D& f, const std::string& region ASSERT1(f.getMesh() == localmesh); Field3D f_interp{emptyFrom(f)}; + // TODO(peter): Should we apply dirichlet BCs to derivatives? + // Derivatives are used for tension and need to be on dimensionless // coordinates Field3D fx = bout::derivatives::index::DDX(f, CELL_DEFAULT, "DEFAULT"); diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 6ac0b0bca8..5393437ff7 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -25,7 +25,9 @@ DIRECTORY = "data" NPROC = 2 MTHREAD = 2 OPERATORS = ("grad_par", "grad2_par2", "div_par", "div_par_K_grad_par", "laplace_par") -NX = 3 +# Note that we need at least _2_ interior points for hermite spline +# interpolation due to an awkwardness with the boundaries +NX = 4 # Resolution in y and z NLIST = [8, 16, 32, 64, 128] dx = 1.0 / array(NLIST) From 6a4204f516f69069ff9a164fb69123826013bace Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 9 Oct 2025 17:24:28 +0100 Subject: [PATCH 200/259] tests: Add monotonichermitespline, decrease resolution scan --- tests/MMS/spatial/fci/runtest | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 5393437ff7..e3d10d989b 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -11,7 +11,6 @@ import json import pathlib import sys from time import time -from typing import Any import boutconfig as conf import zoidberg as zb @@ -29,7 +28,7 @@ OPERATORS = ("grad_par", "grad2_par2", "div_par", "div_par_K_grad_par", "laplace # interpolation due to an awkwardness with the boundaries NX = 4 # Resolution in y and z -NLIST = [8, 16, 32, 64, 128] +NLIST = [8, 16, 32, 64] dx = 1.0 / array(NLIST) @@ -237,6 +236,12 @@ if __name__ == "__main__": "yperiodic": True, "args": "mesh:ddy:first=C2 mesh:paralleltransform:xzinterpolation:type=lagrange4pt", }, + "nslice=1 monotonichermitespline": { + "nslice": 1, + "order": 2, + "yperiodic": True, + "args": "mesh:ddy:first=C2 mesh:paralleltransform:xzinterpolation:type=monotonichermitespline", + }, } for name, case in cases.items(): From 6e35ac05507c0f11bd5ccbcd955fd8b0a9860e3b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 13:50:13 +0100 Subject: [PATCH 201/259] CI: Don't run clang-{tidy,format} on RC branches --- .github/workflows/clang-format.yml | 2 ++ .github/workflows/clang-tidy-review.yml | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 60cf5b6d6f..e32c959cb2 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -8,6 +8,8 @@ on: jobs: clang-format: + # Release candidate branches tend to have big PRs which causes all sorts of problems + if: ${{ !endsWith(github.head_ref, '-rc') }} runs-on: ubuntu-latest steps: # Checkout the pull request branch, also include all history diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 743eefe703..3f20db608f 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -5,9 +5,6 @@ on: paths: - '**.cxx' - '**.hxx' - branches-ignore: - # Release candidate branches tend to have big PRs which causes all sorts of problems - - 'v*rc' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -15,6 +12,8 @@ concurrency: jobs: review: + # Release candidate branches tend to have big PRs which causes all sorts of problems + if: ${{ !endsWith(github.head_ref, '-rc') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 From 6c78dc439884f66943842de574921367c9ffdd67 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 14:06:09 +0100 Subject: [PATCH 202/259] Fix reorder warning from snes --- src/solver/impls/snes/snes.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 2bb163f324..7965107b38 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -115,12 +115,12 @@ SNESSolver::SNESSolver(Options* opts) .doc("Convergence tolerance in terms of the norm of the change in " "the solution between steps") .withDefault(1e-8)), - maxits((*options)["max_nonlinear_iterations"] - .doc("Maximum number of nonlinear iterations per SNES solve") - .withDefault(50)), maxf((*options)["maxf"] .doc("Maximum number of function evaluations per SNES solve") .withDefault(10000)), + maxits((*options)["max_nonlinear_iterations"] + .doc("Maximum number of nonlinear iterations per SNES solve") + .withDefault(50)), lower_its((*options)["lower_its"] .doc("Iterations below which the next timestep is increased") .withDefault(static_cast(maxits * 0.5))), From f1f014376ff22cb46734dec043ee23c507052ef1 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 14:06:27 +0100 Subject: [PATCH 203/259] Fix some easy clang-tidy snes warnings --- src/solver/impls/snes/snes.cxx | 14 +++++++------- src/solver/impls/snes/snes.hxx | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 7965107b38..de6c54388d 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -57,6 +57,7 @@ class ColoringStencil { } }; +namespace { /* * PETSc callback function, which evaluates the nonlinear * function to be solved by SNES. @@ -64,7 +65,7 @@ class ColoringStencil { * This function assumes the context void pointer is a pointer * to an SNESSolver object. */ -static PetscErrorCode FormFunction(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { +PetscErrorCode FormFunction(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, false); } @@ -73,7 +74,7 @@ static PetscErrorCode FormFunction(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { * * This function can be a linearised form of FormFunction */ -static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { +PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { return static_cast(ctx)->snes_function(x, f, true); } @@ -82,21 +83,20 @@ static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -static PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, +PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, true); } -static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { - int ierr; - +PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { // Get the context SNESSolver* s; - ierr = PCShellGetContext(pc, reinterpret_cast(&s)); + int ierr = PCShellGetContext(pc, reinterpret_cast(&s)); CHKERRQ(ierr); PetscFunctionReturn(s->precon(x, y)); } +} SNESSolver::SNESSolver(Options* opts) : Solver(opts), diff --git a/src/solver/impls/snes/snes.hxx b/src/solver/impls/snes/snes.hxx index bd942f09ff..31deae6f06 100644 --- a/src/solver/impls/snes/snes.hxx +++ b/src/solver/impls/snes/snes.hxx @@ -57,7 +57,7 @@ BOUT_ENUM_CLASS(BoutSnesEquationForm, pseudo_transient, rearranged_backward_eule class SNESSolver : public Solver { public: explicit SNESSolver(Options* opts = nullptr); - ~SNESSolver() = default; + ~SNESSolver() override = default; int init() override; int run() override; From 6380657813022478bf2870f4fbe6d6ecabe45259 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 14:06:51 +0100 Subject: [PATCH 204/259] Bump bundled fmt --- externalpackages/fmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/fmt b/externalpackages/fmt index 2ac6c5ca8b..486e7ba579 160000 --- a/externalpackages/fmt +++ b/externalpackages/fmt @@ -1 +1 @@ -Subproject commit 2ac6c5ca8b3dfbcb1cc5cf49a8cc121e3984559c +Subproject commit 486e7ba579a2c677772d004ecd0311142ba481be From 01c406823fed18c63a5745c72333999c82ef8364 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 16:16:30 +0100 Subject: [PATCH 205/259] Fix deprecation warning --- include/bout/invertable_operator.hxx | 56 +++++++++++++--------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/include/bout/invertable_operator.hxx b/include/bout/invertable_operator.hxx index fe139986be..9b9dbba41a 100644 --- a/include/bout/invertable_operator.hxx +++ b/include/bout/invertable_operator.hxx @@ -219,21 +219,18 @@ public: localmesh->LocalNy, localmesh->LocalNz, localmesh->maxregionblocksize); } } - if (localmesh->firstY() or localmesh->lastY()) { - for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { - if (not localmesh->periodicY(ix)) { - if (localmesh->firstY()) { - nocorner3D += - Region(ix, ix, 0, localmesh->ystart - 1, 0, - localmesh->LocalNz - 1, localmesh->LocalNy, - localmesh->LocalNz, localmesh->maxregionblocksize); - } - if (localmesh->lastY()) { - nocorner3D += Region( - ix, ix, localmesh->LocalNy - localmesh->ystart, - localmesh->LocalNy - 1, 0, localmesh->LocalNz - 1, localmesh->LocalNy, - localmesh->LocalNz, localmesh->maxregionblocksize); - } + for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { + if (not localmesh->periodicY(ix)) { + if (localmesh->firstY(ix)) { + nocorner3D += Region( + ix, ix, 0, localmesh->ystart - 1, 0, localmesh->LocalNz - 1, + localmesh->LocalNy, localmesh->LocalNz, localmesh->maxregionblocksize); + } + if (localmesh->lastY(ix)) { + nocorner3D += Region( + ix, ix, localmesh->LocalNy - localmesh->ystart, localmesh->LocalNy - 1, + 0, localmesh->LocalNz - 1, localmesh->LocalNy, localmesh->LocalNz, + localmesh->maxregionblocksize); } } } @@ -259,20 +256,17 @@ public: 0, 0, localmesh->LocalNy, 1, localmesh->maxregionblocksize); } } - if (localmesh->firstY() or localmesh->lastY()) { - for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { - if (not localmesh->periodicY(ix)) { - if (localmesh->firstY()) { - nocorner2D += - Region(ix, ix, 0, localmesh->ystart - 1, 0, 0, - localmesh->LocalNy, 1, localmesh->maxregionblocksize); - } - if (localmesh->lastY()) { - nocorner2D += - Region(ix, ix, localmesh->LocalNy - localmesh->ystart, - localmesh->LocalNy - 1, 0, 0, localmesh->LocalNy, 1, - localmesh->maxregionblocksize); - } + for (int ix = localmesh->xstart; ix <= localmesh->xend; ix++) { + if (not localmesh->periodicY(ix)) { + if (localmesh->firstY(ix)) { + nocorner2D += + Region(ix, ix, 0, localmesh->ystart - 1, 0, 0, + localmesh->LocalNy, 1, localmesh->maxregionblocksize); + } + if (localmesh->lastY(ix)) { + nocorner2D += Region( + ix, ix, localmesh->LocalNy - localmesh->ystart, localmesh->LocalNy - 1, + 0, 0, localmesh->LocalNy, 1, localmesh->maxregionblocksize); } } } @@ -575,7 +569,7 @@ public: }; #endif // PETSC -}; // namespace inversion -}; // namespace bout +}; // namespace inversion +}; // namespace bout #endif // HEADER GUARD From e804d0978e3d33c3bf9e003aadb6ee83efefbc77 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 17:10:32 +0100 Subject: [PATCH 206/259] Remove `boututils` from requirements; bump `boutdata` --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 52d3076d58..078eecac6d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,5 @@ scipy>=1.14.1 netcdf4>=1.7.1 matplotlib>=3.7.0 Cython>=3.0.0 -boututils>=0.2.1 -boutdata>=0.2.1 +boutdata>=0.3.0 zoidberg>=0.2.2 From d5b92c70f2cf640b9e4ed80b8f0d0f79cf35bd09 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 17:13:57 +0100 Subject: [PATCH 207/259] Suppress warning from `nodiscard` function --- tests/unit/sys/test_options.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/sys/test_options.cxx b/tests/unit/sys/test_options.cxx index 448b49fc19..a9a3bf4af4 100644 --- a/tests/unit/sys/test_options.cxx +++ b/tests/unit/sys/test_options.cxx @@ -1099,7 +1099,7 @@ value6 = 12 } TEST_F(OptionsTest, InvalidFormat) { - EXPECT_THROW(fmt::format("{:nope}", Options{}), fmt::format_error); + EXPECT_THROW([[maybe_unused]] auto none = fmt::format("{:nope}", Options{}), fmt::format_error); } TEST_F(OptionsTest, FormatValue) { From 87269806690664888e4a4a3c2469ebac59a4123b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 6 Oct 2025 17:42:20 +0100 Subject: [PATCH 208/259] Add shim for ARKodeGetNumRhsEvals --- src/solver/impls/arkode/arkode.cxx | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/solver/impls/arkode/arkode.cxx b/src/solver/impls/arkode/arkode.cxx index 6f20ce11a6..0151f90167 100644 --- a/src/solver/impls/arkode/arkode.cxx +++ b/src/solver/impls/arkode/arkode.cxx @@ -72,6 +72,18 @@ int arkode_pre(BoutReal t, N_Vector yy, N_Vector yp, N_Vector rvec, N_Vector zve int arkode_jac(N_Vector v, N_Vector Jv, BoutReal t, N_Vector y, N_Vector fy, void* user_data, N_Vector tmp); + +#if SUNDIALS_VERSION_LESS_THAN(7, 2, 0) +// Shim for backwards compatibility +int ARKodeGetNumRhsEvals(void* arkode_mem, int partition_index, long int* num_rhs_evals) { + long int temp = 0; + if (partition_index == 0) { + return ARKStepGetNumRhsEvals(arkode_mem, num_rhs_evals, &temp); + } else { + return ARKStepGetNumRhsEvals(arkode_mem, &temp, num_rhs_evals); + } +} +#endif } // namespace // NOLINTEND(readability-identifier-length) @@ -417,8 +429,7 @@ int ArkodeSolver::init() { if (hasPreconditioner()) { output.write("\tUsing user-supplied preconditioner\n"); - if (ARKodeSetPreconditioner(arkode_mem, nullptr, arkode_pre) - != ARKLS_SUCCESS) { + if (ARKodeSetPreconditioner(arkode_mem, nullptr, arkode_pre) != ARKLS_SUCCESS) { throw BoutException("ARKodeSetPreconditioner failed\n"); } } else { @@ -516,12 +527,13 @@ int ArkodeSolver::run() { } // Get additional diagnostics - long int temp_long_int, temp_long_int2; + long int temp_long_int = 0; ARKodeGetNumSteps(arkode_mem, &temp_long_int); nsteps = int(temp_long_int); - ARKStepGetNumRhsEvals(arkode_mem, &temp_long_int, &temp_long_int2); + ARKodeGetNumRhsEvals(arkode_mem, 0, &temp_long_int); nfe_evals = int(temp_long_int); - nfi_evals = int(temp_long_int2); + ARKodeGetNumRhsEvals(arkode_mem, 1, &temp_long_int); + nfi_evals = int(temp_long_int); if (treatment == Treatment::ImEx or treatment == Treatment::Implicit) { ARKodeGetNumNonlinSolvIters(arkode_mem, &temp_long_int); nniters = int(temp_long_int); From 466fa980d8fb7f80b14252adec8769ab4e98d55a Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 10 Oct 2025 14:20:40 +0100 Subject: [PATCH 209/259] Bump DOI --- CITATION.cff | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 496f8a3154..318fcd1406 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -214,10 +214,10 @@ authors: - family-names: Tsagkaridis given-names: Malamas version: 5.2.0 -date-released: 2023-04-10 +date-released: 2025-10-10 repository-code: https://github.com/boutproject/BOUT-dev url: http://boutproject.github.io/ -doi: 10.5281/zenodo.13753882 +doi: 10.5281/zenodo.17313945 license: 'LGPL-3.0-or-later' references: - type: article diff --git a/README.md b/README.md index c2e035e924..c9e76a1ff4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://github.com/boutproject/BOUT-dev/actions/workflows/tests.yml/badge.svg?branch=next)](https://github.com/boutproject/BOUT-dev/actions) [![License](https://img.shields.io/badge/license-LGPL-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0.en.html) [![py3comp](https://img.shields.io/badge/py3-compatible-brightgreen.svg)](https://img.shields.io/badge/py3-compatible-brightgreen.svg) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13753882.svg)](https://doi.org/10.5281/zenodo.8369888) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17313945.svg)](https://doi.org/10.5281/zenodo.17313945) ``` .______ ______ __ __ .___________. From dc3720f7b57aeb9cf0dde05374dffd664f0e37df Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 10 Oct 2025 11:36:51 -0700 Subject: [PATCH 210/259] snes solver: Consider timestep change at output Previously the timestep adjustment was inside a conditional `if (looping) {...`. The variable `looping` is false when the simulation time reaches or exceeds the next output time. This meant that when the internal timestep exceeded the output step, `looping` was almost always `false` and so the internal timestep would saturate. With this change a timestep adjustment will be considered after every successful internal timestep. Note: There may have been a reason why timestep adjustments were not considered, but I can't remember what it was and it was not documented. --- src/solver/impls/snes/snes.cxx | 93 ++++++++++++++++------------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index de6c54388d..c10095af53 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -1069,62 +1069,59 @@ int SNESSolver::run() { } #endif // PETSC_VERSION_GE(3,20,0) - if (looping) { - - if (pid_controller) { - // Changing the timestep. - // Note: The preconditioner depends on the timestep, - // so we recalculate the jacobian and the preconditioner - // every time the timestep changes - - timestep = pid(timestep, nl_its); - - // NOTE(malamast): Do we really need this? - // Recompute Jacobian (for now) - if (saved_jacobian_lag == 0) { - SNESGetLagJacobian(snes, &saved_jacobian_lag); - SNESSetLagJacobian(snes, 1); - } + if (pid_controller) { + // Changing the timestep. + // Note: The preconditioner depends on the timestep, + // so we recalculate the jacobian and the preconditioner + // every time the timestep changes - } else { + timestep = pid(timestep, nl_its); - // Consider changing the timestep. - // Note: The preconditioner depends on the timestep, - // so if it is not recalculated the it will be less - // effective. - if ((nl_its <= lower_its) && (timestep < max_timestep) - && (steps_since_snes_failure > 2)) { - // Increase timestep slightly - timestep *= timestep_factor_on_lower_its; - - timestep = std::min(timestep, max_timestep); - - // Note: Setting the SNESJacobianFn to NULL retains - // previously set evaluation function. - // - // The SNES Jacobian is a combination of the RHS Jacobian - // and a factor involving the timestep. - // Depends on equation_form - // -> Probably call SNESSetJacobian(snes, Jfd, Jfd, NULL, fdcoloring); - - if (static_cast(lin_its) / nl_its > 4) { - // Recompute Jacobian (for now) - if (saved_jacobian_lag == 0) { - SNESGetLagJacobian(snes, &saved_jacobian_lag); - SNESSetLagJacobian(snes, 1); - } - } + // NOTE(malamast): Do we really need this? + // Recompute Jacobian (for now) + if (saved_jacobian_lag == 0) { + SNESGetLagJacobian(snes, &saved_jacobian_lag); + SNESSetLagJacobian(snes, 1); + } - } else if (nl_its >= upper_its) { - // Reduce timestep slightly - timestep *= timestep_factor_on_upper_its; + } else { - // Recompute Jacobian + // Consider changing the timestep. + // Note: The preconditioner depends on the timestep, + // so if it is not recalculated the it will be less + // effective. + if ((nl_its <= lower_its) && (timestep < max_timestep) + && (steps_since_snes_failure > 2)) { + // Increase timestep slightly + timestep *= timestep_factor_on_lower_its; + + timestep = std::min(timestep, max_timestep); + + // Note: Setting the SNESJacobianFn to NULL retains + // previously set evaluation function. + // + // The SNES Jacobian is a combination of the RHS Jacobian + // and a factor involving the timestep. + // Depends on equation_form + // -> Probably call SNESSetJacobian(snes, Jfd, Jfd, NULL, fdcoloring); + + if (static_cast(lin_its) / nl_its > 4) { + // Recompute Jacobian (for now) if (saved_jacobian_lag == 0) { SNESGetLagJacobian(snes, &saved_jacobian_lag); SNESSetLagJacobian(snes, 1); } } + + } else if (nl_its >= upper_its) { + // Reduce timestep slightly + timestep *= timestep_factor_on_upper_its; + + // Recompute Jacobian + if (saved_jacobian_lag == 0) { + SNESGetLagJacobian(snes, &saved_jacobian_lag); + SNESSetLagJacobian(snes, 1); + } } } snes_failures = 0; @@ -1132,7 +1129,7 @@ int SNESSolver::run() { if (!matrix_free) { ASSERT2(simtime >= target); - ASSERT2(simtime - dt < target); + ASSERT2(simtime - dt <= target); // Stepped over output timestep => Interpolate // snes_x is the solution at t = simtime // x0 is the solution at t = simtime - dt From 07987acec321ad93506dbc3c3640ec9ae8d3c163 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 11:11:09 +0200 Subject: [PATCH 211/259] Add check for flux conservation --- src/mesh/coordinates.cxx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 8da9857d92..3c72c64b62 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -606,6 +606,28 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // Allow transform to fix things up transform->loadParallelMetrics(this); + + if (Bxy.isFci()) { + BoutReal maxError = 0; + auto BJg = Bxy.asField3DParallel() * J / sqrt(g_22); + for (int p = -mesh->ystart ; p <= mesh->ystart ; p++) { + if (p==0) { + continue; + } + BOUT_FOR(i, BJg.getRegion("RGN_NO_BNDRY")) { + auto local = BJg[i] / BJg.ynext(p)[i.yp(p)]; + maxError = std::max(std::abs(local-1), maxError); + } + } + BoutReal allowedError = (*options)["allowedFluxError"].withDefault(1e-6); + if (maxError < allowedError / 100) { + output_info.write("\tInfo: The maximum flux conservation error is {:e}", maxError); + } else if (maxError < allowedError) { + output_warn.write("\tWarning: The maximum flux conservation error is {:e}", maxError); + } else { + throw BoutException("Error: The maximum flux conservation error is {:e}", maxError); + } + } } Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, From f6b7b9eb7f1303c20257e7fa792662d26ee0afa8 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 11:11:33 +0200 Subject: [PATCH 212/259] Interpolate sheath is at least o2 --- include/bout/parallel_boundary_region.hxx | 6 +++++- src/field/field3d.cxx | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 66aed9316e..6706da1c23 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -107,9 +107,13 @@ public: return ythis(f) * (1 + length()) - yprev(f) * length(); } - inline BoutReal interpolate_sheath_o1(const Field3D& f) const { + inline BoutReal interpolate_sheath_o2(const Field3D& f) const { return ythis(f) * (1 - length()) + ynext(f) * length(); } + inline BoutReal interpolate_sheath_o2(const std::function& f) const { + return ythis(f) * (1 - length()) + ynext(f) * length(); + } + inline BoutReal extrapolate_next_o1(const Field3D& f) const { return ythis(f); } inline BoutReal extrapolate_next_o2(const Field3D& f) const { diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 0857fcfb45..eab5a24dd6 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -529,7 +529,7 @@ void Field3D::setBoundaryTo(const Field3D& f3d, bool copyParallelSlices) { for (auto& region : fieldmesh->getBoundariesPar()) { for (const auto& pnt : *region) { // Interpolate midpoint value in f3d - const BoutReal val = pnt.interpolate_sheath_o1(f3d); + const BoutReal val = pnt.interpolate_sheath_o2(f3d); // Set the same boundary value in this field pnt.dirichlet_o1(*this, val); } From 086d68c7bc139de8c65eb379b0a07a8ff591e20f Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Tue, 21 Oct 2025 09:24:17 +0000 Subject: [PATCH 213/259] Apply clang-format changes --- include/bout/parallel_boundary_region.hxx | 4 ++-- src/mesh/coordinates.cxx | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 6706da1c23..aed0f2b242 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -110,11 +110,11 @@ public: inline BoutReal interpolate_sheath_o2(const Field3D& f) const { return ythis(f) * (1 - length()) + ynext(f) * length(); } - inline BoutReal interpolate_sheath_o2(const std::function& f) const { + inline BoutReal + interpolate_sheath_o2(const std::function& f) const { return ythis(f) * (1 - length()) + ynext(f) * length(); } - inline BoutReal extrapolate_next_o1(const Field3D& f) const { return ythis(f); } inline BoutReal extrapolate_next_o2(const Field3D& f) const { ASSERT3(valid() >= 0); diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 3c72c64b62..1ffbbc7dc6 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -610,20 +610,21 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) if (Bxy.isFci()) { BoutReal maxError = 0; auto BJg = Bxy.asField3DParallel() * J / sqrt(g_22); - for (int p = -mesh->ystart ; p <= mesh->ystart ; p++) { - if (p==0) { - continue; + for (int p = -mesh->ystart; p <= mesh->ystart; p++) { + if (p == 0) { + continue; } BOUT_FOR(i, BJg.getRegion("RGN_NO_BNDRY")) { - auto local = BJg[i] / BJg.ynext(p)[i.yp(p)]; - maxError = std::max(std::abs(local-1), maxError); + auto local = BJg[i] / BJg.ynext(p)[i.yp(p)]; + maxError = std::max(std::abs(local - 1), maxError); } } BoutReal allowedError = (*options)["allowedFluxError"].withDefault(1e-6); if (maxError < allowedError / 100) { output_info.write("\tInfo: The maximum flux conservation error is {:e}", maxError); } else if (maxError < allowedError) { - output_warn.write("\tWarning: The maximum flux conservation error is {:e}", maxError); + output_warn.write("\tWarning: The maximum flux conservation error is {:e}", + maxError); } else { throw BoutException("Error: The maximum flux conservation error is {:e}", maxError); } From 23a79a191211fbb394da7d11650081b0b0e185e2 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 14:00:31 +0200 Subject: [PATCH 214/259] Interpolate sheath is at least o2 --- include/bout/boundary_iterator.hxx | 2 +- manual/sphinx/user_docs/boundary_options.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx index 118036256e..3504e2f967 100644 --- a/include/bout/boundary_iterator.hxx +++ b/include/bout/boundary_iterator.hxx @@ -43,7 +43,7 @@ public: return 2 * f(0, ind()) - f(0, ind().yp(-by).xp(-bx)); } - BoutReal interpolate_sheath_o1(const Field3D& f) const { + BoutReal interpolate_sheath_o2(const Field3D& f) const { return (f[ind()] + ynext(f)) * 0.5; } BoutReal diff --git a/manual/sphinx/user_docs/boundary_options.rst b/manual/sphinx/user_docs/boundary_options.rst index e2d8f28b3f..548a3ae339 100644 --- a/manual/sphinx/user_docs/boundary_options.rst +++ b/manual/sphinx/user_docs/boundary_options.rst @@ -502,7 +502,7 @@ geometries, as flux coordinate independent (FCI) method:: void rhs() { BoutReal totalFlux = 0; yboundary.iter_pnts([&](auto& pnt) { - BoutReal flux = pnt.interpolate_sheath_o1(N) * pnt.interpolate_sheath_o1(V); + BoutReal flux = pnt.interpolate_sheath_o2(N) * pnt.interpolate_sheath_o2(V); }); } @@ -536,7 +536,7 @@ Here is a short summary of some members of ``pnt``, where ``f`` is a : * - ``pnt.yprev(f)`` - Returns the value at the second to last point in the domain, if it is valid. NB: this point may not be valid. - * - ``pnt.interpolate_sheath_o1(f)`` + * - ``pnt.interpolate_sheath_o2(f)`` - Returns the value at the boundary, assuming the bounday value has been set * - ``pnt.extrapolate_sheath_o1(f)`` - Returns the value at the boundary, extrapolating from the bulk, first order From a680c16daca4ceece0a27026011eb59e58a6bfef Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 16:15:42 +0200 Subject: [PATCH 215/259] add asField3DParallel() const --- include/bout/field3d.hxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index e776895870..00944f3f12 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -531,6 +531,7 @@ public: bool allowCalcParallelSlices{true}; inline Field3DParallel asField3DParallel(); + inline const Field3DParallel asField3DParallel() const; protected: /// Array sizes (from fieldmesh). These are valid only if fieldmesh is not null @@ -790,6 +791,9 @@ private: }; Field3DParallel Field3D::asField3DParallel() { return Field3DParallel(*this); } +const Field3DParallel Field3D::asField3DParallel() const { + return Field3DParallel(*this); +} inline Field3D operator+(const Field2D& lhs, const Field3DParallel& rhs) { return lhs + rhs.asField3D(); From ac95a373462e952ac4a50694d5f38ab47af211a8 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 16:16:39 +0200 Subject: [PATCH 216/259] Add limitFreeScale and SheathLimitMode --- include/bout/parallel_boundary_region.hxx | 42 +++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index aed0f2b242..121bd0a1c3 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -16,6 +16,8 @@ * */ +BOUT_ENUM_CLASS(SheathLimitMode, limit_free, exponential_free, linear_free); + namespace bout { namespace parallel_boundary_region { @@ -41,13 +43,49 @@ struct Indices { Indices(Ind3D index, RealPoint&& intersection, BoutReal length, signed char valid, signed char offset, unsigned char abs_offset) : index(index), intersection(intersection), length(length), valid(valid), - offset(offset), abs_offset(abs_offset){}; + offset(offset), abs_offset(abs_offset) {}; }; using IndicesVec = std::vector; using IndicesIter = IndicesVec::iterator; using IndicesIterConst = IndicesVec::const_iterator; +/// Limited free gradient of log of a quantity +/// This ensures that the guard cell values remain positive +/// while also ensuring that the quantity never increases +/// +/// fm fc | fp +/// ^ boundary +/// +/// exp( 2*log(fc) - log(fm) ) +inline BoutReal limitFreeScale(BoutReal fm, BoutReal fc, SheathLimitMode mode) { + if ((fm < fc) && (mode == SheathLimitMode::limit_free)) { + return fc; // Neumann rather than increasing into boundary + } + if (fm < 1e-10) { + return fc; // Low / no density condition + } + + BoutReal fp = 0; + switch (mode) { + case SheathLimitMode::limit_free: + case SheathLimitMode::exponential_free: + fp = SQ(fc) / fm; // Exponential + break; + case SheathLimitMode::linear_free: + fp = 2.0 * fc - fm; // Linear + break; + } + +#if CHECKLEVEL >= 2 + if (!std::isfinite(fp)) { + throw BoutException("SheathBoundary limitFree: {}, {} -> {}", fm, fc, fp); + } +#endif + + return fp; +} + inline BoutReal limitFreeScale(BoutReal fm, BoutReal fc) { if (fm < fc) { return 1; // Neumann rather than increasing into boundary @@ -70,7 +108,7 @@ public: BoundaryRegionParIterBase(IndicesVec& bndry_points, IndicesIter bndry_position, int dir, Mesh* localmesh) : bndry_points(bndry_points), bndry_position(bndry_position), dir(dir), - localmesh(localmesh){}; + localmesh(localmesh) {}; // getter Ind3D ind() const { return bndry_position->index; } From 0b8e27d54525e2bc87ac8579f9bf1ddbf0e6700d Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 16:17:23 +0200 Subject: [PATCH 217/259] Add extrapolate_sheath_free --- include/bout/boundary_iterator.hxx | 8 ++++++++ include/bout/parallel_boundary_region.hxx | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx index 3504e2f967..2f05f0c82e 100644 --- a/include/bout/boundary_iterator.hxx +++ b/include/bout/boundary_iterator.hxx @@ -51,6 +51,14 @@ public: return 0.5 * (3 * f(0, ind()) - f(0, ind().yp(-by).xp(-bx))); } + BoutReal extrapolate_sheath_free(const Field3D& f, SheathLimitMode mode) const { + const BoutReal fac = + bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f), mode); + BoutReal val = ythis(f); + BoutReal next = mode == SheathLimitMode::linear_free ? val + fac : val * fac; + return 0.5 * (val + next); + } + void limitFree(Field3D& f) const { const BoutReal fac = bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f)); diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 121bd0a1c3..b4a0c8cfdb 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -277,6 +277,14 @@ public: } } + BoutReal extrapolate_sheath_free(const Field3D& f, SheathLimitMode mode) const { + const auto fac = valid() > 0 ? limitFreeScale(yprev(f), ythis(f), mode) + : (mode == SheathLimitMode::linear_free ? 0 : 1); + auto val = ythis(f); + BoutReal next = mode == SheathLimitMode::linear_free ? val + fac : val * fac; + return val * length() + next * (1 - length()); + } + void setAll(Field3D& f, const BoutReal val) const { for (int i = -localmesh->ystart; i <= localmesh->ystart; ++i) { f.ynext(i)[ind().yp(i)] = val; From cffe52dfa6336682a625e05ccd1b49ef12594515 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 21 Oct 2025 16:17:34 +0200 Subject: [PATCH 218/259] Add set_free --- include/bout/boundary_iterator.hxx | 17 +++++++++++++++++ include/bout/parallel_boundary_region.hxx | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx index 2f05f0c82e..7c162ab0bd 100644 --- a/include/bout/boundary_iterator.hxx +++ b/include/bout/boundary_iterator.hxx @@ -59,6 +59,23 @@ public: return 0.5 * (val + next); } + void set_free(Field3D& f, SheathLimitMode mode) const { + const BoutReal fac = + bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f), mode); + BoutReal val = ythis(f); + if (mode == SheathLimitMode::linear_free) { + for (int i = 1; i <= localmesh->ystart; ++i) { + val += fac; + f[ind().yp(by * i).xp(bx * i)] = val; + } + } else { + for (int i = 1; i <= localmesh->ystart; ++i) { + val *= fac; + f[ind().yp(by * i).xp(bx * i)] = val; + } + } + } + void limitFree(Field3D& f) const { const BoutReal fac = bout::parallel_boundary_region::limitFreeScale(yprev(f), ythis(f)); diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index b4a0c8cfdb..dcda207d06 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -285,6 +285,23 @@ public: return val * length() + next * (1 - length()); } + void set_free(Field3D& f, SheathLimitMode mode) const { + const auto fac = valid() > 0 ? limitFreeScale(yprev(f), ythis(f), mode) + : (mode == SheathLimitMode::linear_free ? 0 : 1); + auto val = ythis(f); + if (mode == SheathLimitMode::linear_free) { + ITER() { + val += fac; + getAt(f, i) = val; + } + } else { + ITER() { + val *= fac; + getAt(f, i) = val; + } + } + } + void setAll(Field3D& f, const BoutReal val) const { for (int i = -localmesh->ystart; i <= localmesh->ystart; ++i) { f.ynext(i)[ind().yp(i)] = val; From a0de0c76889ea27d706fa119d85a15e73fa12c84 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 22 Oct 2025 11:11:34 +0200 Subject: [PATCH 219/259] add missing interpolate_sheath_o2(func) to FA --- include/bout/boundary_iterator.hxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx index 7c162ab0bd..9e2ff04588 100644 --- a/include/bout/boundary_iterator.hxx +++ b/include/bout/boundary_iterator.hxx @@ -46,6 +46,12 @@ public: BoutReal interpolate_sheath_o2(const Field3D& f) const { return (f[ind()] + ynext(f)) * 0.5; } + + BoutReal + interpolate_sheath_o2(const std::function& f) const { + return (f(0, ind()) + f(0, ind().yp(-by).xp(-bx))) * 0.5; + } + BoutReal extrapolate_sheath_o2(const std::function& f) const { return 0.5 * (3 * f(0, ind()) - f(0, ind().yp(-by).xp(-bx))); From 267d37688af9a30bd5049bc07c645868a42ff9c3 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 22 Oct 2025 11:12:06 +0200 Subject: [PATCH 220/259] add is_lower() to check for which direction the boundary is --- include/bout/boundary_iterator.hxx | 5 +++++ include/bout/parallel_boundary_region.hxx | 2 ++ 2 files changed, 7 insertions(+) diff --git a/include/bout/boundary_iterator.hxx b/include/bout/boundary_iterator.hxx index 9e2ff04588..728c2e1cb0 100644 --- a/include/bout/boundary_iterator.hxx +++ b/include/bout/boundary_iterator.hxx @@ -92,6 +92,11 @@ public: } } + bool is_lower() const { + ASSERT2(bx == 0); + return by == -1; + } + void neumann_o1(Field3D& f, BoutReal grad) const { BoutReal val = ythis(f); for (int i = 1; i <= localmesh->ystart; ++i) { diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index dcda207d06..21b37b4953 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -238,6 +238,8 @@ public: } } + bool is_lower() const { return dir == -1; } + // NB: value needs to be scaled by dy // neumann_o1 is actually o2 if we would use an appropriate one-sided stencil. // But in general we do not, and thus for normal C2 stencils, this is 1st order. From d8c316911bc35b02275f4ec1bf5879b96ab7add5 Mon Sep 17 00:00:00 2001 From: David Bold Date: Thu, 23 Oct 2025 14:31:27 +0200 Subject: [PATCH 221/259] Add Field3DParallel::allocate --- include/bout/field3d.hxx | 1 + src/field/field3d.cxx | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 00944f3f12..0f65fa7fd5 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -785,6 +785,7 @@ public: return *this; } Field3DParallel& operator=(BoutReal); + Field3DParallel& allocate(); private: void ensureFieldAligned(); diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index eab5a24dd6..2fc6726ebc 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -1012,3 +1012,17 @@ void Field3DParallel::ensureFieldAligned() { } } } + +Field3DParallel& Field3DParallel::allocate() { + Field3D::allocate(); + if (isFci()) { + ASSERT2(hasParallelSlices()); + if (fieldmesh != nullptr) { + for (int i = 0; i < fieldmesh->ystart; ++i) { + yup_fields[i].allocate(); + ydown_fields[i].allocate(); + } + } + } + return *this; +} From ffb69befa9ead4050f884f2a991e0c059b95dd8f Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Thu, 23 Oct 2025 12:32:28 +0000 Subject: [PATCH 222/259] Apply clang-format changes --- include/bout/parallel_boundary_region.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bout/parallel_boundary_region.hxx b/include/bout/parallel_boundary_region.hxx index 21b37b4953..b31b6c8395 100644 --- a/include/bout/parallel_boundary_region.hxx +++ b/include/bout/parallel_boundary_region.hxx @@ -43,7 +43,7 @@ struct Indices { Indices(Ind3D index, RealPoint&& intersection, BoutReal length, signed char valid, signed char offset, unsigned char abs_offset) : index(index), intersection(intersection), length(length), valid(valid), - offset(offset), abs_offset(abs_offset) {}; + offset(offset), abs_offset(abs_offset){}; }; using IndicesVec = std::vector; @@ -108,7 +108,7 @@ public: BoundaryRegionParIterBase(IndicesVec& bndry_points, IndicesIter bndry_position, int dir, Mesh* localmesh) : bndry_points(bndry_points), bndry_position(bndry_position), dir(dir), - localmesh(localmesh) {}; + localmesh(localmesh){}; // getter Ind3D ind() const { return bndry_position->index; } From 8e211e2160eb0fc12232552e0e02dd7f584e7fcf Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 23 Oct 2025 17:04:28 +0100 Subject: [PATCH 223/259] Enable non-const iteration over `Options` --- include/bout/options.hxx | 8 ++++++++ src/sys/options/options_netcdf.cxx | 5 +---- tests/unit/sys/test_options.cxx | 11 +++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/bout/options.hxx b/include/bout/options.hxx index 9356326d0e..dbb926838a 100644 --- a/include/bout/options.hxx +++ b/include/bout/options.hxx @@ -205,6 +205,14 @@ public: bout::utils::variant, Matrix, Tensor>; + /// Methods to iterate over `Options` + auto begin() { return std::begin(children); } + auto end() { return std::end(children); } + auto begin() const { return std::begin(children); } + auto end() const { return std::end(children); } + auto cbegin() const { return std::cbegin(children); } + auto cend() const { return std::cend(children); } + /// A tree representation with leaves containing ValueType. /// Used to construct Options from initializer lists. /// diff --git a/src/sys/options/options_netcdf.cxx b/src/sys/options/options_netcdf.cxx index 60dfba2102..94b62f0f02 100644 --- a/src/sys/options/options_netcdf.cxx +++ b/src/sys/options/options_netcdf.cxx @@ -448,10 +448,7 @@ void NcPutAttVisitor::operator()(const std::string& value) { void writeGroup(const Options& options, NcGroup group, const std::string& time_dimension) { - for (const auto& childpair : options.getChildren()) { - const auto& name = childpair.first; - const auto& child = childpair.second; - + for (const auto& [name, child] : options) { if (child.isValue()) { try { auto nctype = bout::utils::visit(NcTypeVisitor(), child.value); diff --git a/tests/unit/sys/test_options.cxx b/tests/unit/sys/test_options.cxx index a9a3bf4af4..67e405953d 100644 --- a/tests/unit/sys/test_options.cxx +++ b/tests/unit/sys/test_options.cxx @@ -1439,3 +1439,14 @@ TEST_F(OptionsTest, BoolCompound) { ASSERT_TRUE(Options("true & !false").as()); ASSERT_TRUE(Options("2 > 1 & 2 < 3").as()); } + +TEST_F(OptionsTest, Iterate) { + Options option{{{"value1", 1}, {"value2", 2}}}; + + for (auto& [name, value] : option) { + value.force(value.as() + 1); + } + + ASSERT_EQ(option["value1"], 2); + ASSERT_EQ(option["value2"], 3); +} From 2792afd57d13dc1c0cddc6b2d3100373ebd08510 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 23 Oct 2025 18:15:05 +0100 Subject: [PATCH 224/259] Add factory for LaplaceXY, LaplaceXY2, LaplaceXY2Hypre --- CMakeLists.txt | 10 +- include/bout/invert/laplacexy.hxx | 231 +- .../impls/hypre/laplacexy-hypre.cxx} | 14 +- .../laplacexy/impls/hypre/laplacexy-hypre.hxx | 57 +- .../laplacexy/impls/petsc/laplacexy-petsc.cxx | 1891 ++++++++++++++++ .../laplacexy/impls/petsc/laplacexy-petsc.hxx | 204 ++ .../impls/petsc2/laplacexy-petsc2.cxx} | 28 +- .../impls/petsc2/laplacexy-petsc2.hxx | 74 +- src/invert/laplacexy/laplacexy.cxx | 1893 +---------------- .../test-laplacexy-fv/test-laplacexy.cxx | 6 +- .../test-laplacexy-short/test-laplacexy.cxx | 25 +- .../test-laplacexy/test-laplacexy.cxx | 6 +- .../test-laplacexy2-hypre/test-laplacexy.cxx | 8 +- 13 files changed, 2258 insertions(+), 2189 deletions(-) rename src/invert/{laplacexy2/laplacexy2_hypre.cxx => laplacexy/impls/hypre/laplacexy-hypre.cxx} (97%) rename include/bout/invert/laplacexy2_hypre.hxx => src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx (70%) create mode 100644 src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx create mode 100644 src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx rename src/invert/{laplacexy2/laplacexy2.cxx => laplacexy/impls/petsc2/laplacexy-petsc2.cxx} (94%) rename include/bout/invert/laplacexy2.hxx => src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx (64%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c49e434e4..cc368a3b32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,11 +235,13 @@ set(BOUT_SOURCES ./src/invert/laplace/impls/hypre3d/hypre3d_laplace.cxx ./src/invert/laplace/impls/hypre3d/hypre3d_laplace.hxx ./src/invert/laplace/invert_laplace.cxx + ./src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx + ./src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx + ./src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx + ./src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx + ./src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx + ./src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx ./src/invert/laplacexy/laplacexy.cxx - ./include/bout/invert/laplacexy2.hxx - ./src/invert/laplacexy2/laplacexy2.cxx - ./include/bout/invert/laplacexy2_hypre.hxx - ./src/invert/laplacexy2/laplacexy2_hypre.cxx ./src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx ./src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx ./src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx diff --git a/include/bout/invert/laplacexy.hxx b/include/bout/invert/laplacexy.hxx index 5a4dd46512..7ec6901cee 100644 --- a/include/bout/invert/laplacexy.hxx +++ b/include/bout/invert/laplacexy.hxx @@ -1,18 +1,18 @@ /************************************************************************** - * Laplacian solver in 2D (X-Y) + * Perpendicular Laplacian inversion in X-Y * - * Equation solved is: + * Equation solved is: * * Div( A * Grad_perp(x) ) + B*x = b * * Intended for use in solving n = 0 component of potential * from inversion of vorticity equation - * + * ************************************************************************** - * Copyright 2015 B.Dudson + * Copyright 2015-2025 BOUT++ Team * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -30,196 +30,69 @@ * **************************************************************************/ -#ifndef BOUT_LAPLACE_XY_H -#define BOUT_LAPLACE_XY_H - -#include "bout/build_defines.hxx" - -#if !BOUT_HAS_PETSC -// If no PETSc - -#warning LaplaceXY requires PETSc. No LaplaceXY available +#ifndef BOUT_LAPLACEXY_H +#define BOUT_LAPLACEXY_H -#include +#include +#include +#include +#include -class Field2D; -class Mesh; -class Options; +class LaplaceXY; class Solver; -/*! - * Create a dummy class so that code will compile - * without PETSc, but will throw an exception if - * LaplaceXY is used. - */ -class LaplaceXY { +class LaplaceXYFactory + : public Factory { public: - LaplaceXY(Mesh* UNUSED(m) = nullptr, Options* UNUSED(opt) = nullptr, - const CELL_LOC UNUSED(loc) = CELL_CENTRE) { - throw BoutException("LaplaceXY requires PETSc. No LaplaceXY available"); + static constexpr auto type_name = "LaplaceXY"; + static constexpr auto section_name = "laplacexy"; + static constexpr auto option_name = "type"; + static constexpr auto default_type = "petsc"; + + ReturnType create(Mesh* mesh = nullptr, Options* options = nullptr, + CELL_LOC loc = CELL_CENTRE) const { + return Factory::create(getType(options), mesh, optionsOrDefaultSection(options), loc); } - void setCoefs(const Field2D& UNUSED(A), const Field2D& UNUSED(B)) {} - const Field2D solve(const Field2D& UNUSED(rhs), const Field2D& UNUSED(x0)) { - throw BoutException("LaplaceXY requires PETSc. No LaplaceXY available"); + ReturnType create(const std::string& type, Options* options) const { + return Factory::create(type, nullptr, options, CELL_CENTRE); } - void savePerformance(Solver&, std::string) { - throw BoutException("LaplaceXY requires PETSc. No LaplaceXY available"); - } -}; -#else // BOUT_HAS_PETSC + static void ensureRegistered(); +}; -#include "bout/solver.hxx" -#include "bout/utils.hxx" -#include -#include -#include +template +using RegisterLaplaceXY = LaplaceXYFactory::RegisterInFactory; -class Options; -class Solver; +using RegisterUnavailableLaplaceXY = LaplaceXYFactory::RegisterUnavailableInFactory; class LaplaceXY { public: - /*! - * Constructor - */ - LaplaceXY(Mesh* m = nullptr, Options* opt = nullptr, const CELL_LOC loc = CELL_CENTRE); - /*! - * Destructor - */ - ~LaplaceXY(); - - /*! - * Set coefficients (A, B) in equation: - * Div( A * Grad_perp(x) ) + B*x = b - */ - void setCoefs(const Field2D& A, const Field2D& B); - - /*! - * Solve Laplacian in X-Y - * - * Inputs - * ====== - * - * rhs - The field to be inverted. This must be allocated - * and contain valid data. - * x0 - Initial guess at the solution. If this is unallocated - * then an initial guess of zero will be used. - * - * Returns - * ======= - * - * The solution as a Field2D. On failure an exception will be raised - * - */ - const Field2D solve(const Field2D& rhs, const Field2D& x0); - - /*! - * Preconditioner function - * This is called by PETSc via a static function. - * and should not be called by external users - */ - int precon(Vec x, Vec y); - - /*! - * If this method is called, save some performance monitoring information - */ - void savePerformance(Solver& solver, const std::string& name = ""); + LaplaceXY(Mesh* m = nullptr, [[maybe_unused]] Options* options = nullptr, + const CELL_LOC loc = CELL_CENTRE) + : localmesh(m == nullptr ? bout::globals::mesh : m), location(loc) {} + LaplaceXY(const LaplaceXY&) = default; + LaplaceXY(LaplaceXY&&) = delete; + LaplaceXY& operator=(const LaplaceXY&) = default; + LaplaceXY& operator=(LaplaceXY&&) = delete; + virtual ~LaplaceXY() = default; + + virtual void setCoefs(const Field2D& A, const Field2D& B) = 0; + + virtual Field2D solve(const Field2D& b, const Field2D& x0) = 0; + + static std::unique_ptr create(Mesh* m = nullptr, Options* opt = nullptr, + CELL_LOC loc = CELL_CENTRE) { + return LaplaceXYFactory::getInstance().create(m, opt, loc); + } +protected: + static const int INVERT_DC_GRAD = 1; + static const int INVERT_AC_GRAD = 2; // Use zero neumann (NOTE: AC is a misnomer) + static const int INVERT_SET = 16; // Set boundary to x0 value + static const int INVERT_RHS = 32; // Set boundary to b value private: - PetscLib lib; ///< Requires PETSc library - Mat MatA; ///< Matrix to be inverted - Vec xs, bs; ///< Solution and RHS vectors - KSP ksp; ///< Krylov Subspace solver - PC pc; ///< Preconditioner - Mesh* localmesh; ///< The mesh this operates on, provides metrics and communication - - /// default prefix for writing performance logging variables - std::string default_prefix; - - // Preconditioner - int xstart, xend; - int nloc, nsys; - Matrix acoef, bcoef, ccoef, xvals, bvals; - std::unique_ptr> cr; ///< Tridiagonal solver - - // Use finite volume or finite difference discretization - bool finite_volume{true}; - - // Y derivatives - bool include_y_derivs; // Include Y derivative terms? - - // Boundary conditions - bool x_inner_dirichlet; // Dirichlet on inner X boundary? - bool x_outer_dirichlet; // Dirichlet on outer X boundary? - std::string y_bndry{"neumann"}; // Boundary condition for y-boundary - - // Location of the rhs and solution CELL_LOC location; - - /*! - * Number of grid points on this processor - */ - int localSize(); - - /*! - * Return the communicator for XY - */ - MPI_Comm communicator(); - - /*! - * Return the global index of a local (x,y) coordinate - * including guard cells. - * Boundary cells have a global index of -1 - * - * To do this, a Field2D (indexXY) is used to store - * the index as a floating point number which is then rounded - * to an integer. Guard cells are filled by communication - * so no additional logic is needed in Mesh. - */ - int globalIndex(int x, int y); - Field2D indexXY; ///< Global index (integer stored as BoutReal) - - // Save performance information? - bool save_performance = false; - - // Running average of number of iterations taken for solve in each output timestep - BoutReal average_iterations = 0.; - - // Variable to store the final result of average_iterations, since output is - // written after all other monitors have been called, and average_iterations - // must be reset in the monitor - BoutReal output_average_iterations = 0.; - - // Running total of number of calls to the solver in each output timestep - int n_calls = 0; - - // Utility methods - void setPreallocationFiniteVolume(PetscInt* d_nnz, PetscInt* o_nnz); - void setPreallocationFiniteDifference(PetscInt* d_nnz, PetscInt* o_nnz); - void setMatrixElementsFiniteVolume(const Field2D& A, const Field2D& B); - void setMatrixElementsFiniteDifference(const Field2D& A, const Field2D& B); - void solveFiniteVolume(const Field2D& x0); - void solveFiniteDifference(const Field2D& x0); - - // Monitor class used to reset performance-monitoring variables for a new - // output timestep - friend class LaplaceXYMonitor; - class LaplaceXYMonitor : public Monitor { - public: - LaplaceXYMonitor(LaplaceXY& owner) : laplacexy(owner) {} - - int call(Solver* /*solver*/, BoutReal /*time*/, int /*iter*/, int /*nout*/) override; - void outputVars(Options& output_options, const std::string& time_dimension) override; - - private: - // LaplaceXY object that this monitor belongs to - LaplaceXY& laplacexy; - }; - - LaplaceXYMonitor monitor; }; -#endif // BOUT_HAS_PETSC -#endif // BOUT_LAPLACE_XY_H +#endif // BOUT_LAPLACEXY_H diff --git a/src/invert/laplacexy2/laplacexy2_hypre.cxx b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx similarity index 97% rename from src/invert/laplacexy2/laplacexy2_hypre.cxx rename to src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx index a5028169f8..950fcc4f8e 100644 --- a/src/invert/laplacexy2/laplacexy2_hypre.cxx +++ b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx @@ -1,7 +1,9 @@ -#include +#include "bout/build_defines.hxx" #if BOUT_HAS_HYPRE +#include "laplacexy-hypre.hxx" + #include "bout/assert.hxx" #include "bout/boutcomm.hxx" #include "bout/globals.hxx" @@ -9,11 +11,11 @@ #include "bout/output.hxx" #include "bout/sys/timer.hxx" -#include - #if BOUT_HAS_CUDA && defined(__CUDACC__) -#define gpuErrchk(ans) \ - { gpuAssert((ans), __FILE__, __LINE__); } +#define gpuErrchk(ans) \ + { \ + gpuAssert((ans), __FILE__, __LINE__); \ + } inline void gpuAssert(cudaError_t code, const char* file, int line, bool abort = true) { if (code != cudaSuccess) { fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); @@ -226,7 +228,7 @@ void LaplaceXY2Hypre::setCoefs(const Field2D& A, const Field2D& B) { } } -Field2D LaplaceXY2Hypre::solve(Field2D& rhs, Field2D& x0) { +Field2D LaplaceXY2Hypre::solve(const Field2D& rhs, const Field2D& x0) { Timer timer("invert"); ASSERT1(rhs.getMesh() == localmesh); diff --git a/include/bout/invert/laplacexy2_hypre.hxx b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx similarity index 70% rename from include/bout/invert/laplacexy2_hypre.hxx rename to src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx index 1df0988d06..3950725a89 100644 --- a/include/bout/invert/laplacexy2_hypre.hxx +++ b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx @@ -33,51 +33,36 @@ #ifndef LAPLACE_XY2_HYPRE_H #define LAPLACE_XY2_HYPRE_H -#include - -#if not BOUT_HAS_HYPRE -// If no Hypre - -#include "bout/globalindexer.hxx" -#include -#include -#include - -/*! - * Create a dummy class so that code will compile - * without Hypre, but will throw an exception if - * LaplaceXY is used. - */ -class LaplaceXY2Hypre { -public: - LaplaceXY2Hypre(Mesh* UNUSED(m) = nullptr, Options* UNUSED(opt) = nullptr, - const CELL_LOC UNUSED(loc) = CELL_CENTRE) { - throw BoutException("LaplaceXY requires Hypre. No LaplaceXY available"); - } - void setCoefs(const Field2D& UNUSED(A), const Field2D& UNUSED(B)) {} - Field2D solve(const Field2D& UNUSED(rhs), const Field2D& UNUSED(x0)) { - throw BoutException("LaplaceXY requires Hypre. No LaplaceXY available"); - } -}; +#include "bout/build_defines.hxx" +#include "bout/invert/laplacexy.hxx" + +#if !BOUT_HAS_PETSC -#else // BOUT_HAS_HYPRE +namespace { +RegisterUnavailableLaplaceXY + registerlaplacexyhypre("hypre", "BOUT++ was not configured with HYPRE"); +} + +#else // BOUT_HAS_PETSC class Mesh; -#include "bout/utils.hxx" #include -class LaplaceXY2Hypre { +class LaplaceXY2Hypre : public LaplaceXY { public: - LaplaceXY2Hypre(Mesh* m = nullptr, Options* opt = nullptr, - const CELL_LOC loc = CELL_CENTRE); - ~LaplaceXY2Hypre() = default; + LaplaceXY2Hypre(Mesh* m = nullptr, Options* opt = nullptr, CELL_LOC loc = CELL_CENTRE); + LaplaceXY2Hypre(const LaplaceXY2Hypre&) = delete; + LaplaceXY2Hypre(LaplaceXY2Hypre&&) = delete; + LaplaceXY2Hypre& operator=(const LaplaceXY2Hypre&) = delete; + LaplaceXY2Hypre& operator=(LaplaceXY2Hypre&&) = delete; + ~LaplaceXY2Hypre() override = default; /*! * Set coefficients (A, B) in equation: * Div( A * Grad_perp(x) ) + B*x = b */ - void setCoefs(const Field2D& A, const Field2D& B); + void setCoefs(const Field2D& A, const Field2D& B) override; /*! * Solve Laplacian in X-Y @@ -96,7 +81,7 @@ public: * The solution as a Field2D. On failure an exception will be raised * */ - Field2D solve(Field2D& rhs, Field2D& x0); + Field2D solve(const Field2D& rhs, const Field2D& x0) override; /*! * Preconditioner function @@ -131,5 +116,9 @@ private: MPI_Comm communicator(); }; +namespace { +const inline RegisterLaplaceXY registerlaplacexyhypre{"hypre"}; +} + #endif // BOUT_HAS_HYPRE #endif // LAPLACE_XY_HYPRE_H diff --git a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx new file mode 100644 index 0000000000..e80a2ca640 --- /dev/null +++ b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx @@ -0,0 +1,1891 @@ +#include "bout/build_defines.hxx" + +#if BOUT_HAS_PETSC + +#include "laplacexy-petsc.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace { +PetscErrorCode laplacePCapply(PC pc, Vec x, Vec y) { + // Get the context + LaplaceXYpetsc* s = nullptr; + const auto ierr = PCShellGetContext(pc, reinterpret_cast(&s)); + CHKERRQ(ierr); + + PetscFunctionReturn(s->precon(x, y)); +} +} // namespace + +LaplaceXYpetsc::LaplaceXYpetsc(Mesh* m, Options* opt, const CELL_LOC loc) + : lib(opt == nullptr ? &(Options::root()["laplacexy"]) : opt), + localmesh(m == nullptr ? bout::globals::mesh : m), location(loc), monitor(*this) { + Timer timer("invert"); + + if (opt == nullptr) { + // If no options supplied, use default + opt = &(Options::root()["laplacexy"]); + } + + finite_volume = + (*opt)["finite_volume"] + .doc("Use finite volume rather than finite difference discretisation.") + .withDefault(true); + + /////////////////////////////////////////////////// + // Boundary condititions options + if (localmesh->periodicY(localmesh->xstart)) { + // Periodic in Y, so in the core + x_inner_dirichlet = (*opt)["core_bndry_dirichlet"].withDefault(false); + } else { + // Non-periodic, so in the PF region + x_inner_dirichlet = (*opt)["pf_bndry_dirichlet"].withDefault(true); + } + if ((*opt)["y_bndry_dirichlet"].isSet()) { + throw BoutException("y_bndry_dirichlet has been deprecated. Use y_bndry=dirichlet " + "instead."); + } + y_bndry = (*opt)["y_bndry"].withDefault("neumann"); + + // Check value of y_bndry is a supported option + if (not(y_bndry == "dirichlet" or y_bndry == "neumann" or y_bndry == "free_o3")) { + + throw BoutException("Unrecognized option '{}' for laplacexy:ybndry", y_bndry); + } + + if (not finite_volume) { + // Check we can use corner cells + if (not localmesh->include_corner_cells) { + throw BoutException( + "Finite difference form of LaplaceXYpetsc allows non-orthogonal x- and " + "y-directions, so requires mesh:include_corner_cells=true."); + } + } + + // Use name of options section as the default prefix for performance logging variables + default_prefix = opt->name(); + + // Get MPI communicator + auto* comm = BoutComm::get(); + + // Local size + const int localN = localSize(); + + // Create Vectors + VecCreate(comm, &xs); + VecSetSizes(xs, localN, PETSC_DETERMINE); + VecSetFromOptions(xs); + VecDuplicate(xs, &bs); + + // Set size of Matrix on each processor to localN x localN + MatCreate(comm, &MatA); + MatSetSizes(MatA, localN, localN, PETSC_DETERMINE, PETSC_DETERMINE); + MatSetFromOptions(MatA); + + ////////////////////////////////////////////////// + // Specify local indices. This creates a mapping + // from local indices to index, using a Field2D object + + indexXY = -1; // Set all points to -1, indicating out of domain + + int ind = 0; + + // Y boundaries + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + indexXY(it.ind, localmesh->ystart - 1) = ind++; + } + if ((not finite_volume) and localmesh->hasBndryLowerY()) { + // Corner boundary cells + if (localmesh->firstX()) { + indexXY(localmesh->xstart - 1, localmesh->ystart - 1) = ind++; + } + if (localmesh->lastX()) { + indexXY(localmesh->xend + 1, localmesh->ystart - 1) = ind++; + } + } + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + indexXY(it.ind, localmesh->yend + 1) = ind++; + } + if ((not finite_volume) and localmesh->hasBndryUpperY()) { + // Corner boundary cells + if (localmesh->firstX()) { + indexXY(localmesh->xstart - 1, localmesh->yend + 1) = ind++; + } + if (localmesh->lastX()) { + indexXY(localmesh->xend + 1, localmesh->yend + 1) = ind++; + } + } + + xstart = localmesh->xstart; + if (localmesh->firstX()) { + xstart -= 1; // Include X guard cells + } + xend = localmesh->xend; + if (localmesh->lastX()) { + xend += 1; + } + for (int x = xstart; x <= xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + indexXY(x, y) = ind++; + } + } + + ASSERT1(ind == localN); // Reached end of range + + ////////////////////////////////////////////////// + // Allocate storage for preconditioner + + nloc = xend - xstart + 1; // Number of X points on this processor + nsys = localmesh->yend - localmesh->ystart + 1; // Number of separate Y slices + + acoef.reallocate(nsys, nloc); + bcoef.reallocate(nsys, nloc); + ccoef.reallocate(nsys, nloc); + xvals.reallocate(nsys, nloc); + bvals.reallocate(nsys, nloc); + + // Create a cyclic reduction object + cr = bout::utils::make_unique>(localmesh->getXcomm(), nloc); + + ////////////////////////////////////////////////// + // Pre-allocate PETSc storage + + PetscInt* d_nnz = nullptr; + PetscInt* o_nnz = nullptr; + PetscMalloc((localN) * sizeof(PetscInt), &d_nnz); + PetscMalloc((localN) * sizeof(PetscInt), &o_nnz); + + if (finite_volume) { + setPreallocationFiniteVolume(d_nnz, o_nnz); + } else { + setPreallocationFiniteDifference(d_nnz, o_nnz); + } + // Pre-allocate + MatMPIAIJSetPreallocation(MatA, 0, d_nnz, 0, o_nnz); + MatSetUp(MatA); + + PetscFree(d_nnz); + PetscFree(o_nnz); + + // Determine which row/columns of the matrix are locally owned + int Istart = 0; + int Iend = 0; + MatGetOwnershipRange(MatA, &Istart, &Iend); + + // Convert indexXY from local index to global index + indexXY += Istart; + + // Now communicate to fill guard cells + // Note, this includes corner cells if necessary + localmesh->communicate(indexXY); + + ////////////////////////////////////////////////// + // Set up KSP + + // Declare KSP Context + KSPCreate(comm, &ksp); + + // Configure Linear Solver + + const bool direct = (*opt)["direct"].doc("Use a direct LU solver").withDefault(false); + + if (direct) { + KSPGetPC(ksp, &pc); + PCSetType(pc, PCLU); +#if PETSC_VERSION_GE(3, 9, 0) + PCFactorSetMatSolverType(pc, "mumps"); +#else + PCFactorSetMatSolverPackage(pc, "mumps"); +#endif + } else { + + // Convergence Parameters. Solution is considered converged if |r_k| < max( rtol * |b| , atol ) + // where r_k = b - Ax_k. The solution is considered diverged if |r_k| > dtol * |b|. + + const BoutReal rtol = (*opt)["rtol"].doc("Relative tolerance").withDefault(1e-5); + const BoutReal atol = + (*opt)["atol"] + .doc("Absolute tolerance. The solution is considered converged if |Ax-b| " + "< max( rtol * |b| , atol )") + .withDefault(1e-10); + const BoutReal dtol = + (*opt)["dtol"] + .doc("The solution is considered diverged if |Ax-b| > dtol * |b|") + .withDefault(1e3); + const int maxits = (*opt)["maxits"].doc("Maximum iterations").withDefault(100000); + + // Get KSP Solver Type + const std::string ksptype = + (*opt)["ksptype"].doc("KSP solver type").withDefault("gmres"); + + // Get PC type + const std::string pctype = + (*opt)["pctype"].doc("Preconditioner type").withDefault("none"); + + KSPSetType(ksp, ksptype.c_str()); + KSPSetTolerances(ksp, rtol, atol, dtol, maxits); + + KSPSetInitialGuessNonzero(ksp, static_cast(true)); + + KSPGetPC(ksp, &pc); + PCSetType(pc, pctype.c_str()); + + if (pctype == "shell") { + // Using tridiagonal solver as preconditioner + PCShellSetApply(pc, laplacePCapply); + PCShellSetContext(pc, this); + + const bool rightprec = + (*opt)["rightprec"].doc("Use right preconditioning?").withDefault(true); + if (rightprec) { + KSPSetPCSide(ksp, PC_RIGHT); // Right preconditioning + } else { + KSPSetPCSide(ksp, PC_LEFT); // Left preconditioning + } + } + } + + lib.setOptionsFromInputFile(ksp); + + /////////////////////////////////////////////////// + // Including Y derivatives? + + include_y_derivs = (*opt)["include_y_derivs"] + .doc("Include Y derivatives in operator to invert?") + .withDefault(true); + + /////////////////////////////////////////////////// + // Set the default coefficients + Field2D one(1., localmesh); + Field2D zero(0., localmesh); + one.setLocation(location); + zero.setLocation(location); + setCoefs(one, zero); +} + +void LaplaceXYpetsc::setPreallocationFiniteVolume(PetscInt* d_nnz, PetscInt* o_nnz) { + const int localN = localSize(); + + // This discretisation uses a 5-point stencil + for (int i = 0; i < localN; i++) { + // Non-zero elements on this processor + d_nnz[i] = 5; // Star pattern in 2D + // Non-zero elements on neighboring processor + o_nnz[i] = 0; + } + + // X boundaries + if (localmesh->firstX()) { + // Lower X boundary + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xstart - 1, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + + d_nnz[localIndex] = 2; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + } else { + // On another processor + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xstart, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] -= 1; + o_nnz[localIndex] += 1; + } + } + if (localmesh->lastX()) { + // Upper X boundary + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xend + 1, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 2; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + } else { + // On another processor + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xend, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] -= 1; + o_nnz[localIndex] += 1; + } + } + // Y boundaries + + for (int x = localmesh->xstart; x <= localmesh->xend; x++) { + // Default to no boundary + // NOTE: This assumes that communications in Y are to other + // processors. If Y is communicated with this processor (e.g. NYPE=1) + // then this will result in PETSc warnings about out of range allocations + { + const int localIndex = globalIndex(x, localmesh->ystart); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + // d_nnz[localIndex] -= 1; // Note: Slightly inefficient + o_nnz[localIndex] += 1; + } + { + const int localIndex = globalIndex(x, localmesh->yend); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + // d_nnz[localIndex] -= 1; // Note: Slightly inefficient + o_nnz[localIndex] += 1; + } + } + + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + { + const int localIndex = globalIndex(it.ind, localmesh->ystart - 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 2; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + { + const int localIndex = globalIndex(it.ind, localmesh->ystart); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] += 1; + o_nnz[localIndex] -= 1; + } + } + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + { + const int localIndex = globalIndex(it.ind, localmesh->yend + 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 2; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + { + const int localIndex = globalIndex(it.ind, localmesh->yend); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] += 1; + o_nnz[localIndex] -= 1; + } + } +} + +void LaplaceXYpetsc::setPreallocationFiniteDifference(PetscInt* d_nnz, PetscInt* o_nnz) { + const int localN = localSize(); + + // This discretisation uses a 9-point stencil + for (int i = 0; i < localN; i++) { + // Non-zero elements on this processor + d_nnz[i] = 9; // Square pattern in 2D + // Non-zero elements on neighboring processor + o_nnz[i] = 0; + } + + // X boundaries + if (localmesh->firstX()) { + // Lower X boundary + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xstart - 1, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + + d_nnz[localIndex] = 2; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + } else { + // On another processor + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xstart, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] -= 3; + o_nnz[localIndex] += 3; + } + } + if (localmesh->lastX()) { + // Upper X boundary + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xend + 1, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 2; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + } else { + // On another processor + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int localIndex = globalIndex(localmesh->xend, y); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] -= 3; + o_nnz[localIndex] += 3; + } + } + // Y boundaries + const int y_bndry_stencil_size = (y_bndry == "free_o3") ? 4 : 2; + + for (int x = localmesh->xstart; x <= localmesh->xend; x++) { + // Default to no boundary + // NOTE: This assumes that communications in Y are to other + // processors. If Y is communicated with this processor (e.g. NYPE=1) + // then this will result in PETSc warnings about out of range allocations + { + const int localIndex = globalIndex(x, localmesh->ystart); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + // d_nnz[localIndex] -= 3; // Note: Slightly inefficient + o_nnz[localIndex] += 3; + } + { + const int localIndex = globalIndex(x, localmesh->yend); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + // d_nnz[localIndex] -= 3; // Note: Slightly inefficient + o_nnz[localIndex] += 3; + } + } + + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, they are handled specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + { + const int localIndex = globalIndex(it.ind, localmesh->ystart - 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = y_bndry_stencil_size; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + { + const int localIndex = globalIndex(it.ind, localmesh->ystart); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + //d_nnz[localIndex] += 3; + o_nnz[localIndex] -= 3; + } + } + if (localmesh->hasBndryLowerY()) { + if (y_bndry == "dirichlet") { + // special handling for the corners, since we use a free_o3 y-boundary + // condition just in the corners when y_bndry=="dirichlet" + if (localmesh->firstX()) { + const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 4; + } + if (localmesh->lastX()) { + const int localIndex = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 4; + } + } else { + if (localmesh->firstX()) { + const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = y_bndry_stencil_size; + } + if (localmesh->lastX()) { + const int localIndex = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = y_bndry_stencil_size; + } + } + } + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, they are handled specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + { + const int localIndex = globalIndex(it.ind, localmesh->yend + 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = y_bndry_stencil_size; // Diagonal sub-matrix + o_nnz[localIndex] = 0; // Off-diagonal sub-matrix + } + { + const int localIndex = globalIndex(it.ind, localmesh->yend); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + //d_nnz[localIndex] += 3; + o_nnz[localIndex] -= 3; + } + } + if (localmesh->hasBndryUpperY()) { + if (y_bndry == "dirichlet") { + // special handling for the corners, since we use a free_o3 y-boundary + // condition just in the corners when y_bndry=="dirichlet" + if (localmesh->firstX()) { + const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 4; + } + if (localmesh->lastX()) { + const int localIndex = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = 4; + } + } else { + if (localmesh->firstX()) { + const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = y_bndry_stencil_size; + } + if (localmesh->lastX()) { + const int localIndex = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + ASSERT1((localIndex >= 0) && (localIndex < localN)); + d_nnz[localIndex] = y_bndry_stencil_size; + } + } + } +} + +void LaplaceXYpetsc::setCoefs(const Field2D& A, const Field2D& B) { + Timer timer("invert"); + + ASSERT1(A.getMesh() == localmesh); + ASSERT1(B.getMesh() == localmesh); + ASSERT1(A.getLocation() == location); + ASSERT1(B.getLocation() == location); + + if (finite_volume) { + setMatrixElementsFiniteVolume(A, B); + } else { + setMatrixElementsFiniteDifference(A, B); + } + + // X boundaries + if (localmesh->firstX()) { + if (x_inner_dirichlet) { + + // Dirichlet on inner X boundary + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int row = globalIndex(localmesh->xstart - 1, y); + PetscScalar val = 0.5; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + int col = globalIndex(localmesh->xstart, y); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + // Preconditioner + bcoef(y - localmesh->ystart, 0) = 0.5; + ccoef(y - localmesh->ystart, 0) = 0.5; + } + + } else { + + // Neumann on inner X boundary + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int row = globalIndex(localmesh->xstart - 1, y); + PetscScalar val = 1.0; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + int col = globalIndex(localmesh->xstart, y); + val = -1.0; + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + // Preconditioner + bcoef(y - localmesh->ystart, 0) = 1.0; + ccoef(y - localmesh->ystart, 0) = -1.0; + } + } + } + if (localmesh->lastX()) { + // Dirichlet on outer X boundary + + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int row = globalIndex(localmesh->xend + 1, y); + PetscScalar val = 0.5; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + int col = globalIndex(localmesh->xend, y); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + // Preconditioner + acoef(y - localmesh->ystart, localmesh->xend + 1 - xstart) = 0.5; + bcoef(y - localmesh->ystart, localmesh->xend + 1 - xstart) = 0.5; + } + } + + if (y_bndry == "dirichlet") { + // Dirichlet on Y boundaries + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int row = globalIndex(it.ind, localmesh->ystart - 1); + PetscScalar val = 0.5; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + int col = globalIndex(it.ind, localmesh->ystart); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int row = globalIndex(it.ind, localmesh->yend + 1); + PetscScalar val = 0.5; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + int col = globalIndex(it.ind, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } + } else if (y_bndry == "neumann") { + // Neumann on Y boundaries + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int row = globalIndex(it.ind, localmesh->ystart - 1); + PetscScalar val = 1.0; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -1.0; + int col = globalIndex(it.ind, localmesh->ystart); + + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int row = globalIndex(it.ind, localmesh->yend + 1); + PetscScalar val = 1.0; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -1.0; + int col = globalIndex(it.ind, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } + } else if (y_bndry == "free_o3") { + // 'free_o3' extrapolating boundary condition on Y boundaries + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int row = globalIndex(it.ind, localmesh->ystart - 1); + PetscScalar val = 1.0; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -3.0; + int col = globalIndex(it.ind, localmesh->ystart); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = 3.0; + col = globalIndex(it.ind, localmesh->ystart + 1); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = -1.0; + col = globalIndex(it.ind, localmesh->ystart + 2); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int row = globalIndex(it.ind, localmesh->yend + 1); + PetscScalar val = 1.0; + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -3.0; + int col = globalIndex(it.ind, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = 3.0; + col = globalIndex(it.ind, localmesh->yend - 1); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = -1.0; + col = globalIndex(it.ind, localmesh->yend - 2); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } + } else { + throw BoutException("Unsupported option for y_bndry"); + } + + if (not finite_volume) { + // Handle corner boundary cells in case we need to include D2DXDY + // Apply the y-boundary-condition to the cells in the x-boundary - this is an + // arbitrary choice, cf. connections around the X-point + + if (localmesh->hasBndryLowerY()) { + if (localmesh->firstX()) { + if (y_bndry == "neumann") { + // Neumann y-bc + // f(xs-1,ys-1) = f(xs-1,ys) + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -1.0; + int col = globalIndex(localmesh->xstart - 1, localmesh->ystart); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { + // 'free_o3' extrapolating boundary condition on Y boundaries + // f(xs-1,ys-1) = 3*f(xs-1,ys) - 3*f(xs-1,ys+1) + f(xs-1,ys+2) + // + // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know + // what value to pass for the corner + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -3.0; + int col = globalIndex(localmesh->xstart - 1, localmesh->ystart); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = 3.0; + col = globalIndex(localmesh->xstart - 1, localmesh->ystart + 1); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = -1.0; + col = globalIndex(localmesh->xstart - 1, localmesh->ystart + 2); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else { + throw BoutException("Unsupported option for y_bndry"); + } + } + if (localmesh->lastX()) { + if (y_bndry == "neumann") { + // Neumann y-bc + // f(xe+1,ys-1) = f(xe+1,ys) + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -1.0; + int col = globalIndex(localmesh->xend + 1, localmesh->ystart); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { + // 'free_o3' extrapolating boundary condition on Y boundaries + // f(xe+1,ys-1) = 3*f(xe+1,ys) - 3*f(xe+1,ys+1) + f(xe+1,ys+2) + // + // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know + // what value to pass for the corner + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -3.0; + int col = globalIndex(localmesh->xend + 1, localmesh->ystart); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = 3.0; + col = globalIndex(localmesh->xend + 1, localmesh->ystart + 1); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = -1.0; + col = globalIndex(localmesh->xend + 1, localmesh->ystart + 2); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else { + throw BoutException("Unsupported option for y_bndry"); + } + } + } + if (localmesh->hasBndryUpperY()) { + if (localmesh->firstX()) { + if (y_bndry == "neumann") { + // Neumann y-bc + // f(xs-1,ys-1) = f(xs-1,ys) + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -1.0; + int col = globalIndex(localmesh->xstart - 1, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { + // 'free_o3' extrapolating boundary condition on Y boundaries + // f(xs-1,ys-1) = 3*f(xs-1,ys) - 3*f(xs-1,ys+1) + f(xs-1,ys+2) + // + // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know + // what value to pass for the corner + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -3.0; + int col = globalIndex(localmesh->xstart - 1, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = 3.0; + col = globalIndex(localmesh->xstart - 1, localmesh->yend - 1); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = -1.0; + col = globalIndex(localmesh->xstart - 1, localmesh->yend - 2); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else { + throw BoutException("Unsupported option for y_bndry"); + } + } + if (localmesh->lastX()) { + if (y_bndry == "neumann") { + // Neumann y-bc + // f(xe+1,ys-1) = f(xe+1,ys) + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -1.0; + int col = globalIndex(localmesh->xend + 1, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { + // 'free_o3' extrapolating boundary condition on Y boundaries + // f(xe+1,ys-1) = 3*f(xe+1,ys) - 3*f(xe+1,ys+1) + f(xe+1,ys+2) + // + // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know + // what value to pass for the corner + PetscScalar val = 1.0; + int row = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); + + val = -3.0; + int col = globalIndex(localmesh->xend + 1, localmesh->yend); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = 3.0; + col = globalIndex(localmesh->xend + 1, localmesh->yend - 1); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + + val = -1.0; + col = globalIndex(localmesh->xend + 1, localmesh->yend - 2); + MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); + } else { + throw BoutException("Unsupported option for y_bndry"); + } + } + } + } + + // Assemble Matrix + MatAssemblyBegin(MatA, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(MatA, MAT_FINAL_ASSEMBLY); + + // Set the operator +#if PETSC_VERSION_GE(3, 5, 0) + KSPSetOperators(ksp, MatA, MatA); +#else + KSPSetOperators(ksp, MatA, MatA, DIFFERENT_NONZERO_PATTERN); +#endif + + // Set coefficients for preconditioner + cr->setCoefs(acoef, bcoef, ccoef); +} + +void LaplaceXYpetsc::setMatrixElementsFiniteVolume(const Field2D& A, const Field2D& B) { + ////////////////////////////////////////////////// + // Set Matrix elements + // + // (1/J) d/dx ( J * g11 d/dx ) + (1/J) d/dy ( J * g22 d/dy ) + + auto coords = localmesh->getCoordinates(location); + const Field2D J_DC = DC(coords->J); + const Field2D g11_DC = DC(coords->g11); + const Field2D dx_DC = DC(coords->dx); + const Field2D dy_DC = DC(coords->dy); + const Field2D g_22_DC = DC(coords->g_22); + const Field2D g_23_DC = DC(coords->g_23); + const Field2D g23_DC = DC(coords->g23); + + for (int x = localmesh->xstart; x <= localmesh->xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + // stencil entries + PetscScalar c, xm, xp, ym, yp; + + // XX component + + // Metrics on x+1/2 boundary + BoutReal J = 0.5 * (J_DC(x, y) + J_DC(x + 1, y)); + BoutReal g11 = 0.5 * (g11_DC(x, y) + g11_DC(x + 1, y)); + BoutReal dx = 0.5 * (dx_DC(x, y) + dx_DC(x + 1, y)); + BoutReal Acoef = 0.5 * (A(x, y) + A(x + 1, y)); + + BoutReal val = Acoef * J * g11 / (J_DC(x, y) * dx * dx_DC(x, y)); + xp = val; + c = -val; + + // Metrics on x-1/2 boundary + J = 0.5 * (J_DC(x, y) + J_DC(x - 1, y)); + g11 = 0.5 * (g11_DC(x, y) + g11_DC(x - 1, y)); + dx = 0.5 * (dx_DC(x, y) + dx_DC(x - 1, y)); + Acoef = 0.5 * (A(x, y) + A(x - 1, y)); + + val = Acoef * J * g11 / (J_DC(x, y) * dx * dx_DC(x, y)); + xm = val; + c -= val; + + c += B(x, y); + + // Put values into the preconditioner, X derivatives only + acoef(y - localmesh->ystart, x - xstart) = xm; + bcoef(y - localmesh->ystart, x - xstart) = c; + ccoef(y - localmesh->ystart, x - xstart) = xp; + + if (include_y_derivs) { + // YY component + // Metrics at y+1/2 + J = 0.5 * (J_DC(x, y) + J_DC(x, y + 1)); + BoutReal g_22 = 0.5 * (g_22_DC(x, y) + g_22_DC(x, y + 1)); + BoutReal g23 = 0.5 * (g23_DC(x, y) + g23_DC(x, y + 1)); + BoutReal g_23 = 0.5 * (g_23_DC(x, y) + g_23_DC(x, y + 1)); + BoutReal dy = 0.5 * (dy_DC(x, y) + dy_DC(x, y + 1)); + Acoef = 0.5 * (A(x, y + 1) + A(x, y)); + + val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x, y) * dy * dy_DC(x, y)); + yp = val; + c -= val; + + // Metrics at y-1/2 + J = 0.5 * (J_DC(x, y) + J_DC(x, y - 1)); + g_22 = 0.5 * (g_22_DC(x, y) + g_22_DC(x, y - 1)); + g23 = 0.5 * (g23_DC(x, y) + g23_DC(x, y - 1)); + g_23 = 0.5 * (g_23_DC(x, y) + g_23_DC(x, y - 1)); + dy = 0.5 * (dy_DC(x, y) + dy_DC(x, y - 1)); + Acoef = 0.5 * (A(x, y - 1) + A(x, y)); + + val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x, y) * dy * dy_DC(x, y)); + ym = val; + c -= val; + } + + ///////////////////////////////////////////////// + // Now have a 5-point stencil for the Laplacian + + int row = globalIndex(x, y); + + // Set the centre (diagonal) + MatSetValues(MatA, 1, &row, 1, &row, &c, INSERT_VALUES); + + // X + 1 + int col = globalIndex(x + 1, y); + MatSetValues(MatA, 1, &row, 1, &col, &xp, INSERT_VALUES); + + // X - 1 + col = globalIndex(x - 1, y); + MatSetValues(MatA, 1, &row, 1, &col, &xm, INSERT_VALUES); + + if (include_y_derivs) { + // Y + 1 + col = globalIndex(x, y + 1); + MatSetValues(MatA, 1, &row, 1, &col, &yp, INSERT_VALUES); + + // Y - 1 + col = globalIndex(x, y - 1); + MatSetValues(MatA, 1, &row, 1, &col, &ym, INSERT_VALUES); + } + } + } +} + +void LaplaceXYpetsc::setMatrixElementsFiniteDifference(const Field2D& A, + const Field2D& B) { + ////////////////////////////////////////////////// + // Set Matrix elements + // + // Div(A Grad(f)) + B f + // = A Laplace_perp(f) + Grad_perp(A).Grad_perp(f) + B f + // = A*(G1*dfdx + (G2-1/J*d/dy(J/g_22))*dfdy + // + g11*d2fdx2 + (g22-1/g_22)*d2fdy2 + 2*g12*d2fdxdy) + // + g11*dAdx*dfdx + (g22-1/g_22)*dAdy*dfdy + g12*(dAdx*dfdy + dAdy*dfdx) + // + B*f + + auto coords = localmesh->getCoordinates(location); + const Field2D G1_2D = DC(coords->G1); + const Field2D G2_2D = DC(coords->G2); + const Field2D J_2D = DC(coords->J); + const Field2D g11_2D = DC(coords->g11); + const Field2D g_22_2D = DC(coords->g_22); + const Field2D g22_2D = DC(coords->g22); + const Field2D g12_2D = DC(coords->g12); + const Field2D d1_dx_2D = DC(coords->d1_dx); + const Field2D d1_dy_2D = DC(coords->d1_dy); + const Field2D dx_2D = DC(coords->dx); + const Field2D dy_2D = DC(coords->dy); + + const Field2D coef_dfdy = G2_2D - DC(DDY(J_2D / g_22_2D) / J_2D); + + for (int x = localmesh->xstart; x <= localmesh->xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + // stencil entries + PetscScalar c, xm, xp, ym, yp, xpyp, xpym, xmyp, xmym; + + BoutReal dx = dx_2D(x, y); + + // A*G1*dfdx + BoutReal val = A(x, y) * G1_2D(x, y) / (2. * dx); + xp = val; + xm = -val; + + // A*g11*d2fdx2 + val = A(x, y) * g11_2D(x, y) / SQ(dx); + xp += val; + c = -2. * val; + xm += val; + // Non-uniform grid correction + val = A(x, y) * g11_2D(x, y) * d1_dx_2D(x, y) / (2. * dx); + xp += val; + xm -= val; + + // g11*dAdx*dfdx + val = g11_2D(x, y) * (A(x + 1, y) - A(x - 1, y)) / (4. * SQ(dx)); + xp += val; + xm -= val; + + // B*f + c += B(x, y); + + // Put values into the preconditioner, X derivatives only + acoef(y - localmesh->ystart, x - xstart) = xm; + bcoef(y - localmesh->ystart, x - xstart) = c; + ccoef(y - localmesh->ystart, x - xstart) = xp; + + if (include_y_derivs) { + BoutReal dy = dy_2D(x, y); + BoutReal dAdx = (A(x + 1, y) - A(x - 1, y)) / (2. * dx); + BoutReal dAdy = (A(x, y + 1) - A(x, y - 1)) / (2. * dy); + + // A*(G2-1/J*d/dy(J/g_22))*dfdy + val = A(x, y) * coef_dfdy(x, y) / (2. * dy); + yp = val; + ym = -val; + + // A*(g22-1/g_22)*d2fdy2 + val = A(x, y) * (g22_2D(x, y) - 1. / g_22_2D(x, y)) / SQ(dy); + yp += val; + c -= 2. * val; + ym += val; + // Non-uniform mesh correction + val = A(x, y) * (g22_2D(x, y) - 1. / g_22_2D(x, y)) * d1_dy_2D(x, y) / (2. * dy); + yp += val; + ym -= val; + + // 2*A*g12*d2dfdxdy + val = A(x, y) * g12_2D(x, y) / (2. * dx * dy); + xpyp = val; + xpym = -val; + xmyp = -val; + xmym = val; + + // g22*dAdy*dfdy + val = (g22_2D(x, y) - 1. / g_22_2D(x, y)) * dAdy / (2. * dy); + yp += val; + ym -= val; + + // g12*(dAdx*dfdy + dAdy*dfdx) + val = g12_2D(x, y) * dAdx / (2. * dy); + yp += val; + ym -= val; + val = g12_2D(x, y) * dAdy / (2. * dx); + xp += val; + xm -= val; + } + + ///////////////////////////////////////////////// + // Now have a 9-point stencil for the Laplacian + + int row = globalIndex(x, y); + + // Set the centre (diagonal) + MatSetValues(MatA, 1, &row, 1, &row, &c, INSERT_VALUES); + + // X + 1 + int col = globalIndex(x + 1, y); + MatSetValues(MatA, 1, &row, 1, &col, &xp, INSERT_VALUES); + + // X - 1 + col = globalIndex(x - 1, y); + MatSetValues(MatA, 1, &row, 1, &col, &xm, INSERT_VALUES); + + if (include_y_derivs) { + // Y + 1 + col = globalIndex(x, y + 1); + MatSetValues(MatA, 1, &row, 1, &col, &yp, INSERT_VALUES); + + // Y - 1 + col = globalIndex(x, y - 1); + MatSetValues(MatA, 1, &row, 1, &col, &ym, INSERT_VALUES); + + // X + 1, Y + 1 + col = globalIndex(x + 1, y + 1); + MatSetValues(MatA, 1, &row, 1, &col, &xpyp, INSERT_VALUES); + + // X + 1, Y - 1 + col = globalIndex(x + 1, y - 1); + MatSetValues(MatA, 1, &row, 1, &col, &xpym, INSERT_VALUES); + + // X - 1, Y + 1 + col = globalIndex(x - 1, y + 1); + MatSetValues(MatA, 1, &row, 1, &col, &xmyp, INSERT_VALUES); + + // X - 1, Y - 1 + col = globalIndex(x - 1, y - 1); + MatSetValues(MatA, 1, &row, 1, &col, &xmym, INSERT_VALUES); + } + } + } +} + +LaplaceXYpetsc::~LaplaceXYpetsc() { + PetscBool is_finalised; + PetscFinalized(&is_finalised); + + if (!is_finalised) { + // PetscFinalize may already have destroyed this object + KSPDestroy(&ksp); + } + + VecDestroy(&xs); + VecDestroy(&bs); + MatDestroy(&MatA); +} + +Field2D LaplaceXYpetsc::solve(const Field2D& rhs, const Field2D& x0) { + Timer timer("invert"); + + ASSERT1(rhs.getMesh() == localmesh); + ASSERT1(x0.getMesh() == localmesh); + ASSERT1(rhs.getLocation() == location); + ASSERT1(x0.getLocation() == location); + + // Load initial guess x0 into xs and rhs into bs + + for (int x = localmesh->xstart; x <= localmesh->xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(x, y); + + PetscScalar val = x0(x, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = rhs(x, y); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + + if (finite_volume) { + solveFiniteVolume(x0); + } else { + solveFiniteDifference(x0); + } + + // Assemble RHS Vector + VecAssemblyBegin(bs); + VecAssemblyEnd(bs); + + // Assemble Trial Solution Vector + VecAssemblyBegin(xs); + VecAssemblyEnd(xs); + + // Solve the system + KSPSolve(ksp, bs, xs); + + KSPConvergedReason reason; + KSPGetConvergedReason(ksp, &reason); + + if (reason <= 0) { + throw BoutException("LaplaceXYpetsc failed to converge. Reason {} ({:d})", + KSPConvergedReasons[reason], static_cast(reason)); + } + + if (save_performance) { + // Update performance monitoring information + n_calls++; + + int iterations = 0; + KSPGetIterationNumber(ksp, &iterations); + + average_iterations = BoutReal(n_calls - 1) / BoutReal(n_calls) * average_iterations + + BoutReal(iterations) / BoutReal(n_calls); + } + + ////////////////////////// + // Copy data into result + + Field2D result; + result.allocate(); + result.setLocation(location); + + for (int x = localmesh->xstart; x <= localmesh->xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(x, y); + + PetscScalar val; + VecGetValues(xs, 1, &ind, &val); + result(x, y) = val; + } + } + + // Inner X boundary + if (localmesh->firstX()) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xstart - 1, y); + PetscScalar val; + VecGetValues(xs, 1, &ind, &val); + for (int x = localmesh->xstart - 1; x >= 0; x--) { + result(x, y) = val; + } + } + } + + // Outer X boundary + if (localmesh->lastX()) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xend + 1, y); + PetscScalar val; + VecGetValues(xs, 1, &ind, &val); + for (int x = localmesh->xend + 1; x < localmesh->LocalNx; x++) { + result(x, y) = val; + } + } + } + + // Lower Y boundary + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + if ( + // Should not go into corner cells, finite-volume LaplaceXYpetsc stencil does not include + // them + (finite_volume and (it.ind < localmesh->xstart or it.ind > localmesh->xend)) + + // Only go into first corner cell for finite-difference + or (it.ind < localmesh->xstart - 1 or it.ind > localmesh->xend + 1)) { + continue; + } + int ind = globalIndex(it.ind, localmesh->ystart - 1); + PetscScalar val; + VecGetValues(xs, 1, &ind, &val); + for (int y = localmesh->ystart - 1; y >= 0; y--) { + result(it.ind, y) = val; + } + } + + // Upper Y boundary + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + if ( + // Should not go into corner cells, finite-volume LaplaceXYpetsc stencil does not include + // them + (finite_volume and (it.ind < localmesh->xstart or it.ind > localmesh->xend)) + + // Only go into first corner cell for finite-difference + or (it.ind < localmesh->xstart - 1 or it.ind > localmesh->xend + 1)) { + continue; + } + int ind = globalIndex(it.ind, localmesh->yend + 1); + PetscScalar val; + VecGetValues(xs, 1, &ind, &val); + for (int y = localmesh->yend + 1; y < localmesh->LocalNy; y++) { + result(it.ind, y) = val; + } + } + + return result; +} + +void LaplaceXYpetsc::solveFiniteVolume(const Field2D& x0) { + // Use original LaplaceXYpetsc implementation of passing boundary values for backward + // compatibility + if (localmesh->firstX()) { + if (x_inner_dirichlet) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xstart - 1, y); + + PetscScalar val = x0(localmesh->xstart - 1, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.5 * (x0(localmesh->xstart - 1, y) + x0(localmesh->xstart, y)); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } else { + // Inner X boundary (Neumann) + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xstart - 1, y); + + PetscScalar val = x0(localmesh->xstart - 1, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.0; // x0(localmesh->xstart-1,y) - x0(localmesh->xstart,y); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + } + + // Outer X boundary (Dirichlet) + if (localmesh->lastX()) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xend + 1, y); + + PetscScalar val = x0(localmesh->xend + 1, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.5 * (x0(localmesh->xend, y) + x0(localmesh->xend + 1, y)); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + + if (y_bndry == "dirichlet") { + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->ystart - 1); + + PetscScalar val = x0(it.ind, localmesh->ystart - 1); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.5 * (x0(it.ind, localmesh->ystart - 1) + x0(it.ind, localmesh->ystart)); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->yend + 1); + + PetscScalar val = x0(it.ind, localmesh->yend + 1); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.5 * (x0(it.ind, localmesh->yend + 1) + x0(it.ind, localmesh->yend)); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } else if (y_bndry == "neumann" or y_bndry == "free_o3") { + // Y boundaries Neumann + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->ystart - 1); + + PetscScalar val = x0(it.ind, localmesh->ystart - 1); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->yend + 1); + + PetscScalar val = x0(it.ind, localmesh->yend + 1); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } else { + throw BoutException("Unsupported option for y_bndry"); + } +} + +void LaplaceXYpetsc::solveFiniteDifference(const Field2D& x0) { + // For finite-difference implementation pass boundary values in the same way as for + // the 'Laplacian' solvers - the value to use (for Dirichlet boundary conditions) on + // the boundary (which is half way between grid cell and boundary cell) is passed as + // the value in the first boundary cell. + if (localmesh->firstX()) { + if (x_inner_dirichlet) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xstart - 1, y); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 2. * x0(localmesh->xstart - 1, y) - x0(localmesh->xstart, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Pass the value from boundary cell of x0 as the boundary condition to the rhs + val = x0(localmesh->xstart - 1, y); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } else { + // Inner X boundary (Neumann) + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xstart - 1, y); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(localmesh->xstart, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + } + + // Outer X boundary (Dirichlet) + if (localmesh->lastX()) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + int ind = globalIndex(localmesh->xend + 1, y); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 2. * x0(localmesh->xend + 1, y) - x0(localmesh->xend, y); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Pass the value from boundary cell of x0 as the boundary condition to the rhs + val = x0(localmesh->xend + 1, y); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + + if (y_bndry == "dirichlet") { + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, they are treated specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = + 2. * x0(it.ind, localmesh->ystart - 1) - x0(it.ind, localmesh->ystart); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Pass the value from boundary cell of x0 as the boundary condition to the rhs + val = x0(it.ind, localmesh->ystart - 1); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, they are treated specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = + 2. * x0(it.ind, localmesh->yend + 1) - x0(it.ind, localmesh->yend); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Pass the value from boundary cell of x0 as the boundary condition to the rhs + val = x0(it.ind, localmesh->yend + 1); + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + + // Use free_o3 for the corner boundary cells + if (localmesh->hasBndryLowerY()) { + if (localmesh->firstX()) { + int ind = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->ystart) + - 3. * x0(localmesh->xstart - 1, localmesh->ystart + 1) + + x0(localmesh->xstart - 1, localmesh->ystart + 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->lastX()) { + int ind = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->ystart) + - 3. * x0(localmesh->xend + 1, localmesh->ystart + 1) + + x0(localmesh->xend + 1, localmesh->ystart + 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + if (localmesh->hasBndryUpperY()) { + if (localmesh->firstX()) { + int ind = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->yend) + - 3. * x0(localmesh->xstart - 1, localmesh->yend - 1) + + x0(localmesh->xstart - 1, localmesh->yend - 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->lastX()) { + int ind = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->yend) + - 3. * x0(localmesh->xend + 1, localmesh->yend - 1) + + x0(localmesh->xend + 1, localmesh->yend - 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + } else if (y_bndry == "neumann") { + // Y boundaries Neumann + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, they are treated specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(it.ind, localmesh->ystart); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->hasBndryLowerY()) { + if (localmesh->firstX()) { + int ind = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(localmesh->xstart - 1, localmesh->ystart); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->lastX()) { + int ind = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(localmesh->xend + 1, localmesh->ystart); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, they are treated specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(it.ind, localmesh->yend); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->hasBndryUpperY()) { + if (localmesh->firstX()) { + int ind = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(localmesh->xstart - 1, localmesh->yend); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->lastX()) { + int ind = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = x0(localmesh->xend + 1, localmesh->yend); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + } else if (y_bndry == "free_o3") { + // Y boundaries free_o3 + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, they are treated specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(it.ind, localmesh->ystart) + - 3. * x0(it.ind, localmesh->ystart + 1) + + x0(it.ind, localmesh->ystart + 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->hasBndryLowerY()) { + if (localmesh->firstX()) { + int ind = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->ystart) + - 3. * x0(localmesh->xstart - 1, localmesh->ystart + 1) + + x0(localmesh->xstart - 1, localmesh->ystart + 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->lastX()) { + int ind = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->ystart) + - 3. * x0(localmesh->xend + 1, localmesh->ystart + 1) + + x0(localmesh->xend + 1, localmesh->ystart + 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, they are treated specially below + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + int ind = globalIndex(it.ind, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(it.ind, localmesh->yend) + - 3. * x0(it.ind, localmesh->yend - 1) + + x0(it.ind, localmesh->yend - 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->hasBndryUpperY()) { + if (localmesh->firstX()) { + int ind = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->yend) + - 3. * x0(localmesh->xstart - 1, localmesh->yend - 1) + + x0(localmesh->xstart - 1, localmesh->yend - 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + if (localmesh->lastX()) { + int ind = globalIndex(localmesh->xend + 1, localmesh->yend + 1); + + // For the boundary value of the initial guess, use the value that would be set by + // applying the boundary condition to the initial guess + PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->yend) + - 3. * x0(localmesh->xend + 1, localmesh->yend - 1) + + x0(localmesh->xend + 1, localmesh->yend - 2); + VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); + + // Set the value for the rhs of the boundary condition to zero + val = 0.0; + VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); + } + } + } else { + throw BoutException("Unsupported option for y_bndry"); + } +} + +/*! Preconditioner + * NOTE: For generality, this routine does use globalIndex() in the inner loop, although + * this may be slightly less efficient than incrementing an integer for the global index, + * the finite-volume and finite-difference implementations have slightly different + * indexing patterns, so incrementing an integer would be tricky. + */ +int LaplaceXYpetsc::precon(Vec input, Vec result) { + + for (auto itdwn = localmesh->iterateBndryLowerY(); !itdwn.isDone(); itdwn++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (itdwn.ind < localmesh->xstart or itdwn.ind > localmesh->xend) { + continue; + } + const int ind = globalIndex(itdwn.ind, localmesh->ystart - 1); + PetscScalar val; + VecGetValues(input, 1, &ind, &val); + VecSetValues(result, 1, &ind, &val, INSERT_VALUES); + } + for (auto itup = localmesh->iterateBndryUpperY(); !itup.isDone(); itup++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (itup.ind < localmesh->xstart or itup.ind > localmesh->xend) { + continue; + } + const int ind = globalIndex(itup.ind, localmesh->yend + 1); + PetscScalar val; + VecGetValues(input, 1, &ind, &val); + VecSetValues(result, 1, &ind, &val, INSERT_VALUES); + } + + // Load vector x into bvals array + for (int x = xstart; x <= xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int ind = globalIndex(x, y); + PetscScalar val; + VecGetValues(input, 1, &ind, &val); + bvals(y - localmesh->ystart, x - xstart) = val; + } + } + + // Solve tridiagonal systems using CR solver + cr->solve(bvals, xvals); + + // Save result xvals into y array + for (int x = xstart; x <= xend; x++) { + for (int y = localmesh->ystart; y <= localmesh->yend; y++) { + const int ind = globalIndex(x, y); + PetscScalar val = xvals(y - localmesh->ystart, x - xstart); + VecSetValues(result, 1, &ind, &val, INSERT_VALUES); + } + } + VecAssemblyBegin(result); + VecAssemblyEnd(result); + return 0; +} + +/////////////////////////////////////////////////////////////// + +int LaplaceXYpetsc::localSize() { + + // Bulk of points + const int nx = localmesh->xend - localmesh->xstart + 1; + const int ny = localmesh->yend - localmesh->ystart + 1; + + int n = nx * ny; + + // X boundaries + if (localmesh->firstX()) { + n += ny; + } + if (localmesh->lastX()) { + n += ny; + } + + // Y boundaries + for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + n++; + } + if ((not finite_volume) and localmesh->hasBndryLowerY()) { + if (localmesh->firstX()) { + n++; + } + if (localmesh->lastX()) { + n++; + } + } + for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { + // Should not go into corner cells, LaplaceXYpetsc stencil does not include them + if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { + continue; + } + n++; + } + if ((not finite_volume) and localmesh->hasBndryUpperY()) { + if (localmesh->firstX()) { + n++; + } + if (localmesh->lastX()) { + n++; + } + } + + return n; +} + +int LaplaceXYpetsc::globalIndex(int x, int y) { + if ((x < 0) || (x >= localmesh->LocalNx) || (y < 0) || (y >= localmesh->LocalNy)) { + return -1; // Out of range + } + + // Get the index from a Field2D, round to integer + return static_cast(std::round(indexXY(x, y))); +} + +void LaplaceXYpetsc::savePerformance(Solver& solver, const std::string& name) { + // set flag so that performance monitoring values are calculated + save_performance = true; + + // add values to be saved to the output + if (not name.empty()) { + default_prefix = name; + } + + // add monitor to reset counters/averages for new output timestep + // monitor added to back of queue, so that values are reset after being saved + solver.addMonitor(&monitor, Solver::BACK); +} + +int LaplaceXYpetsc::LaplaceXYMonitor::call(Solver* /*solver*/, BoutReal /*time*/, + int /*iter*/, int /*nout*/) { + laplacexy->output_average_iterations = laplacexy->average_iterations; + + laplacexy->n_calls = 0; + laplacexy->average_iterations = 0.; + + return 0; +} + +void LaplaceXYpetsc::LaplaceXYMonitor::outputVars(Options& output_options, + const std::string& time_dimension) { + output_options[fmt::format("{}_average_iterations", laplacexy->default_prefix)] + .assignRepeat(laplacexy->output_average_iterations, time_dimension); +} + +#endif // BOUT_HAS_PETSC diff --git a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx new file mode 100644 index 0000000000..1db812a19d --- /dev/null +++ b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx @@ -0,0 +1,204 @@ +/************************************************************************** + * Laplacian solver in 2D (X-Y) + * + * Equation solved is: + * + * Div( A * Grad_perp(x) ) + B*x = b + * + * Intended for use in solving n = 0 component of potential + * from inversion of vorticity equation + * + ************************************************************************** + * Copyright 2015 B.Dudson + * + * Contact: Ben Dudson, bd512@york.ac.uk + * + * This file is part of BOUT++. + * + * BOUT++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BOUT++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with BOUT++. If not, see . + * + **************************************************************************/ + +#ifndef BOUT_LAPLACE_XY_PETSC_H +#define BOUT_LAPLACE_XY_PETSC_H + +#include "bout/build_defines.hxx" +#include "bout/invert/laplacexy.hxx" + +#if !BOUT_HAS_PETSC + +namespace { +RegisterUnavailableLaplaceXY + registerlaplacexypetsc("petsc", "BOUT++ was not configured with PETSc"); +} + +#else // BOUT_HAS_PETSC + +#include "bout/solver.hxx" +#include "bout/utils.hxx" +#include +#include +#include + +class Options; +class Solver; + +class LaplaceXYpetsc : public LaplaceXY { +public: + LaplaceXYpetsc(Mesh* m = nullptr, Options* opt = nullptr, CELL_LOC loc = CELL_CENTRE); + LaplaceXYpetsc(const LaplaceXYpetsc&) = delete; + LaplaceXYpetsc(LaplaceXYpetsc&&) = delete; + LaplaceXYpetsc& operator=(const LaplaceXYpetsc&) = delete; + LaplaceXYpetsc& operator=(LaplaceXYpetsc&&) = delete; + ~LaplaceXYpetsc() override; + + /*! + * Set coefficients (A, B) in equation: + * Div( A * Grad_perp(x) ) + B*x = b + */ + void setCoefs(const Field2D& A, const Field2D& B) override; + + /*! + * Solve Laplacian in X-Y + * + * Inputs + * ====== + * + * rhs - The field to be inverted. This must be allocated + * and contain valid data. + * x0 - Initial guess at the solution. If this is unallocated + * then an initial guess of zero will be used. + * + * Returns + * ======= + * + * The solution as a Field2D. On failure an exception will be raised + * + */ + Field2D solve(const Field2D& rhs, const Field2D& x0) override; + + /*! + * Preconditioner function + * This is called by PETSc via a static function. + * and should not be called by external users + */ + int precon(Vec x, Vec y); + + /*! + * If this method is called, save some performance monitoring information + */ + void savePerformance(Solver& solver, const std::string& name = ""); + +private: + PetscLib lib; ///< Requires PETSc library + Mat MatA = nullptr; ///< Matrix to be inverted + Vec xs = nullptr; ///< Solution vector + Vec bs = nullptr; ///< RHS vectors + KSP ksp = nullptr; ///< Krylov Subspace solver + PC pc = nullptr; ///< Preconditioner + + Mesh* localmesh; ///< The mesh this operates on, provides metrics and communication + + /// default prefix for writing performance logging variables + std::string default_prefix; + + // Preconditioner + int xstart, xend; + int nloc, nsys; + Matrix acoef, bcoef, ccoef, xvals, bvals; + std::unique_ptr> cr; ///< Tridiagonal solver + + // Use finite volume or finite difference discretization + bool finite_volume{true}; + + // Y derivatives + bool include_y_derivs; // Include Y derivative terms? + + // Boundary conditions + bool x_inner_dirichlet; // Dirichlet on inner X boundary? + bool x_outer_dirichlet{false}; // Dirichlet on outer X boundary? + std::string y_bndry{"neumann"}; // Boundary condition for y-boundary + + // Location of the rhs and solution + CELL_LOC location; + + /*! + * Number of grid points on this processor + */ + int localSize(); + + /*! + * Return the communicator for XY + */ + MPI_Comm communicator(); + + /*! + * Return the global index of a local (x,y) coordinate + * including guard cells. + * Boundary cells have a global index of -1 + * + * To do this, a Field2D (indexXY) is used to store + * the index as a floating point number which is then rounded + * to an integer. Guard cells are filled by communication + * so no additional logic is needed in Mesh. + */ + int globalIndex(int x, int y); + Field2D indexXY; ///< Global index (integer stored as BoutReal) + + // Save performance information? + bool save_performance = false; + + // Running average of number of iterations taken for solve in each output timestep + BoutReal average_iterations = 0.; + + // Variable to store the final result of average_iterations, since output is + // written after all other monitors have been called, and average_iterations + // must be reset in the monitor + BoutReal output_average_iterations = 0.; + + // Running total of number of calls to the solver in each output timestep + int n_calls = 0; + + // Utility methods + void setPreallocationFiniteVolume(PetscInt* d_nnz, PetscInt* o_nnz); + void setPreallocationFiniteDifference(PetscInt* d_nnz, PetscInt* o_nnz); + void setMatrixElementsFiniteVolume(const Field2D& A, const Field2D& B); + void setMatrixElementsFiniteDifference(const Field2D& A, const Field2D& B); + void solveFiniteVolume(const Field2D& x0); + void solveFiniteDifference(const Field2D& x0); + + // Monitor class used to reset performance-monitoring variables for a new + // output timestep + friend class LaplaceXYMonitor; + class LaplaceXYMonitor : public Monitor { + public: + LaplaceXYMonitor(LaplaceXYpetsc& owner) : laplacexy(&owner) {} + + int call(Solver* /*solver*/, BoutReal /*time*/, int /*iter*/, int /*nout*/) override; + void outputVars(Options& output_options, const std::string& time_dimension) override; + + private: + // LaplaceXY object that this monitor belongs to + LaplaceXYpetsc* laplacexy; + }; + + LaplaceXYMonitor monitor; +}; + +namespace { +const inline RegisterLaplaceXY registerlaplacexypetsc{"petsc"}; +} + +#endif // BOUT_HAS_PETSC +#endif // BOUT_LAPLACE_XY_PETSC_H diff --git a/src/invert/laplacexy2/laplacexy2.cxx b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx similarity index 94% rename from src/invert/laplacexy2/laplacexy2.cxx rename to src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx index 713fd8e68f..ae2cc8313a 100644 --- a/src/invert/laplacexy2/laplacexy2.cxx +++ b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx @@ -2,26 +2,25 @@ #if BOUT_HAS_PETSC and not BOUT_USE_METRIC_3D +#include "laplacexy-petsc2.hxx" + #include #include #include -#include #include #include #include #include -#include - namespace { Ind2D index2d(Mesh* mesh, int x, int y) { int ny = mesh->LocalNy; - return Ind2D(x * ny + y, ny, 1); + return Ind2D((x * ny) + y, ny, 1); } } // namespace -LaplaceXY2::LaplaceXY2(Mesh* m, Options* opt, const CELL_LOC loc) +LaplaceXYpetsc2::LaplaceXYpetsc2(Mesh* m, Options* opt, const CELL_LOC loc) : localmesh(m == nullptr ? bout::globals::mesh : m), indexConverter(std::make_shared>( localmesh, squareStencil(localmesh))), @@ -100,12 +99,12 @@ LaplaceXY2::LaplaceXY2(Mesh* m, Options* opt, const CELL_LOC loc) // Decide boundary condititions if (localmesh->periodicY(localmesh->xstart)) { // Periodic in Y, so in the core - opt->get("core_bndry_dirichlet", x_inner_dirichlet, false); + x_inner_dirichlet = (*opt)["core_bndry_dirichlet"].withDefault(false); } else { // Non-periodic, so in the PF region - opt->get("pf_bndry_dirichlet", x_inner_dirichlet, true); + x_inner_dirichlet = (*opt)["pf_bndry_dirichlet"].withDefault(true); } - opt->get("y_bndry_dirichlet", y_bndry_dirichlet, false); + y_bndry_dirichlet = (*opt)["y_bndry_dirichlet"].withDefault(false); /////////////////////////////////////////////////// // Including Y derivatives? @@ -123,7 +122,7 @@ LaplaceXY2::LaplaceXY2(Mesh* m, Options* opt, const CELL_LOC loc) setCoefs(one, zero); } -void LaplaceXY2::setCoefs(const Field2D& A, const Field2D& B) { +void LaplaceXYpetsc2::setCoefs(const Field2D& A, const Field2D& B) { Timer timer("invert"); ASSERT1(A.getMesh() == localmesh); @@ -290,7 +289,7 @@ void LaplaceXY2::setCoefs(const Field2D& A, const Field2D& B) { #endif } -LaplaceXY2::~LaplaceXY2() { +LaplaceXYpetsc2::~LaplaceXYpetsc2() { PetscBool is_finalised; PetscFinalized(&is_finalised); @@ -300,7 +299,7 @@ LaplaceXY2::~LaplaceXY2() { } } -Field2D LaplaceXY2::solve(const Field2D& rhs, const Field2D& x0) { +Field2D LaplaceXYpetsc2::solve(const Field2D& rhs, const Field2D& x0) { Timer timer("invert"); ASSERT1(rhs.getMesh() == localmesh); @@ -310,7 +309,8 @@ Field2D LaplaceXY2::solve(const Field2D& rhs, const Field2D& x0) { // Load initial guess x0 into xs and rhs into bs - PetscVector xs(x0, indexConverter), bs(rhs, indexConverter); + PetscVector xs(x0, indexConverter); + PetscVector bs(rhs, indexConverter); if (localmesh->firstX()) { if (x_inner_dirichlet) { @@ -381,11 +381,11 @@ Field2D LaplaceXY2::solve(const Field2D& rhs, const Field2D& x0) { // Solve the system KSPSolve(ksp, *bs.get(), *xs.get()); - KSPConvergedReason reason; + KSPConvergedReason reason = KSP_CONVERGED_ITERATING; KSPGetConvergedReason(ksp, &reason); if (reason <= 0) { - throw BoutException("LaplaceXY2 failed to converge. Reason {} ({:d})", + throw BoutException("LaplaceXYpetsc2 failed to converge. Reason {} ({:d})", KSPConvergedReasons[reason], static_cast(reason)); } diff --git a/include/bout/invert/laplacexy2.hxx b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx similarity index 64% rename from include/bout/invert/laplacexy2.hxx rename to src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx index 51f75f467d..1480f366fe 100644 --- a/include/bout/invert/laplacexy2.hxx +++ b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx @@ -30,63 +30,45 @@ * **************************************************************************/ -#ifndef BOUT_LAPLACE_XY2_H -#define BOUT_LAPLACE_XY2_H +#ifndef BOUT_LAPLACE_XY_PETSC2_H +#define BOUT_LAPLACE_XY_PETSC2_H #include "bout/build_defines.hxx" +#include "bout/invert/laplacexy.hxx" -#if (not BOUT_HAS_PETSC) or BOUT_USE_METRIC_3D -// If no PETSc or 3D metrics +#if !BOUT_HAS_PETSC +namespace { +RegisterUnavailableLaplaceXY + registerlaplacexypetsc2("petsc2", "BOUT++ was not configured with PETSc"); +} -#warning LaplaceXY2 requires PETSc and 2D metrics. No LaplaceXY2 available +#elif BOUT_USE_METRIC_3D +namespace { +RegisterUnavailableLaplaceXY + registerlaplacexypetsc2("petsc2", "BOUT++ was configured with 3D metrics"); +} -#include -#include -#include - -/*! - * Create a dummy class so that code will compile - * without PETSc, but will throw an exception if - * LaplaceXY is used. - */ -class LaplaceXY2 { -public: - LaplaceXY2(Mesh* UNUSED(m) = nullptr, Options* UNUSED(opt) = nullptr, - const CELL_LOC UNUSED(loc) = CELL_CENTRE) { - throw BoutException( - "LaplaceXY2 requires PETSc and 2D metrics. No LaplaceXY2 available"); - } - void setCoefs(const Field2D& UNUSED(A), const Field2D& UNUSED(B)) {} - Field2D solve(const Field2D& UNUSED(rhs), const Field2D& UNUSED(x0)) { - throw BoutException( - "LaplaceXY2 requires PETSc and 2D metrics. No LaplaceXY2 available"); - } -}; +#else // BOUT_HAS_PETSC -#else // BOUT_HAS_PETSC and 2D metrics - -#include "bout/utils.hxx" #include #include #include #include -class LaplaceXY2 { +class LaplaceXYpetsc2 : public LaplaceXY { public: - /*! - * Constructor - */ - LaplaceXY2(Mesh* m = nullptr, Options* opt = nullptr, const CELL_LOC loc = CELL_CENTRE); - /*! - * Destructor - */ - ~LaplaceXY2(); + LaplaceXYpetsc2(Mesh* m = nullptr, Options* opt = nullptr, CELL_LOC loc = CELL_CENTRE); + LaplaceXYpetsc2(const LaplaceXYpetsc2&) = default; + LaplaceXYpetsc2(LaplaceXYpetsc2&&) = delete; + LaplaceXYpetsc2& operator=(const LaplaceXYpetsc2&) = default; + LaplaceXYpetsc2& operator=(LaplaceXYpetsc2&&) = delete; + ~LaplaceXYpetsc2() override; /*! * Set coefficients (A, B) in equation: * Div( A * Grad_perp(x) ) + B*x = b */ - void setCoefs(const Field2D& A, const Field2D& B); + void setCoefs(const Field2D& A, const Field2D& B) override; /*! * Solve Laplacian in X-Y @@ -105,7 +87,7 @@ public: * The solution as a Field2D. On failure an exception will be raised * */ - Field2D solve(const Field2D& rhs, const Field2D& x0); + Field2D solve(const Field2D& rhs, const Field2D& x0) override; /*! * Preconditioner function @@ -121,8 +103,8 @@ private: IndexerPtr indexConverter; PetscMatrix matrix; ///< Matrix to be inverted - KSP ksp; ///< Krylov Subspace solver - PC pc; ///< Preconditioner + KSP ksp = nullptr; ///< Krylov Subspace solver + PC pc = nullptr; ///< Preconditioner // Y derivatives bool include_y_derivs; // Include Y derivative terms? @@ -140,5 +122,9 @@ private: MPI_Comm communicator(); }; +namespace { +const inline RegisterLaplaceXY registerlaplacexypetsc2{"petsc2"}; +} + #endif // BOUT_HAS_PETSC -#endif // BOUT_LAPLACE_XY2_H +#endif // BOUT_LAPLACE_XY_PETSC2_H diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index bdd22e29bd..3bac2d9d2b 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -1,1889 +1,10 @@ -#include "bout/build_defines.hxx" - -#if BOUT_HAS_PETSC +// NOLINTBEGIN(misc-include-cleaner, unused-includes) +#include "impls/hypre/laplacexy-hypre.hxx" +#include "impls/petsc/laplacexy-petsc.hxx" +#include "impls/petsc2/laplacexy-petsc2.hxx" +// NOLINTEND(misc-include-cleaner, unused-includes) #include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static PetscErrorCode laplacePCapply(PC pc, Vec x, Vec y) { - int ierr; - - // Get the context - LaplaceXY* s; - ierr = PCShellGetContext(pc, reinterpret_cast(&s)); - CHKERRQ(ierr); - - PetscFunctionReturn(s->precon(x, y)); -} - -LaplaceXY::LaplaceXY(Mesh* m, Options* opt, const CELL_LOC loc) - : lib(opt == nullptr ? &(Options::root()["laplacexy"]) : opt), - localmesh(m == nullptr ? bout::globals::mesh : m), location(loc), monitor(*this) { - Timer timer("invert"); - - if (opt == nullptr) { - // If no options supplied, use default - opt = &(Options::root()["laplacexy"]); - } - - finite_volume = - (*opt)["finite_volume"] - .doc("Use finite volume rather than finite difference discretisation.") - .withDefault(true); - - /////////////////////////////////////////////////// - // Boundary condititions options - if (localmesh->periodicY(localmesh->xstart)) { - // Periodic in Y, so in the core - x_inner_dirichlet = (*opt)["core_bndry_dirichlet"].withDefault(false); - } else { - // Non-periodic, so in the PF region - x_inner_dirichlet = (*opt)["pf_bndry_dirichlet"].withDefault(true); - } - if ((*opt)["y_bndry_dirichlet"].isSet()) { - throw BoutException("y_bndry_dirichlet has been deprecated. Use y_bndry=dirichlet " - "instead."); - } else { - y_bndry = (*opt)["y_bndry"].withDefault("neumann"); - } - - // Check value of y_bndry is a supported option - if (not(y_bndry == "dirichlet" or y_bndry == "neumann" or y_bndry == "free_o3")) { - - throw BoutException("Unrecognized option '{}' for laplacexy:ybndry", y_bndry); - } - - if (not finite_volume) { - // Check we can use corner cells - if (not localmesh->include_corner_cells) { - throw BoutException( - "Finite difference form of LaplaceXY allows non-orthogonal x- and " - "y-directions, so requires mesh:include_corner_cells=true."); - } - } - - // Use name of options section as the default prefix for performance logging variables - default_prefix = opt->name(); - - // Get MPI communicator - auto comm = BoutComm::get(); - - // Local size - const int localN = localSize(); - - // Create Vectors - VecCreate(comm, &xs); - VecSetSizes(xs, localN, PETSC_DETERMINE); - VecSetFromOptions(xs); - VecDuplicate(xs, &bs); - - // Set size of Matrix on each processor to localN x localN - MatCreate(comm, &MatA); - MatSetSizes(MatA, localN, localN, PETSC_DETERMINE, PETSC_DETERMINE); - MatSetFromOptions(MatA); - - ////////////////////////////////////////////////// - // Specify local indices. This creates a mapping - // from local indices to index, using a Field2D object - - indexXY = -1; // Set all points to -1, indicating out of domain - - int ind = 0; - - // Y boundaries - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - indexXY(it.ind, localmesh->ystart - 1) = ind++; - } - if ((not finite_volume) and localmesh->hasBndryLowerY()) { - // Corner boundary cells - if (localmesh->firstX()) { - indexXY(localmesh->xstart - 1, localmesh->ystart - 1) = ind++; - } - if (localmesh->lastX()) { - indexXY(localmesh->xend + 1, localmesh->ystart - 1) = ind++; - } - } - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - indexXY(it.ind, localmesh->yend + 1) = ind++; - } - if ((not finite_volume) and localmesh->hasBndryUpperY()) { - // Corner boundary cells - if (localmesh->firstX()) { - indexXY(localmesh->xstart - 1, localmesh->yend + 1) = ind++; - } - if (localmesh->lastX()) { - indexXY(localmesh->xend + 1, localmesh->yend + 1) = ind++; - } - } - - xstart = localmesh->xstart; - if (localmesh->firstX()) { - xstart -= 1; // Include X guard cells - } - xend = localmesh->xend; - if (localmesh->lastX()) { - xend += 1; - } - for (int x = xstart; x <= xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - indexXY(x, y) = ind++; - } - } - - ASSERT1(ind == localN); // Reached end of range - - ////////////////////////////////////////////////// - // Allocate storage for preconditioner - - nloc = xend - xstart + 1; // Number of X points on this processor - nsys = localmesh->yend - localmesh->ystart + 1; // Number of separate Y slices - - acoef.reallocate(nsys, nloc); - bcoef.reallocate(nsys, nloc); - ccoef.reallocate(nsys, nloc); - xvals.reallocate(nsys, nloc); - bvals.reallocate(nsys, nloc); - - // Create a cyclic reduction object - cr = bout::utils::make_unique>(localmesh->getXcomm(), nloc); - - ////////////////////////////////////////////////// - // Pre-allocate PETSc storage - - PetscInt *d_nnz, *o_nnz; - PetscMalloc((localN) * sizeof(PetscInt), &d_nnz); - PetscMalloc((localN) * sizeof(PetscInt), &o_nnz); - - if (finite_volume) { - setPreallocationFiniteVolume(d_nnz, o_nnz); - } else { - setPreallocationFiniteDifference(d_nnz, o_nnz); - } - // Pre-allocate - MatMPIAIJSetPreallocation(MatA, 0, d_nnz, 0, o_nnz); - MatSetUp(MatA); - - PetscFree(d_nnz); - PetscFree(o_nnz); - - // Determine which row/columns of the matrix are locally owned - int Istart, Iend; - MatGetOwnershipRange(MatA, &Istart, &Iend); - - // Convert indexXY from local index to global index - indexXY += Istart; - - // Now communicate to fill guard cells - // Note, this includes corner cells if necessary - localmesh->communicate(indexXY); - - ////////////////////////////////////////////////// - // Set up KSP - - // Declare KSP Context - KSPCreate(comm, &ksp); - - // Configure Linear Solver - - const bool direct = (*opt)["direct"].doc("Use a direct LU solver").withDefault(false); - - if (direct) { - KSPGetPC(ksp, &pc); - PCSetType(pc, PCLU); -#if PETSC_VERSION_GE(3, 9, 0) - PCFactorSetMatSolverType(pc, "mumps"); -#else - PCFactorSetMatSolverPackage(pc, "mumps"); -#endif - } else { - - // Convergence Parameters. Solution is considered converged if |r_k| < max( rtol * |b| , atol ) - // where r_k = b - Ax_k. The solution is considered diverged if |r_k| > dtol * |b|. - - const BoutReal rtol = (*opt)["rtol"].doc("Relative tolerance").withDefault(1e-5); - const BoutReal atol = - (*opt)["atol"] - .doc("Absolute tolerance. The solution is considered converged if |Ax-b| " - "< max( rtol * |b| , atol )") - .withDefault(1e-10); - const BoutReal dtol = - (*opt)["dtol"] - .doc("The solution is considered diverged if |Ax-b| > dtol * |b|") - .withDefault(1e3); - const int maxits = (*opt)["maxits"].doc("Maximum iterations").withDefault(100000); - - // Get KSP Solver Type - const std::string ksptype = - (*opt)["ksptype"].doc("KSP solver type").withDefault("gmres"); - - // Get PC type - const std::string pctype = - (*opt)["pctype"].doc("Preconditioner type").withDefault("none"); - - KSPSetType(ksp, ksptype.c_str()); - KSPSetTolerances(ksp, rtol, atol, dtol, maxits); - - KSPSetInitialGuessNonzero(ksp, static_cast(true)); - - KSPGetPC(ksp, &pc); - PCSetType(pc, pctype.c_str()); - - if (pctype == "shell") { - // Using tridiagonal solver as preconditioner - PCShellSetApply(pc, laplacePCapply); - PCShellSetContext(pc, this); - - const bool rightprec = - (*opt)["rightprec"].doc("Use right preconditioning?").withDefault(true); - if (rightprec) { - KSPSetPCSide(ksp, PC_RIGHT); // Right preconditioning - } else { - KSPSetPCSide(ksp, PC_LEFT); // Left preconditioning - } - } - } - - lib.setOptionsFromInputFile(ksp); - - /////////////////////////////////////////////////// - // Including Y derivatives? - - include_y_derivs = (*opt)["include_y_derivs"] - .doc("Include Y derivatives in operator to invert?") - .withDefault(true); - - /////////////////////////////////////////////////// - // Set the default coefficients - Field2D one(1., localmesh); - Field2D zero(0., localmesh); - one.setLocation(location); - zero.setLocation(location); - setCoefs(one, zero); -} - -void LaplaceXY::setPreallocationFiniteVolume(PetscInt* d_nnz, PetscInt* o_nnz) { - const int localN = localSize(); - - // This discretisation uses a 5-point stencil - for (int i = 0; i < localN; i++) { - // Non-zero elements on this processor - d_nnz[i] = 5; // Star pattern in 2D - // Non-zero elements on neighboring processor - o_nnz[i] = 0; - } - - // X boundaries - if (localmesh->firstX()) { - // Lower X boundary - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xstart - 1, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - - d_nnz[localIndex] = 2; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - } else { - // On another processor - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xstart, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] -= 1; - o_nnz[localIndex] += 1; - } - } - if (localmesh->lastX()) { - // Upper X boundary - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xend + 1, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 2; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - } else { - // On another processor - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xend, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] -= 1; - o_nnz[localIndex] += 1; - } - } - // Y boundaries - - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - // Default to no boundary - // NOTE: This assumes that communications in Y are to other - // processors. If Y is communicated with this processor (e.g. NYPE=1) - // then this will result in PETSc warnings about out of range allocations - { - const int localIndex = globalIndex(x, localmesh->ystart); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - // d_nnz[localIndex] -= 1; // Note: Slightly inefficient - o_nnz[localIndex] += 1; - } - { - const int localIndex = globalIndex(x, localmesh->yend); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - // d_nnz[localIndex] -= 1; // Note: Slightly inefficient - o_nnz[localIndex] += 1; - } - } - - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - { - const int localIndex = globalIndex(it.ind, localmesh->ystart - 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 2; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - { - const int localIndex = globalIndex(it.ind, localmesh->ystart); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] += 1; - o_nnz[localIndex] -= 1; - } - } - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - { - const int localIndex = globalIndex(it.ind, localmesh->yend + 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 2; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - { - const int localIndex = globalIndex(it.ind, localmesh->yend); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] += 1; - o_nnz[localIndex] -= 1; - } - } -} - -void LaplaceXY::setPreallocationFiniteDifference(PetscInt* d_nnz, PetscInt* o_nnz) { - const int localN = localSize(); - - // This discretisation uses a 9-point stencil - for (int i = 0; i < localN; i++) { - // Non-zero elements on this processor - d_nnz[i] = 9; // Square pattern in 2D - // Non-zero elements on neighboring processor - o_nnz[i] = 0; - } - - // X boundaries - if (localmesh->firstX()) { - // Lower X boundary - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xstart - 1, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - - d_nnz[localIndex] = 2; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - } else { - // On another processor - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xstart, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] -= 3; - o_nnz[localIndex] += 3; - } - } - if (localmesh->lastX()) { - // Upper X boundary - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xend + 1, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 2; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - } else { - // On another processor - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int localIndex = globalIndex(localmesh->xend, y); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] -= 3; - o_nnz[localIndex] += 3; - } - } - // Y boundaries - const int y_bndry_stencil_size = (y_bndry == "free_o3") ? 4 : 2; - - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - // Default to no boundary - // NOTE: This assumes that communications in Y are to other - // processors. If Y is communicated with this processor (e.g. NYPE=1) - // then this will result in PETSc warnings about out of range allocations - { - const int localIndex = globalIndex(x, localmesh->ystart); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - // d_nnz[localIndex] -= 3; // Note: Slightly inefficient - o_nnz[localIndex] += 3; - } - { - const int localIndex = globalIndex(x, localmesh->yend); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - // d_nnz[localIndex] -= 3; // Note: Slightly inefficient - o_nnz[localIndex] += 3; - } - } - - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, they are handled specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - { - const int localIndex = globalIndex(it.ind, localmesh->ystart - 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = y_bndry_stencil_size; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - { - const int localIndex = globalIndex(it.ind, localmesh->ystart); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - //d_nnz[localIndex] += 3; - o_nnz[localIndex] -= 3; - } - } - if (localmesh->hasBndryLowerY()) { - if (y_bndry == "dirichlet") { - // special handling for the corners, since we use a free_o3 y-boundary - // condition just in the corners when y_bndry=="dirichlet" - if (localmesh->firstX()) { - const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 4; - } - if (localmesh->lastX()) { - const int localIndex = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 4; - } - } else { - if (localmesh->firstX()) { - const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = y_bndry_stencil_size; - } - if (localmesh->lastX()) { - const int localIndex = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = y_bndry_stencil_size; - } - } - } - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, they are handled specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - { - const int localIndex = globalIndex(it.ind, localmesh->yend + 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = y_bndry_stencil_size; // Diagonal sub-matrix - o_nnz[localIndex] = 0; // Off-diagonal sub-matrix - } - { - const int localIndex = globalIndex(it.ind, localmesh->yend); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - //d_nnz[localIndex] += 3; - o_nnz[localIndex] -= 3; - } - } - if (localmesh->hasBndryUpperY()) { - if (y_bndry == "dirichlet") { - // special handling for the corners, since we use a free_o3 y-boundary - // condition just in the corners when y_bndry=="dirichlet" - if (localmesh->firstX()) { - const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 4; - } - if (localmesh->lastX()) { - const int localIndex = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = 4; - } - } else { - if (localmesh->firstX()) { - const int localIndex = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = y_bndry_stencil_size; - } - if (localmesh->lastX()) { - const int localIndex = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - ASSERT1((localIndex >= 0) && (localIndex < localN)); - d_nnz[localIndex] = y_bndry_stencil_size; - } - } - } -} - -void LaplaceXY::setCoefs(const Field2D& A, const Field2D& B) { - Timer timer("invert"); - - ASSERT1(A.getMesh() == localmesh); - ASSERT1(B.getMesh() == localmesh); - ASSERT1(A.getLocation() == location); - ASSERT1(B.getLocation() == location); - - if (finite_volume) { - setMatrixElementsFiniteVolume(A, B); - } else { - setMatrixElementsFiniteDifference(A, B); - } - - // X boundaries - if (localmesh->firstX()) { - if (x_inner_dirichlet) { - - // Dirichlet on inner X boundary - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int row = globalIndex(localmesh->xstart - 1, y); - PetscScalar val = 0.5; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - int col = globalIndex(localmesh->xstart, y); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - // Preconditioner - bcoef(y - localmesh->ystart, 0) = 0.5; - ccoef(y - localmesh->ystart, 0) = 0.5; - } - - } else { - - // Neumann on inner X boundary - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int row = globalIndex(localmesh->xstart - 1, y); - PetscScalar val = 1.0; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - int col = globalIndex(localmesh->xstart, y); - val = -1.0; - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - // Preconditioner - bcoef(y - localmesh->ystart, 0) = 1.0; - ccoef(y - localmesh->ystart, 0) = -1.0; - } - } - } - if (localmesh->lastX()) { - // Dirichlet on outer X boundary - - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int row = globalIndex(localmesh->xend + 1, y); - PetscScalar val = 0.5; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - int col = globalIndex(localmesh->xend, y); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - // Preconditioner - acoef(y - localmesh->ystart, localmesh->xend + 1 - xstart) = 0.5; - bcoef(y - localmesh->ystart, localmesh->xend + 1 - xstart) = 0.5; - } - } - - if (y_bndry == "dirichlet") { - // Dirichlet on Y boundaries - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int row = globalIndex(it.ind, localmesh->ystart - 1); - PetscScalar val = 0.5; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - int col = globalIndex(it.ind, localmesh->ystart); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int row = globalIndex(it.ind, localmesh->yend + 1); - PetscScalar val = 0.5; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - int col = globalIndex(it.ind, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } - } else if (y_bndry == "neumann") { - // Neumann on Y boundaries - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int row = globalIndex(it.ind, localmesh->ystart - 1); - PetscScalar val = 1.0; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -1.0; - int col = globalIndex(it.ind, localmesh->ystart); - - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int row = globalIndex(it.ind, localmesh->yend + 1); - PetscScalar val = 1.0; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -1.0; - int col = globalIndex(it.ind, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } - } else if (y_bndry == "free_o3") { - // 'free_o3' extrapolating boundary condition on Y boundaries - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int row = globalIndex(it.ind, localmesh->ystart - 1); - PetscScalar val = 1.0; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -3.0; - int col = globalIndex(it.ind, localmesh->ystart); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = 3.0; - col = globalIndex(it.ind, localmesh->ystart + 1); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = -1.0; - col = globalIndex(it.ind, localmesh->ystart + 2); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int row = globalIndex(it.ind, localmesh->yend + 1); - PetscScalar val = 1.0; - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -3.0; - int col = globalIndex(it.ind, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = 3.0; - col = globalIndex(it.ind, localmesh->yend - 1); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = -1.0; - col = globalIndex(it.ind, localmesh->yend - 2); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } - } else { - throw BoutException("Unsupported option for y_bndry"); - } - - if (not finite_volume) { - // Handle corner boundary cells in case we need to include D2DXDY - // Apply the y-boundary-condition to the cells in the x-boundary - this is an - // arbitrary choice, cf. connections around the X-point - - if (localmesh->hasBndryLowerY()) { - if (localmesh->firstX()) { - if (y_bndry == "neumann") { - // Neumann y-bc - // f(xs-1,ys-1) = f(xs-1,ys) - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -1.0; - int col = globalIndex(localmesh->xstart - 1, localmesh->ystart); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { - // 'free_o3' extrapolating boundary condition on Y boundaries - // f(xs-1,ys-1) = 3*f(xs-1,ys) - 3*f(xs-1,ys+1) + f(xs-1,ys+2) - // - // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know - // what value to pass for the corner - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -3.0; - int col = globalIndex(localmesh->xstart - 1, localmesh->ystart); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = 3.0; - col = globalIndex(localmesh->xstart - 1, localmesh->ystart + 1); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = -1.0; - col = globalIndex(localmesh->xstart - 1, localmesh->ystart + 2); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else { - throw BoutException("Unsupported option for y_bndry"); - } - } - if (localmesh->lastX()) { - if (y_bndry == "neumann") { - // Neumann y-bc - // f(xe+1,ys-1) = f(xe+1,ys) - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -1.0; - int col = globalIndex(localmesh->xend + 1, localmesh->ystart); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { - // 'free_o3' extrapolating boundary condition on Y boundaries - // f(xe+1,ys-1) = 3*f(xe+1,ys) - 3*f(xe+1,ys+1) + f(xe+1,ys+2) - // - // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know - // what value to pass for the corner - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -3.0; - int col = globalIndex(localmesh->xend + 1, localmesh->ystart); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = 3.0; - col = globalIndex(localmesh->xend + 1, localmesh->ystart + 1); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = -1.0; - col = globalIndex(localmesh->xend + 1, localmesh->ystart + 2); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else { - throw BoutException("Unsupported option for y_bndry"); - } - } - } - if (localmesh->hasBndryUpperY()) { - if (localmesh->firstX()) { - if (y_bndry == "neumann") { - // Neumann y-bc - // f(xs-1,ys-1) = f(xs-1,ys) - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -1.0; - int col = globalIndex(localmesh->xstart - 1, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { - // 'free_o3' extrapolating boundary condition on Y boundaries - // f(xs-1,ys-1) = 3*f(xs-1,ys) - 3*f(xs-1,ys+1) + f(xs-1,ys+2) - // - // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know - // what value to pass for the corner - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -3.0; - int col = globalIndex(localmesh->xstart - 1, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = 3.0; - col = globalIndex(localmesh->xstart - 1, localmesh->yend - 1); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = -1.0; - col = globalIndex(localmesh->xstart - 1, localmesh->yend - 2); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else { - throw BoutException("Unsupported option for y_bndry"); - } - } - if (localmesh->lastX()) { - if (y_bndry == "neumann") { - // Neumann y-bc - // f(xe+1,ys-1) = f(xe+1,ys) - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -1.0; - int col = globalIndex(localmesh->xend + 1, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else if (y_bndry == "free_o3" or y_bndry == "dirichlet") { - // 'free_o3' extrapolating boundary condition on Y boundaries - // f(xe+1,ys-1) = 3*f(xe+1,ys) - 3*f(xe+1,ys+1) + f(xe+1,ys+2) - // - // Use free_o3 at the corners for Dirichlet y-boundaries because we don't know - // what value to pass for the corner - PetscScalar val = 1.0; - int row = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - MatSetValues(MatA, 1, &row, 1, &row, &val, INSERT_VALUES); - - val = -3.0; - int col = globalIndex(localmesh->xend + 1, localmesh->yend); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = 3.0; - col = globalIndex(localmesh->xend + 1, localmesh->yend - 1); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - - val = -1.0; - col = globalIndex(localmesh->xend + 1, localmesh->yend - 2); - MatSetValues(MatA, 1, &row, 1, &col, &val, INSERT_VALUES); - } else { - throw BoutException("Unsupported option for y_bndry"); - } - } - } - } - - // Assemble Matrix - MatAssemblyBegin(MatA, MAT_FINAL_ASSEMBLY); - MatAssemblyEnd(MatA, MAT_FINAL_ASSEMBLY); - - // Set the operator -#if PETSC_VERSION_GE(3, 5, 0) - KSPSetOperators(ksp, MatA, MatA); -#else - KSPSetOperators(ksp, MatA, MatA, DIFFERENT_NONZERO_PATTERN); -#endif - - // Set coefficients for preconditioner - cr->setCoefs(acoef, bcoef, ccoef); -} - -void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D& A, const Field2D& B) { - ////////////////////////////////////////////////// - // Set Matrix elements - // - // (1/J) d/dx ( J * g11 d/dx ) + (1/J) d/dy ( J * g22 d/dy ) - - auto coords = localmesh->getCoordinates(location); - const Field2D J_DC = DC(coords->J); - const Field2D g11_DC = DC(coords->g11); - const Field2D dx_DC = DC(coords->dx); - const Field2D dy_DC = DC(coords->dy); - const Field2D g_22_DC = DC(coords->g_22); - const Field2D g_23_DC = DC(coords->g_23); - const Field2D g23_DC = DC(coords->g23); - - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - // stencil entries - PetscScalar c, xm, xp, ym, yp; - - // XX component - - // Metrics on x+1/2 boundary - BoutReal J = 0.5 * (J_DC(x, y) + J_DC(x + 1, y)); - BoutReal g11 = 0.5 * (g11_DC(x, y) + g11_DC(x + 1, y)); - BoutReal dx = 0.5 * (dx_DC(x, y) + dx_DC(x + 1, y)); - BoutReal Acoef = 0.5 * (A(x, y) + A(x + 1, y)); - - BoutReal val = Acoef * J * g11 / (J_DC(x, y) * dx * dx_DC(x, y)); - xp = val; - c = -val; - - // Metrics on x-1/2 boundary - J = 0.5 * (J_DC(x, y) + J_DC(x - 1, y)); - g11 = 0.5 * (g11_DC(x, y) + g11_DC(x - 1, y)); - dx = 0.5 * (dx_DC(x, y) + dx_DC(x - 1, y)); - Acoef = 0.5 * (A(x, y) + A(x - 1, y)); - - val = Acoef * J * g11 / (J_DC(x, y) * dx * dx_DC(x, y)); - xm = val; - c -= val; - - c += B(x, y); - - // Put values into the preconditioner, X derivatives only - acoef(y - localmesh->ystart, x - xstart) = xm; - bcoef(y - localmesh->ystart, x - xstart) = c; - ccoef(y - localmesh->ystart, x - xstart) = xp; - - if (include_y_derivs) { - // YY component - // Metrics at y+1/2 - J = 0.5 * (J_DC(x, y) + J_DC(x, y + 1)); - BoutReal g_22 = 0.5 * (g_22_DC(x, y) + g_22_DC(x, y + 1)); - BoutReal g23 = 0.5 * (g23_DC(x, y) + g23_DC(x, y + 1)); - BoutReal g_23 = 0.5 * (g_23_DC(x, y) + g_23_DC(x, y + 1)); - BoutReal dy = 0.5 * (dy_DC(x, y) + dy_DC(x, y + 1)); - Acoef = 0.5 * (A(x, y + 1) + A(x, y)); - - val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x, y) * dy * dy_DC(x, y)); - yp = val; - c -= val; - - // Metrics at y-1/2 - J = 0.5 * (J_DC(x, y) + J_DC(x, y - 1)); - g_22 = 0.5 * (g_22_DC(x, y) + g_22_DC(x, y - 1)); - g23 = 0.5 * (g23_DC(x, y) + g23_DC(x, y - 1)); - g_23 = 0.5 * (g_23_DC(x, y) + g_23_DC(x, y - 1)); - dy = 0.5 * (dy_DC(x, y) + dy_DC(x, y - 1)); - Acoef = 0.5 * (A(x, y - 1) + A(x, y)); - - val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x, y) * dy * dy_DC(x, y)); - ym = val; - c -= val; - } - - ///////////////////////////////////////////////// - // Now have a 5-point stencil for the Laplacian - - int row = globalIndex(x, y); - - // Set the centre (diagonal) - MatSetValues(MatA, 1, &row, 1, &row, &c, INSERT_VALUES); - - // X + 1 - int col = globalIndex(x + 1, y); - MatSetValues(MatA, 1, &row, 1, &col, &xp, INSERT_VALUES); - - // X - 1 - col = globalIndex(x - 1, y); - MatSetValues(MatA, 1, &row, 1, &col, &xm, INSERT_VALUES); - - if (include_y_derivs) { - // Y + 1 - col = globalIndex(x, y + 1); - MatSetValues(MatA, 1, &row, 1, &col, &yp, INSERT_VALUES); - - // Y - 1 - col = globalIndex(x, y - 1); - MatSetValues(MatA, 1, &row, 1, &col, &ym, INSERT_VALUES); - } - } - } -} - -void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D& A, const Field2D& B) { - ////////////////////////////////////////////////// - // Set Matrix elements - // - // Div(A Grad(f)) + B f - // = A Laplace_perp(f) + Grad_perp(A).Grad_perp(f) + B f - // = A*(G1*dfdx + (G2-1/J*d/dy(J/g_22))*dfdy - // + g11*d2fdx2 + (g22-1/g_22)*d2fdy2 + 2*g12*d2fdxdy) - // + g11*dAdx*dfdx + (g22-1/g_22)*dAdy*dfdy + g12*(dAdx*dfdy + dAdy*dfdx) - // + B*f - - auto coords = localmesh->getCoordinates(location); - const Field2D G1_2D = DC(coords->G1); - const Field2D G2_2D = DC(coords->G2); - const Field2D J_2D = DC(coords->J); - const Field2D g11_2D = DC(coords->g11); - const Field2D g_22_2D = DC(coords->g_22); - const Field2D g22_2D = DC(coords->g22); - const Field2D g12_2D = DC(coords->g12); - const Field2D d1_dx_2D = DC(coords->d1_dx); - const Field2D d1_dy_2D = DC(coords->d1_dy); - const Field2D dx_2D = DC(coords->dx); - const Field2D dy_2D = DC(coords->dy); - - const Field2D coef_dfdy = G2_2D - DC(DDY(J_2D / g_22_2D) / J_2D); - - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - // stencil entries - PetscScalar c, xm, xp, ym, yp, xpyp, xpym, xmyp, xmym; - - BoutReal dx = dx_2D(x, y); - - // A*G1*dfdx - BoutReal val = A(x, y) * G1_2D(x, y) / (2. * dx); - xp = val; - xm = -val; - - // A*g11*d2fdx2 - val = A(x, y) * g11_2D(x, y) / SQ(dx); - xp += val; - c = -2. * val; - xm += val; - // Non-uniform grid correction - val = A(x, y) * g11_2D(x, y) * d1_dx_2D(x, y) / (2. * dx); - xp += val; - xm -= val; - - // g11*dAdx*dfdx - val = g11_2D(x, y) * (A(x + 1, y) - A(x - 1, y)) / (4. * SQ(dx)); - xp += val; - xm -= val; - - // B*f - c += B(x, y); - - // Put values into the preconditioner, X derivatives only - acoef(y - localmesh->ystart, x - xstart) = xm; - bcoef(y - localmesh->ystart, x - xstart) = c; - ccoef(y - localmesh->ystart, x - xstart) = xp; - - if (include_y_derivs) { - BoutReal dy = dy_2D(x, y); - BoutReal dAdx = (A(x + 1, y) - A(x - 1, y)) / (2. * dx); - BoutReal dAdy = (A(x, y + 1) - A(x, y - 1)) / (2. * dy); - - // A*(G2-1/J*d/dy(J/g_22))*dfdy - val = A(x, y) * coef_dfdy(x, y) / (2. * dy); - yp = val; - ym = -val; - - // A*(g22-1/g_22)*d2fdy2 - val = A(x, y) * (g22_2D(x, y) - 1. / g_22_2D(x, y)) / SQ(dy); - yp += val; - c -= 2. * val; - ym += val; - // Non-uniform mesh correction - val = A(x, y) * (g22_2D(x, y) - 1. / g_22_2D(x, y)) * d1_dy_2D(x, y) / (2. * dy); - yp += val; - ym -= val; - - // 2*A*g12*d2dfdxdy - val = A(x, y) * g12_2D(x, y) / (2. * dx * dy); - xpyp = val; - xpym = -val; - xmyp = -val; - xmym = val; - - // g22*dAdy*dfdy - val = (g22_2D(x, y) - 1. / g_22_2D(x, y)) * dAdy / (2. * dy); - yp += val; - ym -= val; - - // g12*(dAdx*dfdy + dAdy*dfdx) - val = g12_2D(x, y) * dAdx / (2. * dy); - yp += val; - ym -= val; - val = g12_2D(x, y) * dAdy / (2. * dx); - xp += val; - xm -= val; - } - - ///////////////////////////////////////////////// - // Now have a 9-point stencil for the Laplacian - - int row = globalIndex(x, y); - - // Set the centre (diagonal) - MatSetValues(MatA, 1, &row, 1, &row, &c, INSERT_VALUES); - - // X + 1 - int col = globalIndex(x + 1, y); - MatSetValues(MatA, 1, &row, 1, &col, &xp, INSERT_VALUES); - - // X - 1 - col = globalIndex(x - 1, y); - MatSetValues(MatA, 1, &row, 1, &col, &xm, INSERT_VALUES); - - if (include_y_derivs) { - // Y + 1 - col = globalIndex(x, y + 1); - MatSetValues(MatA, 1, &row, 1, &col, &yp, INSERT_VALUES); - - // Y - 1 - col = globalIndex(x, y - 1); - MatSetValues(MatA, 1, &row, 1, &col, &ym, INSERT_VALUES); - - // X + 1, Y + 1 - col = globalIndex(x + 1, y + 1); - MatSetValues(MatA, 1, &row, 1, &col, &xpyp, INSERT_VALUES); - - // X + 1, Y - 1 - col = globalIndex(x + 1, y - 1); - MatSetValues(MatA, 1, &row, 1, &col, &xpym, INSERT_VALUES); - - // X - 1, Y + 1 - col = globalIndex(x - 1, y + 1); - MatSetValues(MatA, 1, &row, 1, &col, &xmyp, INSERT_VALUES); - - // X - 1, Y - 1 - col = globalIndex(x - 1, y - 1); - MatSetValues(MatA, 1, &row, 1, &col, &xmym, INSERT_VALUES); - } - } - } -} - -LaplaceXY::~LaplaceXY() { - PetscBool is_finalised; - PetscFinalized(&is_finalised); - - if (!is_finalised) { - // PetscFinalize may already have destroyed this object - KSPDestroy(&ksp); - } - - VecDestroy(&xs); - VecDestroy(&bs); - MatDestroy(&MatA); -} - -const Field2D LaplaceXY::solve(const Field2D& rhs, const Field2D& x0) { - Timer timer("invert"); - - ASSERT1(rhs.getMesh() == localmesh); - ASSERT1(x0.getMesh() == localmesh); - ASSERT1(rhs.getLocation() == location); - ASSERT1(x0.getLocation() == location); - - // Load initial guess x0 into xs and rhs into bs - - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(x, y); - - PetscScalar val = x0(x, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = rhs(x, y); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - - if (finite_volume) { - solveFiniteVolume(x0); - } else { - solveFiniteDifference(x0); - } - - // Assemble RHS Vector - VecAssemblyBegin(bs); - VecAssemblyEnd(bs); - - // Assemble Trial Solution Vector - VecAssemblyBegin(xs); - VecAssemblyEnd(xs); - - // Solve the system - KSPSolve(ksp, bs, xs); - - KSPConvergedReason reason; - KSPGetConvergedReason(ksp, &reason); - - if (reason <= 0) { - throw BoutException("LaplaceXY failed to converge. Reason {} ({:d})", - KSPConvergedReasons[reason], static_cast(reason)); - } - - if (save_performance) { - // Update performance monitoring information - n_calls++; - - int iterations = 0; - KSPGetIterationNumber(ksp, &iterations); - - average_iterations = BoutReal(n_calls - 1) / BoutReal(n_calls) * average_iterations - + BoutReal(iterations) / BoutReal(n_calls); - } - - ////////////////////////// - // Copy data into result - - Field2D result; - result.allocate(); - result.setLocation(location); - - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(x, y); - - PetscScalar val; - VecGetValues(xs, 1, &ind, &val); - result(x, y) = val; - } - } - - // Inner X boundary - if (localmesh->firstX()) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xstart - 1, y); - PetscScalar val; - VecGetValues(xs, 1, &ind, &val); - for (int x = localmesh->xstart - 1; x >= 0; x--) { - result(x, y) = val; - } - } - } - - // Outer X boundary - if (localmesh->lastX()) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xend + 1, y); - PetscScalar val; - VecGetValues(xs, 1, &ind, &val); - for (int x = localmesh->xend + 1; x < localmesh->LocalNx; x++) { - result(x, y) = val; - } - } - } - - // Lower Y boundary - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - if ( - // Should not go into corner cells, finite-volume LaplaceXY stencil does not include - // them - (finite_volume and (it.ind < localmesh->xstart or it.ind > localmesh->xend)) - - // Only go into first corner cell for finite-difference - or (it.ind < localmesh->xstart - 1 or it.ind > localmesh->xend + 1)) { - continue; - } - int ind = globalIndex(it.ind, localmesh->ystart - 1); - PetscScalar val; - VecGetValues(xs, 1, &ind, &val); - for (int y = localmesh->ystart - 1; y >= 0; y--) { - result(it.ind, y) = val; - } - } - - // Upper Y boundary - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - if ( - // Should not go into corner cells, finite-volume LaplaceXY stencil does not include - // them - (finite_volume and (it.ind < localmesh->xstart or it.ind > localmesh->xend)) - - // Only go into first corner cell for finite-difference - or (it.ind < localmesh->xstart - 1 or it.ind > localmesh->xend + 1)) { - continue; - } - int ind = globalIndex(it.ind, localmesh->yend + 1); - PetscScalar val; - VecGetValues(xs, 1, &ind, &val); - for (int y = localmesh->yend + 1; y < localmesh->LocalNy; y++) { - result(it.ind, y) = val; - } - } - - return result; -} - -void LaplaceXY::solveFiniteVolume(const Field2D& x0) { - // Use original LaplaceXY implementation of passing boundary values for backward - // compatibility - if (localmesh->firstX()) { - if (x_inner_dirichlet) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xstart - 1, y); - - PetscScalar val = x0(localmesh->xstart - 1, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.5 * (x0(localmesh->xstart - 1, y) + x0(localmesh->xstart, y)); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } else { - // Inner X boundary (Neumann) - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xstart - 1, y); - - PetscScalar val = x0(localmesh->xstart - 1, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.0; // x0(localmesh->xstart-1,y) - x0(localmesh->xstart,y); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - } - - // Outer X boundary (Dirichlet) - if (localmesh->lastX()) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xend + 1, y); - - PetscScalar val = x0(localmesh->xend + 1, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.5 * (x0(localmesh->xend, y) + x0(localmesh->xend + 1, y)); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - - if (y_bndry == "dirichlet") { - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->ystart - 1); - - PetscScalar val = x0(it.ind, localmesh->ystart - 1); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.5 * (x0(it.ind, localmesh->ystart - 1) + x0(it.ind, localmesh->ystart)); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->yend + 1); - - PetscScalar val = x0(it.ind, localmesh->yend + 1); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.5 * (x0(it.ind, localmesh->yend + 1) + x0(it.ind, localmesh->yend)); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } else if (y_bndry == "neumann" or y_bndry == "free_o3") { - // Y boundaries Neumann - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->ystart - 1); - - PetscScalar val = x0(it.ind, localmesh->ystart - 1); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->yend + 1); - - PetscScalar val = x0(it.ind, localmesh->yend + 1); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } else { - throw BoutException("Unsupported option for y_bndry"); - } -} - -void LaplaceXY::solveFiniteDifference(const Field2D& x0) { - // For finite-difference implementation pass boundary values in the same way as for - // the 'Laplacian' solvers - the value to use (for Dirichlet boundary conditions) on - // the boundary (which is half way between grid cell and boundary cell) is passed as - // the value in the first boundary cell. - if (localmesh->firstX()) { - if (x_inner_dirichlet) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xstart - 1, y); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 2. * x0(localmesh->xstart - 1, y) - x0(localmesh->xstart, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Pass the value from boundary cell of x0 as the boundary condition to the rhs - val = x0(localmesh->xstart - 1, y); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } else { - // Inner X boundary (Neumann) - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xstart - 1, y); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(localmesh->xstart, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - } - - // Outer X boundary (Dirichlet) - if (localmesh->lastX()) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - int ind = globalIndex(localmesh->xend + 1, y); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 2. * x0(localmesh->xend + 1, y) - x0(localmesh->xend, y); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Pass the value from boundary cell of x0 as the boundary condition to the rhs - val = x0(localmesh->xend + 1, y); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - - if (y_bndry == "dirichlet") { - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, they are treated specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = - 2. * x0(it.ind, localmesh->ystart - 1) - x0(it.ind, localmesh->ystart); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Pass the value from boundary cell of x0 as the boundary condition to the rhs - val = x0(it.ind, localmesh->ystart - 1); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, they are treated specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = - 2. * x0(it.ind, localmesh->yend + 1) - x0(it.ind, localmesh->yend); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Pass the value from boundary cell of x0 as the boundary condition to the rhs - val = x0(it.ind, localmesh->yend + 1); - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - - // Use free_o3 for the corner boundary cells - if (localmesh->hasBndryLowerY()) { - if (localmesh->firstX()) { - int ind = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->ystart) - - 3. * x0(localmesh->xstart - 1, localmesh->ystart + 1) - + x0(localmesh->xstart - 1, localmesh->ystart + 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->lastX()) { - int ind = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->ystart) - - 3. * x0(localmesh->xend + 1, localmesh->ystart + 1) - + x0(localmesh->xend + 1, localmesh->ystart + 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - if (localmesh->hasBndryUpperY()) { - if (localmesh->firstX()) { - int ind = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->yend) - - 3. * x0(localmesh->xstart - 1, localmesh->yend - 1) - + x0(localmesh->xstart - 1, localmesh->yend - 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->lastX()) { - int ind = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->yend) - - 3. * x0(localmesh->xend + 1, localmesh->yend - 1) - + x0(localmesh->xend + 1, localmesh->yend - 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - } else if (y_bndry == "neumann") { - // Y boundaries Neumann - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, they are treated specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(it.ind, localmesh->ystart); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->hasBndryLowerY()) { - if (localmesh->firstX()) { - int ind = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(localmesh->xstart - 1, localmesh->ystart); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->lastX()) { - int ind = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(localmesh->xend + 1, localmesh->ystart); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, they are treated specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(it.ind, localmesh->yend); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->hasBndryUpperY()) { - if (localmesh->firstX()) { - int ind = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(localmesh->xstart - 1, localmesh->yend); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->lastX()) { - int ind = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = x0(localmesh->xend + 1, localmesh->yend); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - } else if (y_bndry == "free_o3") { - // Y boundaries free_o3 - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, they are treated specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(it.ind, localmesh->ystart) - - 3. * x0(it.ind, localmesh->ystart + 1) - + x0(it.ind, localmesh->ystart + 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->hasBndryLowerY()) { - if (localmesh->firstX()) { - int ind = globalIndex(localmesh->xstart - 1, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->ystart) - - 3. * x0(localmesh->xstart - 1, localmesh->ystart + 1) - + x0(localmesh->xstart - 1, localmesh->ystart + 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->lastX()) { - int ind = globalIndex(localmesh->xend + 1, localmesh->ystart - 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->ystart) - - 3. * x0(localmesh->xend + 1, localmesh->ystart + 1) - + x0(localmesh->xend + 1, localmesh->ystart + 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, they are treated specially below - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - int ind = globalIndex(it.ind, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(it.ind, localmesh->yend) - - 3. * x0(it.ind, localmesh->yend - 1) - + x0(it.ind, localmesh->yend - 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->hasBndryUpperY()) { - if (localmesh->firstX()) { - int ind = globalIndex(localmesh->xstart - 1, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xstart - 1, localmesh->yend) - - 3. * x0(localmesh->xstart - 1, localmesh->yend - 1) - + x0(localmesh->xstart - 1, localmesh->yend - 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - if (localmesh->lastX()) { - int ind = globalIndex(localmesh->xend + 1, localmesh->yend + 1); - - // For the boundary value of the initial guess, use the value that would be set by - // applying the boundary condition to the initial guess - PetscScalar val = 3. * x0(localmesh->xend + 1, localmesh->yend) - - 3. * x0(localmesh->xend + 1, localmesh->yend - 1) - + x0(localmesh->xend + 1, localmesh->yend - 2); - VecSetValues(xs, 1, &ind, &val, INSERT_VALUES); - - // Set the value for the rhs of the boundary condition to zero - val = 0.0; - VecSetValues(bs, 1, &ind, &val, INSERT_VALUES); - } - } - } else { - throw BoutException("Unsupported option for y_bndry"); - } -} - -/*! Preconditioner - * NOTE: For generality, this routine does use globalIndex() in the inner loop, although - * this may be slightly less efficient than incrementing an integer for the global index, - * the finite-volume and finite-difference implementations have slightly different - * indexing patterns, so incrementing an integer would be tricky. - */ -int LaplaceXY::precon(Vec input, Vec result) { - - for (auto itdwn = localmesh->iterateBndryLowerY(); !itdwn.isDone(); itdwn++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (itdwn.ind < localmesh->xstart or itdwn.ind > localmesh->xend) { - continue; - } - const int ind = globalIndex(itdwn.ind, localmesh->ystart - 1); - PetscScalar val; - VecGetValues(input, 1, &ind, &val); - VecSetValues(result, 1, &ind, &val, INSERT_VALUES); - } - for (auto itup = localmesh->iterateBndryUpperY(); !itup.isDone(); itup++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (itup.ind < localmesh->xstart or itup.ind > localmesh->xend) { - continue; - } - const int ind = globalIndex(itup.ind, localmesh->yend + 1); - PetscScalar val; - VecGetValues(input, 1, &ind, &val); - VecSetValues(result, 1, &ind, &val, INSERT_VALUES); - } - - // Load vector x into bvals array - for (int x = xstart; x <= xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int ind = globalIndex(x, y); - PetscScalar val; - VecGetValues(input, 1, &ind, &val); - bvals(y - localmesh->ystart, x - xstart) = val; - } - } - - // Solve tridiagonal systems using CR solver - cr->solve(bvals, xvals); - - // Save result xvals into y array - for (int x = xstart; x <= xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - const int ind = globalIndex(x, y); - PetscScalar val = xvals(y - localmesh->ystart, x - xstart); - VecSetValues(result, 1, &ind, &val, INSERT_VALUES); - } - } - VecAssemblyBegin(result); - VecAssemblyEnd(result); - return 0; -} - -/////////////////////////////////////////////////////////////// - -int LaplaceXY::localSize() { - - // Bulk of points - const int nx = localmesh->xend - localmesh->xstart + 1; - const int ny = localmesh->yend - localmesh->ystart + 1; - - int n = nx * ny; - - // X boundaries - if (localmesh->firstX()) { - n += ny; - } - if (localmesh->lastX()) { - n += ny; - } - - // Y boundaries - for (RangeIterator it = localmesh->iterateBndryLowerY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - n++; - } - if ((not finite_volume) and localmesh->hasBndryLowerY()) { - if (localmesh->firstX()) { - n++; - } - if (localmesh->lastX()) { - n++; - } - } - for (RangeIterator it = localmesh->iterateBndryUpperY(); !it.isDone(); it++) { - // Should not go into corner cells, LaplaceXY stencil does not include them - if (it.ind < localmesh->xstart or it.ind > localmesh->xend) { - continue; - } - n++; - } - if ((not finite_volume) and localmesh->hasBndryUpperY()) { - if (localmesh->firstX()) { - n++; - } - if (localmesh->lastX()) { - n++; - } - } - - return n; -} - -int LaplaceXY::globalIndex(int x, int y) { - if ((x < 0) || (x >= localmesh->LocalNx) || (y < 0) || (y >= localmesh->LocalNy)) { - return -1; // Out of range - } - - // Get the index from a Field2D, round to integer - return static_cast(std::round(indexXY(x, y))); -} - -void LaplaceXY::savePerformance(Solver& solver, const std::string& name) { - // set flag so that performance monitoring values are calculated - save_performance = true; - - // add values to be saved to the output - if (not name.empty()) { - default_prefix = name; - } - - // add monitor to reset counters/averages for new output timestep - // monitor added to back of queue, so that values are reset after being saved - solver.addMonitor(&monitor, Solver::BACK); -} - -int LaplaceXY::LaplaceXYMonitor::call(Solver* /*solver*/, BoutReal /*time*/, int /*iter*/, - int /*nout*/) { - laplacexy.output_average_iterations = laplacexy.average_iterations; - - laplacexy.n_calls = 0; - laplacexy.average_iterations = 0.; - - return 0; -} - -void LaplaceXY::LaplaceXYMonitor::outputVars(Options& output_options, - const std::string& time_dimension) { - output_options[fmt::format("{}_average_iterations", laplacexy.default_prefix)] - .assignRepeat(laplacexy.output_average_iterations, time_dimension); -} - -#endif // BOUT_HAS_PETSC +// DO NOT REMOVE: ensures linker keeps all symbols in this TU +void LaplaceXYFactory::ensureRegistered() {} diff --git a/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx b/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx index 8408f08c00..55c4a383b3 100644 --- a/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx @@ -34,7 +34,7 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); - LaplaceXY laplacexy; + auto laplacexy = LaplaceXY::create(); // Solving equations of the form // Div(A Grad_perp(f)) + B*f = rhs @@ -57,9 +57,9 @@ int main(int argc, char** argv) { Field2D rhs, rhs_check; rhs = Laplace_perpXY(a, f) + b * f; - laplacexy.setCoefs(a, b); + laplacexy->setCoefs(a, b); - sol = laplacexy.solve(rhs, 0.); + sol = laplacexy->solve(rhs, 0.); error = (f - sol) / f; absolute_error = f - sol; max_error = max(abs(absolute_error), true); diff --git a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx index 3486760810..fa67079861 100644 --- a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx @@ -35,20 +35,20 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); using bout::globals::mesh; - auto coords = mesh->getCoordinates(); + auto* coords = mesh->getCoordinates(); auto& opt = Options::root(); - LaplaceXY laplacexy; + auto laplacexy = LaplaceXY::create(); bool include_y_derivs = opt["laplacexy"]["include_y_derivs"]; // Solving equations of the form // Div(A Grad_perp(f)) + B*f = rhs // A*Laplace_perp(f) + Grad_perp(A).Grad_perp(f) + B*f = rhs - Field2D f, a, b, sol; - Field2D error, absolute_error; //Absolute value of relative error: abs((f - sol)/f) - BoutReal max_error; //Output of test + Field2D f; + Field2D a; + Field2D b; initial_profile("f", f); initial_profile("a", a); @@ -61,7 +61,8 @@ int main(int argc, char** argv) { //////////////////////////////////////////////////////////////////////////////////////// - Field2D rhs, rhs_check; + Field2D rhs; + Field2D rhs_check; if (include_y_derivs) { rhs = a * DC(Laplace_perp(f)) + DC(Grad_perp(a) * Grad_perp(f)) + b * f; } else { @@ -69,14 +70,14 @@ int main(int argc, char** argv) { a * DC(Delp2(f, CELL_DEFAULT, false)) + DC(coords->g11 * DDX(a) * DDX(f)) + b * f; } - laplacexy.setCoefs(a, b); + laplacexy->setCoefs(a, b); - sol = laplacexy.solve(rhs, 0.); - error = (f - sol) / f; - absolute_error = f - sol; - max_error = max(abs(absolute_error), true); + auto sol = laplacexy->solve(rhs, 0.); + const auto error = (f - sol) / f; + const auto absolute_error = f - sol; + const auto max_error = max(abs(absolute_error), true); - output << "Magnitude of maximum absolute error is " << max_error << endl; + output.write("Magnitude of maximum absolute error is {}\n", max_error); mesh->communicate(sol); if (include_y_derivs) { diff --git a/tests/integrated/test-laplacexy/test-laplacexy.cxx b/tests/integrated/test-laplacexy/test-laplacexy.cxx index 3142d359b1..d7b0a55ec8 100644 --- a/tests/integrated/test-laplacexy/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy/test-laplacexy.cxx @@ -64,10 +64,10 @@ int main(int argc, char** argv) { rhs = a * Delp2(f, CELL_DEFAULT, false) + coords->g11 * DDX(a) * DDX(f) + b * f; } - LaplaceXY laplacexy; - laplacexy.setCoefs(a, b); + auto laplacexy = LaplaceXY::create(); + laplacexy->setCoefs(a, b); - Field2D solution = laplacexy.solve(rhs, 0.); + Field2D solution = laplacexy->solve(rhs, 0.); Field2D relative_error = (f - solution) / f; Field2D absolute_error = f - solution; BoutReal max_error = max(abs(absolute_error), true); diff --git a/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx b/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx index 2fb8a10777..7b7ac97517 100644 --- a/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx @@ -27,14 +27,14 @@ #include #include #include -#include +#include #include int main(int argc, char** argv) { BoutInitialise(argc, argv); - LaplaceXY2Hypre laplacexy; + auto laplacexy = LaplaceXYFactory::getInstance().create("hypre", nullptr); // Solving equations of the form // Div(A Grad_perp(f)) + B*f = rhs @@ -54,10 +54,10 @@ int main(int argc, char** argv) { Field2D rhs = Laplace_perpXY(a, f) + b * f; - laplacexy.setCoefs(a, b); + laplacexy->setCoefs(a, b); Field2D guess = 0.0; - Field2D sol = laplacexy.solve(rhs, guess); + Field2D sol = laplacexy->solve(rhs, guess); Field2D error = (f - sol) / f; // Absolute value of relative error: abs((f - sol)/f) Field2D absolute_error = abs(f - sol); From 96c86b85cd4f50bc640bfe5c14f6f026bae62e90 Mon Sep 17 00:00:00 2001 From: ZedThree <1486942+ZedThree@users.noreply.github.com> Date: Thu, 23 Oct 2025 17:22:49 +0000 Subject: [PATCH 225/259] Apply clang-format changes --- src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx index 950fcc4f8e..163b5049ee 100644 --- a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx +++ b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx @@ -12,10 +12,8 @@ #include "bout/sys/timer.hxx" #if BOUT_HAS_CUDA && defined(__CUDACC__) -#define gpuErrchk(ans) \ - { \ - gpuAssert((ans), __FILE__, __LINE__); \ - } +#define gpuErrchk(ans) \ + { gpuAssert((ans), __FILE__, __LINE__); } inline void gpuAssert(cudaError_t code, const char* file, int line, bool abort = true) { if (code != cudaSuccess) { fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); From 84a684b1887ddb3237e7cc841b66647a690a2a20 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 09:22:17 +0100 Subject: [PATCH 226/259] Fix typo in define --- src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx index 3950725a89..32e9c05ab1 100644 --- a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx +++ b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx @@ -36,14 +36,14 @@ #include "bout/build_defines.hxx" #include "bout/invert/laplacexy.hxx" -#if !BOUT_HAS_PETSC +#if !BOUT_HAS_HYPRE namespace { RegisterUnavailableLaplaceXY registerlaplacexyhypre("hypre", "BOUT++ was not configured with HYPRE"); } -#else // BOUT_HAS_PETSC +#else // BOUT_HAS_HYPRE class Mesh; From 84d540662d08343c522f0eb06d3fd2c55f633b2d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 13:35:04 +0100 Subject: [PATCH 227/259] Remove private variables from base class --- include/bout/invert/laplacexy.hxx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/bout/invert/laplacexy.hxx b/include/bout/invert/laplacexy.hxx index 7ec6901cee..0cdd5e751a 100644 --- a/include/bout/invert/laplacexy.hxx +++ b/include/bout/invert/laplacexy.hxx @@ -67,9 +67,7 @@ using RegisterUnavailableLaplaceXY = LaplaceXYFactory::RegisterUnavailableInFact class LaplaceXY { public: - LaplaceXY(Mesh* m = nullptr, [[maybe_unused]] Options* options = nullptr, - const CELL_LOC loc = CELL_CENTRE) - : localmesh(m == nullptr ? bout::globals::mesh : m), location(loc) {} + LaplaceXY() = default; LaplaceXY(const LaplaceXY&) = default; LaplaceXY(LaplaceXY&&) = delete; LaplaceXY& operator=(const LaplaceXY&) = default; @@ -90,9 +88,6 @@ protected: static const int INVERT_AC_GRAD = 2; // Use zero neumann (NOTE: AC is a misnomer) static const int INVERT_SET = 16; // Set boundary to x0 value static const int INVERT_RHS = 32; // Set boundary to b value -private: - Mesh* localmesh; ///< The mesh this operates on, provides metrics and communication - CELL_LOC location; }; #endif // BOUT_LAPLACEXY_H From 7c7acad3522122b01f8eaa605350c72b07eae587 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 16:46:02 +0100 Subject: [PATCH 228/259] Try to appease clang-tidy `misc-include-cleaner` --- include/bout/invert/laplacexy.hxx | 5 +++- .../laplacexy/impls/hypre/laplacexy-hypre.cxx | 11 +++++++++ .../laplacexy/impls/hypre/laplacexy-hypre.hxx | 5 +++- .../laplacexy/impls/petsc/laplacexy-petsc.cxx | 24 ++++++++++++------- .../laplacexy/impls/petsc/laplacexy-petsc.hxx | 13 ++++++---- .../impls/petsc2/laplacexy-petsc2.cxx | 21 +++++++++++----- .../impls/petsc2/laplacexy-petsc2.hxx | 10 ++++---- .../test-laplacexy-fv/test-laplacexy.cxx | 17 ++++++++----- .../test-laplacexy-short/test-laplacexy.cxx | 10 +++++++- .../test-laplacexy/test-laplacexy.cxx | 10 +++++++- .../test-laplacexy2-hypre/test-laplacexy.cxx | 9 +++++-- 11 files changed, 101 insertions(+), 34 deletions(-) diff --git a/include/bout/invert/laplacexy.hxx b/include/bout/invert/laplacexy.hxx index 0cdd5e751a..51605b9db5 100644 --- a/include/bout/invert/laplacexy.hxx +++ b/include/bout/invert/laplacexy.hxx @@ -33,12 +33,15 @@ #ifndef BOUT_LAPLACEXY_H #define BOUT_LAPLACEXY_H +#include #include #include #include -#include + +#include class LaplaceXY; +class Options; class Solver; class LaplaceXYFactory diff --git a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx index 163b5049ee..9323513f21 100644 --- a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx +++ b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.cxx @@ -5,12 +5,23 @@ #include "laplacexy-hypre.hxx" #include "bout/assert.hxx" +#include "bout/bout_types.hxx" #include "bout/boutcomm.hxx" +#include "bout/coordinates.hxx" +#include "bout/field2d.hxx" +#include "bout/globalindexer.hxx" #include "bout/globals.hxx" #include "bout/mesh.hxx" +#include "bout/operatorstencil.hxx" +#include "bout/options.hxx" #include "bout/output.hxx" +#include "bout/region.hxx" +#include "bout/sys/range.hxx" #include "bout/sys/timer.hxx" +#include +#include + #if BOUT_HAS_CUDA && defined(__CUDACC__) #define gpuErrchk(ans) \ { gpuAssert((ans), __FILE__, __LINE__); } diff --git a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx index 32e9c05ab1..f415f9ebf4 100644 --- a/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx +++ b/src/invert/laplacexy/impls/hypre/laplacexy-hypre.hxx @@ -47,7 +47,10 @@ RegisterUnavailableLaplaceXY class Mesh; -#include +#include "bout/bout_types.hxx" +#include "bout/field2d.hxx" +#include "bout/globalindexer.hxx" +#include "bout/hypre_interface.hxx" class LaplaceXY2Hypre : public LaplaceXY { public: diff --git a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx index e80a2ca640..3d7f707678 100644 --- a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx +++ b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx @@ -4,14 +4,22 @@ #include "laplacexy-petsc.hxx" -#include -#include -#include -#include -#include -#include -#include - +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutcomm.hxx" +#include "bout/boutexception.hxx" +#include "bout/cyclic_reduction.hxx" +#include "bout/derivs.hxx" +#include "bout/field2d.hxx" +#include "bout/globals.hxx" +#include "bout/options.hxx" +#include "bout/petsclib.hxx" +#include "bout/sys/range.hxx" +#include "bout/solver.hxx" +#include "bout/sys/timer.hxx" +#include "bout/utils.hxx" + +#include #include #include diff --git a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx index 1db812a19d..27d25cf9a7 100644 --- a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx +++ b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.hxx @@ -45,11 +45,16 @@ RegisterUnavailableLaplaceXY #else // BOUT_HAS_PETSC -#include "bout/solver.hxx" +#include "bout/bout_types.hxx" +#include "bout/cyclic_reduction.hxx" +#include "bout/field2d.hxx" +#include "bout/mesh.hxx" +#include "bout/monitor.hxx" +#include "bout/petsclib.hxx" #include "bout/utils.hxx" -#include -#include -#include + +#include +#include class Options; class Solver; diff --git a/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx index ae2cc8313a..63fc8d6f91 100644 --- a/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx +++ b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx @@ -4,12 +4,21 @@ #include "laplacexy-petsc2.hxx" -#include -#include -#include -#include -#include -#include +#include "bout/assert.hxx" +#include "bout/bout_types.hxx" +#include "bout/boutcomm.hxx" +#include "bout/coordinates.hxx" +#include "bout/field2d.hxx" +#include "bout/globalindexer.hxx" +#include "bout/globals.hxx" +#include "bout/operatorstencil.hxx" +#include "bout/options.hxx" +#include "bout/petsc_interface.hxx" +#include "bout/region.hxx" +#include "bout/sys/range.hxx" +#include "bout/sys/timer.hxx" + +#include #include diff --git a/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx index 1480f366fe..eb1be636f2 100644 --- a/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx +++ b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.hxx @@ -50,10 +50,12 @@ RegisterUnavailableLaplaceXY #else // BOUT_HAS_PETSC -#include -#include -#include -#include +#include "bout/bout_types.hxx" +#include "bout/field2d.hxx" +#include "bout/globalindexer.hxx" +#include "bout/mesh.hxx" +#include "bout/petsc_interface.hxx" +#include "bout/petsclib.hxx" class LaplaceXYpetsc2 : public LaplaceXY { public: diff --git a/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx b/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx index 55c4a383b3..be2f993b31 100644 --- a/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy-fv/test-laplacexy.cxx @@ -23,12 +23,17 @@ * **************************************************************************/ -#include -#include -#include -#include -#include -#include +#include "bout/bout.hxx" +#include "bout/bout_types.hxx" +#include "bout/difops.hxx" +#include "bout/field2d.hxx" +#include "bout/initialprofiles.hxx" +#include "bout/invert/laplacexy.hxx" +#include "bout/options.hxx" +#include "bout/options_io.hxx" +#include "bout/output.hxx" + +#include int main(int argc, char** argv) { diff --git a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx index fa67079861..7c284290b3 100644 --- a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx @@ -24,11 +24,19 @@ **************************************************************************/ #include -#include +#include #include +#include +#include +#include #include #include #include +#include +#include +#include + +#include int main(int argc, char** argv) { diff --git a/tests/integrated/test-laplacexy/test-laplacexy.cxx b/tests/integrated/test-laplacexy/test-laplacexy.cxx index d7b0a55ec8..543274d37d 100644 --- a/tests/integrated/test-laplacexy/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy/test-laplacexy.cxx @@ -24,11 +24,19 @@ **************************************************************************/ #include -#include +#include #include +#include +#include +#include #include #include #include +#include +#include +#include + +#include using bout::globals::mesh; diff --git a/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx b/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx index 7b7ac97517..cede14b1f8 100644 --- a/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx @@ -23,13 +23,18 @@ * **************************************************************************/ +#include +#include +#include +#include +#include #include -#include -#include #include #include #include +#include + int main(int argc, char** argv) { BoutInitialise(argc, argv); From 8fa9f2c054af40c63228f706e9078a55030b6198 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 17:21:22 +0100 Subject: [PATCH 229/259] CI: Don't warn about including PETSc or MPI symbols directly --- .clang-tidy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.clang-tidy b/.clang-tidy index 556b8738f8..4caf530aee 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,6 +9,9 @@ CheckOptions: # otherwise this breaks `ASSERT` macros! - key: readability-simplify-boolean-expr.IgnoreMacros value: 'true' + + - key: misc-include-cleaner.IgnoreHeaders + value: 'petsc.*\.h;mpi\.h' --- Disabled checks and reasons: From 2cb22807dc4ffc9e9bfada5a31777335ce44591d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 17:21:42 +0100 Subject: [PATCH 230/259] Fix call to virtual function in ctor --- src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx index 63fc8d6f91..01019466a8 100644 --- a/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx +++ b/src/invert/laplacexy/impls/petsc2/laplacexy-petsc2.cxx @@ -128,7 +128,7 @@ LaplaceXYpetsc2::LaplaceXYpetsc2(Mesh* m, Options* opt, const CELL_LOC loc) Field2D zero(0., localmesh); one.setLocation(location); zero.setLocation(location); - setCoefs(one, zero); + LaplaceXYpetsc2::setCoefs(one, zero); } void LaplaceXYpetsc2::setCoefs(const Field2D& A, const Field2D& B) { From b497f8969ca1f1eb6bdd95a22e346b6c756be6c9 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 17:56:43 +0100 Subject: [PATCH 231/259] Update examples for LaplaceXY factory --- examples/CMakeLists.txt | 1 - examples/dalf3/dalf3.cxx | 2 +- .../elm-pb-outerloop/elm_pb_outerloop.cxx | 39 ++++++++----------- examples/elm-pb/elm_pb.cxx | 19 +++------ examples/laplacexy/alfven-wave/alfven.cxx | 7 ++-- examples/laplacexy/laplace_perp/test.cxx | 4 +- examples/laplacexy/simple-hypre/.gitignore | 1 - .../laplacexy/simple-hypre/CMakeLists.txt | 15 ------- examples/laplacexy/simple-hypre/data/BOUT.inp | 37 ------------------ .../simple-hypre/test-laplacexy-hypre.cxx | 30 -------------- examples/laplacexy/simple/CMakeLists.txt | 5 ++- examples/laplacexy/simple/README.md | 7 +++- examples/laplacexy/simple/hypre/BOUT.inp | 23 +++++++++++ examples/laplacexy/simple/test-laplacexy.cxx | 8 ++-- 14 files changed, 65 insertions(+), 133 deletions(-) delete mode 100644 examples/laplacexy/simple-hypre/.gitignore delete mode 100644 examples/laplacexy/simple-hypre/CMakeLists.txt delete mode 100644 examples/laplacexy/simple-hypre/data/BOUT.inp delete mode 100644 examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx create mode 100644 examples/laplacexy/simple/hypre/BOUT.inp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 849f10e85f..f2444e6bf6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -30,7 +30,6 @@ add_subdirectory(invertable_operator) add_subdirectory(laplacexy/alfven-wave) add_subdirectory(laplacexy/laplace_perp) add_subdirectory(laplacexy/simple) -add_subdirectory(laplacexy/simple-hypre) add_subdirectory(monitor-newapi) add_subdirectory(orszag-tang) add_subdirectory(preconditioning/wave) diff --git a/examples/dalf3/dalf3.cxx b/examples/dalf3/dalf3.cxx index 493e8f5e45..46a9a4286d 100644 --- a/examples/dalf3/dalf3.cxx +++ b/examples/dalf3/dalf3.cxx @@ -300,7 +300,7 @@ class DALF3 : public PhysicsModel { // LaplaceXY for n=0 solve if (split_n0) { // Create an XY solver for n=0 component - laplacexy = std::make_unique(mesh); + laplacexy = LaplaceXY::create(mesh); phi2D = 0.0; // Starting guess } diff --git a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx index 8e84901806..e48a1020ca 100644 --- a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx +++ b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx @@ -28,33 +28,28 @@ /*******************************************************************************/ +#include "bout/build_defines.hxx" +#include "bout/options.hxx" #include #include #include +#include +#include #include #include #include #include +#include #include #include -#include -#include - -#include - -#include -#include #include +#include // Defines BOUT_FOR_RAJA #include #include +#include +#include -#include // Defines BOUT_FOR_RAJA - -#if BOUT_HAS_HYPRE -#include -#endif - -#include +#include CELL_LOC loc = CELL_CENTRE; @@ -91,6 +86,10 @@ BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_target", "neumann"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xin", "none"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xout", "none"); +#if BOUT_HAS_HYPRE +BOUT_OVERRIDE_DEFAULT_OPTION("laplacexy:type", "hypre"); +#endif + /// 3-field ELM simulation class ELMpb : public PhysicsModel { private: @@ -242,11 +241,7 @@ class ELMpb : public PhysicsModel { bool split_n0; // Solve the n=0 component of potential -#if BOUT_HAS_HYPRE - std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#else std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#endif Field2D phi2D; // Axisymmetric phi @@ -567,13 +562,11 @@ class ELMpb : public PhysicsModel { split_n0 = options["split_n0"] .doc("Solve zonal (n=0) component of potential using LaplaceXY?") .withDefault(false); + if (split_n0) { // Create an XY solver for n=0 component -#if BOUT_HAS_HYPRE - laplacexy = bout::utils::make_unique(mesh); -#else - laplacexy = bout::utils::make_unique(mesh); -#endif + laplacexy = LaplaceXY::create(mesh); + // Set coefficients for Boussinesq solve laplacexy->setCoefs(1.0, 0.0); phi2D = 0.0; // Starting guess diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index d981796200..fe18a756ae 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -22,10 +22,6 @@ #include -#if BOUT_HAS_HYPRE -#include -#endif - #include CELL_LOC loc = CELL_CENTRE; @@ -36,6 +32,10 @@ BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_target", "neumann"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xin", "none"); BOUT_OVERRIDE_DEFAULT_OPTION("phi:bndry_xout", "none"); +#if BOUT_HAS_HYPRE +BOUT_OVERRIDE_DEFAULT_OPTION("laplacexy:type", "hypre"); +#endif + /// 3-field ELM simulation class ELMpb : public PhysicsModel { private: @@ -188,11 +188,7 @@ class ELMpb : public PhysicsModel { bool split_n0; // Solve the n=0 component of potential -#if BOUT_HAS_HYPRE - std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#else std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) -#endif Field2D phi2D; // Axisymmetric phi @@ -525,11 +521,8 @@ class ELMpb : public PhysicsModel { .withDefault(false); if (split_n0) { // Create an XY solver for n=0 component -#if BOUT_HAS_HYPRE - laplacexy = bout::utils::make_unique(mesh); -#else - laplacexy = bout::utils::make_unique(mesh); -#endif + laplacexy = LaplaceXY::create(mesh); + // Set coefficients for Boussinesq solve laplacexy->setCoefs(1.0, 0.0); phi2D = 0.0; // Starting guess diff --git a/examples/laplacexy/alfven-wave/alfven.cxx b/examples/laplacexy/alfven-wave/alfven.cxx index a4248afcf7..031931c1c4 100644 --- a/examples/laplacexy/alfven-wave/alfven.cxx +++ b/examples/laplacexy/alfven-wave/alfven.cxx @@ -1,10 +1,11 @@ - #include #include #include #include #include +#include + /// Fundamental constants const BoutReal PI = 3.14159265; const BoutReal e0 = 8.854e-12; // Permittivity of free space @@ -32,7 +33,7 @@ class Alfven : public PhysicsModel { bool laplace_perp; // Use Laplace_perp or Delp2? bool split_n0; // Split solve into n=0 and n~=0? - LaplaceXY* laplacexy; // Laplacian solver in X-Y (n=0) + std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) bool newXZsolver; std::unique_ptr phiSolver; // Old Laplacian in X-Z @@ -80,7 +81,7 @@ class Alfven : public PhysicsModel { if (split_n0) { // Create an XY solver for n=0 component - laplacexy = new LaplaceXY(mesh); + laplacexy = LaplaceXY::create(mesh); phi2D = 0.0; // Starting guess } diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index 75577bb8b7..e3d9528d45 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -56,10 +56,10 @@ int main(int argc, char** argv) { FieldFactory::get()->create2D("input_field", Options::getRoot(), mesh); // Create a LaplaceXY solver - LaplaceXY laplacexy{mesh}; + auto laplacexy = LaplaceXY::create(mesh); // Solve, using 0.0 as starting guess - Field2D solved = laplacexy.solve(input, 0.0); + Field2D solved = laplacexy->solve(input, 0.0); // Need to communicate guard cells mesh->communicate(solved); diff --git a/examples/laplacexy/simple-hypre/.gitignore b/examples/laplacexy/simple-hypre/.gitignore deleted file mode 100644 index eeede075f9..0000000000 --- a/examples/laplacexy/simple-hypre/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test-laplacexy diff --git a/examples/laplacexy/simple-hypre/CMakeLists.txt b/examples/laplacexy/simple-hypre/CMakeLists.txt deleted file mode 100644 index 788ebb1776..0000000000 --- a/examples/laplacexy/simple-hypre/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(test_laplacexy_hypre LANGUAGES CXX C) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(test_laplacexy_hypre - SOURCES test-laplacexy-hypre.cxx - REQUIRES BOUT_HAS_HYPRE) - -if(BOUT_HAS_CUDA) - set_source_files_properties(test-laplacexy-hypre.cxx PROPERTIES LANGUAGE CUDA ) -endif() diff --git a/examples/laplacexy/simple-hypre/data/BOUT.inp b/examples/laplacexy/simple-hypre/data/BOUT.inp deleted file mode 100644 index 5da492168d..0000000000 --- a/examples/laplacexy/simple-hypre/data/BOUT.inp +++ /dev/null @@ -1,37 +0,0 @@ -# -# Simple test of the LaplaceXY solver. -# -# Inverts a given function (rhs), writing "rhs" and solution "x" to file -# - -[mesh] - -# Mesh sizes -nx = 20 -ny = 32 -nz = 1 - -# mesh spacing -dx = 1.0 -dy = 1.0 -dz = 1.0 - -[laplacexy] - -ksptype = gmres # Iterative solver type - not used with Hypre interface -pctype = jacobi # Preconditioner. "jacobi", "bjacobi" and "sor" usually good -# On one processor"lu" uses direct solver - -atol = 1e-12 # type: BoutReal, doc: Relative tolerance for Hypre solver -core_bndry_dirichlet = false # type: bool -hypre_print_level = 3 # type: int, doc: Verbosity for Hypre solver. Integer from 0 (silent) to 4 (most verbose). -#hypre_solver_type = gmres # type: HYPRE_SOLVER_TYPE, doc: Type of solver to use when solving Hypre system. Possible values are: gmres, bicgstab -hypre_solver_type = bicgstab # type: HYPRE_SOLVER_TYPE, doc: Type of solver to use when solving Hypre system. Possible values are: gmres, bicgstab -include_y_derivs = true # type: bool, doc: Include Y derivatives in operator to invert? -maxits = 2000 # type: int, doc: Maximum iterations for Hypre solver -print_timing = true # type: bool, doc: Print extra timing information for LaplaceXY2Hypre -rtol = 1e-07 # type: BoutReal, doc: Relative tolerance for Hypre solver -y_bndry_dirichlet = false # type: bool - -# Function to be inverted -rhs = sin(2*pi*x)*sin(y) diff --git a/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx b/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx deleted file mode 100644 index af2367e1a0..0000000000 --- a/examples/laplacexy/simple-hypre/test-laplacexy-hypre.cxx +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -int main(int argc, char** argv) { - BoutInitialise(argc, argv); - { - /// Create a LaplaceXY object - LaplaceXY2Hypre laplacexy(bout::globals::mesh); - - /// Generate rhs function - Field2D rhs = FieldFactory::get()->create2D("laplacexy:rhs", Options::getRoot(), - bout::globals::mesh); - - /// Solution - Field2D solution = 0.0; - - solution = laplacexy.solve(rhs, solution); - - Options dump; - dump["rhs"] = rhs; - dump["x"] = solution; - bout::writeDefaultOutputFile(dump); - } - BoutFinalise(); -#if BOUT_HAS_CUDA - cudaDeviceReset(); -#endif - return 0; -} diff --git a/examples/laplacexy/simple/CMakeLists.txt b/examples/laplacexy/simple/CMakeLists.txt index ec5e7d2492..7859a08259 100644 --- a/examples/laplacexy/simple/CMakeLists.txt +++ b/examples/laplacexy/simple/CMakeLists.txt @@ -6,4 +6,7 @@ if (NOT TARGET bout++::bout++) find_package(bout++ REQUIRED) endif() -bout_add_example(laplacexy-simple SOURCES test-laplacexy.cxx) +bout_add_example(laplacexy-simple + SOURCES test-laplacexy.cxx + DATA_DIRS data hypre +) diff --git a/examples/laplacexy/simple/README.md b/examples/laplacexy/simple/README.md index ce7cbebf00..491d00d4b3 100644 --- a/examples/laplacexy/simple/README.md +++ b/examples/laplacexy/simple/README.md @@ -8,7 +8,7 @@ and preconditioners. See the "ksptype" and "pctype" settings in BOUT.inp Run with - $ ./test-laplacexy -ksp_monitor + $ ./test-laplacexy -laplacexy:petsc:ksp_monitor which should print the KSP norms from PETSc: @@ -31,3 +31,8 @@ which should print the KSP norms from PETSc: 16 KSP Residual norm 4.309526296050e-01 17 KSP Residual norm 1.115269396077e-01 18 KSP Residual norm 4.334487475743e-13 + +HYPRE +----- + +Use the `hypre` directory to use the HYPRE preconditioner instead of PETSc. diff --git a/examples/laplacexy/simple/hypre/BOUT.inp b/examples/laplacexy/simple/hypre/BOUT.inp new file mode 100644 index 0000000000..338e902d4e --- /dev/null +++ b/examples/laplacexy/simple/hypre/BOUT.inp @@ -0,0 +1,23 @@ +# +# Simple test of the LaplaceXY solver using HYPRE +# +# Inverts a given function (rhs), writing "rhs" and solution "x" to file +# + +[mesh] + +# Mesh sizes +nx = 20 +ny = 32 +nz = 1 + +# mesh spacing +dx = 1.0 +dy = 1.0 +dz = 1.0 + +[laplacexy] +type = hypre + +# Function to be inverted +rhs = sin(2*pi*x)*sin(y) diff --git a/examples/laplacexy/simple/test-laplacexy.cxx b/examples/laplacexy/simple/test-laplacexy.cxx index c033eb68e3..49a93aafdb 100644 --- a/examples/laplacexy/simple/test-laplacexy.cxx +++ b/examples/laplacexy/simple/test-laplacexy.cxx @@ -7,20 +7,18 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); /// Create a LaplaceXY object - LaplaceXY laplacexy(bout::globals::mesh); + auto laplacexy = LaplaceXY::create(bout::globals::mesh); /// Generate rhs function Field2D rhs = FieldFactory::get()->create2D("laplacexy:rhs", Options::getRoot(), bout::globals::mesh); /// Solution - Field2D x = 0.0; - - x = laplacexy.solve(rhs, x); + Field2D result = laplacexy->solve(rhs, 0.0); Options dump; dump["rhs"] = rhs; - dump["x"] = x; + dump["result"] = result; bout::writeDefaultOutputFile(dump); BoutFinalise(); From fbe8a7f909a2c33578e1b84520be66688d148d48 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 24 Oct 2025 18:07:06 +0100 Subject: [PATCH 232/259] Add `has_hypre` to python `boutconfig` --- tools/pylib/boutconfig/__init__.py.cin | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pylib/boutconfig/__init__.py.cin b/tools/pylib/boutconfig/__init__.py.cin index d031d599b5..b65b25a75a 100644 --- a/tools/pylib/boutconfig/__init__.py.cin +++ b/tools/pylib/boutconfig/__init__.py.cin @@ -31,6 +31,7 @@ config = { "has_fftw": "@BOUT_HAS_FFTW@", "petsc_has_sundials": "@PETSC_HAS_SUNDIALS@", "metric_type": "@BOUT_METRIC_TYPE@", + "has_hypre": "@BOUT_HAS_HYPRE@", } for k, v in config.items(): From d1ae6b74e791e092ad27328a7e029103d579b793 Mon Sep 17 00:00:00 2001 From: ZedThree <1486942+ZedThree@users.noreply.github.com> Date: Fri, 24 Oct 2025 17:12:46 +0000 Subject: [PATCH 233/259] Apply clang-format changes --- examples/elm-pb-outerloop/elm_pb_outerloop.cxx | 2 -- src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx | 2 +- tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx index e48a1020ca..4ff8e90dcb 100644 --- a/examples/elm-pb-outerloop/elm_pb_outerloop.cxx +++ b/examples/elm-pb-outerloop/elm_pb_outerloop.cxx @@ -33,13 +33,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include diff --git a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx index 3d7f707678..a116d78475 100644 --- a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx +++ b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx @@ -14,8 +14,8 @@ #include "bout/globals.hxx" #include "bout/options.hxx" #include "bout/petsclib.hxx" -#include "bout/sys/range.hxx" #include "bout/solver.hxx" +#include "bout/sys/range.hxx" #include "bout/sys/timer.hxx" #include "bout/utils.hxx" diff --git a/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx b/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx index cede14b1f8..e04de9c675 100644 --- a/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy2-hypre/test-laplacexy.cxx @@ -23,15 +23,15 @@ * **************************************************************************/ +#include #include #include #include -#include -#include -#include #include #include #include +#include +#include #include From b1acf2c2d2b7b763b29d472cd8e0fda76be530a9 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 29 Oct 2025 11:32:38 +0100 Subject: [PATCH 234/259] Mark Field3DParallel constructors explicit --- include/bout/field3d.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 0f65fa7fd5..e791db776b 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -738,13 +738,13 @@ inline Field3D copy(const Field3D& f) { /// "main" field, Field3DParallel will retain the parallel slices. class Field3DParallel : public Field3D { public: - template + explicit template Field3DParallel(Types... args) : Field3D(std::move(args)...) { ensureFieldAligned(); } // Explicitly needed, as DirectionTypes is sometimes constructed from a // brace enclosed list - Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, + explicit Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, DirectionTypes directions_in = {YDirectionType::Standard, ZDirectionType::Standard}, std::optional regionID = {}) @@ -752,13 +752,13 @@ public: splitParallelSlices(); ensureFieldAligned(); } - Field3DParallel(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, + explicit Field3DParallel(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, DirectionTypes directions_in = {YDirectionType::Standard, ZDirectionType::Standard}) : Field3D(std::move(data), localmesh, location, directions_in) { ensureFieldAligned(); } - Field3DParallel(BoutReal, Mesh* mesh = nullptr); + explicit Field3DParallel(BoutReal, Mesh* mesh = nullptr); Field3D& asField3D() { return *this; } const Field3D& asField3D() const { return *this; } From 5a1419f1e9000324aeb36a8e8f03ca87fa3cf90a Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 29 Oct 2025 12:00:36 +0100 Subject: [PATCH 235/259] Add implict constructors only for Field2D and Field3D --- include/bout/field3d.hxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index e791db776b..9bbe6ad182 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -738,8 +738,14 @@ inline Field3D copy(const Field3D& f) { /// "main" field, Field3DParallel will retain the parallel slices. class Field3DParallel : public Field3D { public: - explicit template - Field3DParallel(Types... args) : Field3D(std::move(args)...) { + template + explicit Field3DParallel(Types... args) : Field3D(std::move(args)...) { + ensureFieldAligned(); + } + Field3DParallel(const Field3D& f) : Field3D(std::move(f)) { + ensureFieldAligned(); + } + Field3DParallel(const Field2D& f) : Field3D(std::move(f)) { ensureFieldAligned(); } // Explicitly needed, as DirectionTypes is sometimes constructed from a From 3b86ba908846d68650f90170bf04eaf7014e7f0a Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:02:17 +0000 Subject: [PATCH 236/259] Apply clang-format changes --- include/bout/field3d.hxx | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/include/bout/field3d.hxx b/include/bout/field3d.hxx index 9bbe6ad182..1a9b24d7fa 100644 --- a/include/bout/field3d.hxx +++ b/include/bout/field3d.hxx @@ -742,25 +742,22 @@ public: explicit Field3DParallel(Types... args) : Field3D(std::move(args)...) { ensureFieldAligned(); } - Field3DParallel(const Field3D& f) : Field3D(std::move(f)) { - ensureFieldAligned(); - } - Field3DParallel(const Field2D& f) : Field3D(std::move(f)) { - ensureFieldAligned(); - } + Field3DParallel(const Field3D& f) : Field3D(std::move(f)) { ensureFieldAligned(); } + Field3DParallel(const Field2D& f) : Field3D(std::move(f)) { ensureFieldAligned(); } // Explicitly needed, as DirectionTypes is sometimes constructed from a // brace enclosed list explicit Field3DParallel(Mesh* localmesh = nullptr, CELL_LOC location_in = CELL_CENTRE, - DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Standard}, - std::optional regionID = {}) + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}, + std::optional regionID = {}) : Field3D(localmesh, location_in, directions_in, regionID) { splitParallelSlices(); ensureFieldAligned(); } - explicit Field3DParallel(Array data, Mesh* localmesh, CELL_LOC location = CELL_CENTRE, - DirectionTypes directions_in = {YDirectionType::Standard, - ZDirectionType::Standard}) + explicit Field3DParallel(Array data, Mesh* localmesh, + CELL_LOC location = CELL_CENTRE, + DirectionTypes directions_in = {YDirectionType::Standard, + ZDirectionType::Standard}) : Field3D(std::move(data), localmesh, location, directions_in) { ensureFieldAligned(); } From 2699cafcfdcf2ee546fca1891086e96022a5f206 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 3 Nov 2025 10:26:59 +0000 Subject: [PATCH 237/259] Delete v5 header shims --- include/boundary_factory.hxx | 4 ---- include/boundary_op.hxx | 4 ---- include/boundary_region.hxx | 4 ---- include/boundary_standard.hxx | 4 ---- include/bout.hxx | 4 ---- include/bout_types.hxx | 4 ---- include/boutcomm.hxx | 4 ---- include/boutexception.hxx | 4 ---- include/cyclic_reduction.hxx | 4 ---- include/dcomplex.hxx | 4 ---- include/derivs.hxx | 4 ---- include/difops.hxx | 4 ---- include/fft.hxx | 4 ---- include/field.hxx | 4 ---- include/field2d.hxx | 4 ---- include/field3d.hxx | 4 ---- include/field_data.hxx | 4 ---- include/field_factory.hxx | 4 ---- include/fieldperp.hxx | 4 ---- include/globals.hxx | 4 ---- include/gyro_average.hxx | 4 ---- include/initialprofiles.hxx | 4 ---- include/interpolation.hxx | 4 ---- include/interpolation_xz.hxx | 4 ---- include/interpolation_z.hxx | 4 ---- include/invert_laplace.hxx | 4 ---- include/invert_parderiv.hxx | 4 ---- include/lapack_routines.hxx | 4 ---- include/mask.hxx | 4 ---- include/msg_stack.hxx | 4 ---- include/multiostream.hxx | 4 ---- include/options.hxx | 4 ---- include/optionsreader.hxx | 4 ---- include/output.hxx | 4 ---- include/parallel_boundary_op.hxx | 4 ---- include/parallel_boundary_region.hxx | 4 ---- include/smoothing.hxx | 4 ---- include/sourcex.hxx | 4 ---- include/stencils.hxx | 4 ---- include/unused.hxx | 4 ---- include/utils.hxx | 4 ---- include/vecops.hxx | 4 ---- include/vector2d.hxx | 4 ---- include/vector3d.hxx | 4 ---- include/where.hxx | 4 ---- 45 files changed, 180 deletions(-) delete mode 100644 include/boundary_factory.hxx delete mode 100644 include/boundary_op.hxx delete mode 100644 include/boundary_region.hxx delete mode 100644 include/boundary_standard.hxx delete mode 100644 include/bout.hxx delete mode 100644 include/bout_types.hxx delete mode 100644 include/boutcomm.hxx delete mode 100644 include/boutexception.hxx delete mode 100644 include/cyclic_reduction.hxx delete mode 100644 include/dcomplex.hxx delete mode 100644 include/derivs.hxx delete mode 100644 include/difops.hxx delete mode 100644 include/fft.hxx delete mode 100644 include/field.hxx delete mode 100644 include/field2d.hxx delete mode 100644 include/field3d.hxx delete mode 100644 include/field_data.hxx delete mode 100644 include/field_factory.hxx delete mode 100644 include/fieldperp.hxx delete mode 100644 include/globals.hxx delete mode 100644 include/gyro_average.hxx delete mode 100644 include/initialprofiles.hxx delete mode 100644 include/interpolation.hxx delete mode 100644 include/interpolation_xz.hxx delete mode 100644 include/interpolation_z.hxx delete mode 100644 include/invert_laplace.hxx delete mode 100644 include/invert_parderiv.hxx delete mode 100644 include/lapack_routines.hxx delete mode 100644 include/mask.hxx delete mode 100644 include/msg_stack.hxx delete mode 100644 include/multiostream.hxx delete mode 100644 include/options.hxx delete mode 100644 include/optionsreader.hxx delete mode 100644 include/output.hxx delete mode 100644 include/parallel_boundary_op.hxx delete mode 100644 include/parallel_boundary_region.hxx delete mode 100644 include/smoothing.hxx delete mode 100644 include/sourcex.hxx delete mode 100644 include/stencils.hxx delete mode 100644 include/unused.hxx delete mode 100644 include/utils.hxx delete mode 100644 include/vecops.hxx delete mode 100644 include/vector2d.hxx delete mode 100644 include/vector3d.hxx delete mode 100644 include/where.hxx diff --git a/include/boundary_factory.hxx b/include/boundary_factory.hxx deleted file mode 100644 index abbead8fc4..0000000000 --- a/include/boundary_factory.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_factory.hxx" has moved to "bout/boundary_factory.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_factory.hxx" diff --git a/include/boundary_op.hxx b/include/boundary_op.hxx deleted file mode 100644 index c96310f2d4..0000000000 --- a/include/boundary_op.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_op.hxx" has moved to "bout/boundary_op.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_op.hxx" diff --git a/include/boundary_region.hxx b/include/boundary_region.hxx deleted file mode 100644 index f487e88aeb..0000000000 --- a/include/boundary_region.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_region.hxx" has moved to "bout/boundary_region.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_region.hxx" diff --git a/include/boundary_standard.hxx b/include/boundary_standard.hxx deleted file mode 100644 index b7f17cf363..0000000000 --- a/include/boundary_standard.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boundary_standard.hxx" has moved to "bout/boundary_standard.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boundary_standard.hxx" diff --git a/include/bout.hxx b/include/bout.hxx deleted file mode 100644 index 926f035d2f..0000000000 --- a/include/bout.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "bout.hxx" has moved to "bout/bout.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/bout.hxx" diff --git a/include/bout_types.hxx b/include/bout_types.hxx deleted file mode 100644 index e6048eb885..0000000000 --- a/include/bout_types.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "bout_types.hxx" has moved to "bout/bout_types.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/bout_types.hxx" diff --git a/include/boutcomm.hxx b/include/boutcomm.hxx deleted file mode 100644 index 256df49c4f..0000000000 --- a/include/boutcomm.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boutcomm.hxx" has moved to "bout/boutcomm.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boutcomm.hxx" diff --git a/include/boutexception.hxx b/include/boutexception.hxx deleted file mode 100644 index 9189babfb3..0000000000 --- a/include/boutexception.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "boutexception.hxx" has moved to "bout/boutexception.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/boutexception.hxx" diff --git a/include/cyclic_reduction.hxx b/include/cyclic_reduction.hxx deleted file mode 100644 index 3ff098b062..0000000000 --- a/include/cyclic_reduction.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "cyclic_reduction.hxx" has moved to "bout/cyclic_reduction.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/cyclic_reduction.hxx" diff --git a/include/dcomplex.hxx b/include/dcomplex.hxx deleted file mode 100644 index a91c5485bf..0000000000 --- a/include/dcomplex.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "dcomplex.hxx" has moved to "bout/dcomplex.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/dcomplex.hxx" diff --git a/include/derivs.hxx b/include/derivs.hxx deleted file mode 100644 index d0a6eb5831..0000000000 --- a/include/derivs.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "derivs.hxx" has moved to "bout/derivs.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/derivs.hxx" diff --git a/include/difops.hxx b/include/difops.hxx deleted file mode 100644 index a61d9712a9..0000000000 --- a/include/difops.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "difops.hxx" has moved to "bout/difops.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/difops.hxx" diff --git a/include/fft.hxx b/include/fft.hxx deleted file mode 100644 index d67b257388..0000000000 --- a/include/fft.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "fft.hxx" has moved to "bout/fft.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/fft.hxx" diff --git a/include/field.hxx b/include/field.hxx deleted file mode 100644 index a2fcb2464e..0000000000 --- a/include/field.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field.hxx" has moved to "bout/field.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field.hxx" diff --git a/include/field2d.hxx b/include/field2d.hxx deleted file mode 100644 index 3b148b3a50..0000000000 --- a/include/field2d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field2d.hxx" has moved to "bout/field2d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field2d.hxx" diff --git a/include/field3d.hxx b/include/field3d.hxx deleted file mode 100644 index 300cec057b..0000000000 --- a/include/field3d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field3d.hxx" has moved to "bout/field3d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field3d.hxx" diff --git a/include/field_data.hxx b/include/field_data.hxx deleted file mode 100644 index 90f5c96c40..0000000000 --- a/include/field_data.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field_data.hxx" has moved to "bout/field_data.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field_data.hxx" diff --git a/include/field_factory.hxx b/include/field_factory.hxx deleted file mode 100644 index c6302ee298..0000000000 --- a/include/field_factory.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "field_factory.hxx" has moved to "bout/field_factory.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/field_factory.hxx" diff --git a/include/fieldperp.hxx b/include/fieldperp.hxx deleted file mode 100644 index 1994e53060..0000000000 --- a/include/fieldperp.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "fieldperp.hxx" has moved to "bout/fieldperp.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/fieldperp.hxx" diff --git a/include/globals.hxx b/include/globals.hxx deleted file mode 100644 index f07488c10c..0000000000 --- a/include/globals.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "globals.hxx" has moved to "bout/globals.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/globals.hxx" diff --git a/include/gyro_average.hxx b/include/gyro_average.hxx deleted file mode 100644 index c0d454eb50..0000000000 --- a/include/gyro_average.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "gyro_average.hxx" has moved to "bout/gyro_average.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/gyro_average.hxx" diff --git a/include/initialprofiles.hxx b/include/initialprofiles.hxx deleted file mode 100644 index 7bc1595261..0000000000 --- a/include/initialprofiles.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "initialprofiles.hxx" has moved to "bout/initialprofiles.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/initialprofiles.hxx" diff --git a/include/interpolation.hxx b/include/interpolation.hxx deleted file mode 100644 index 80ad60b4e4..0000000000 --- a/include/interpolation.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "interpolation.hxx" has moved to "bout/interpolation.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/interpolation.hxx" diff --git a/include/interpolation_xz.hxx b/include/interpolation_xz.hxx deleted file mode 100644 index 8845e34b80..0000000000 --- a/include/interpolation_xz.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "interpolation_xz.hxx" has moved to "bout/interpolation_xz.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/interpolation_xz.hxx" diff --git a/include/interpolation_z.hxx b/include/interpolation_z.hxx deleted file mode 100644 index a88b486026..0000000000 --- a/include/interpolation_z.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "interpolation_z.hxx" has moved to "bout/interpolation_z.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/interpolation_z.hxx" diff --git a/include/invert_laplace.hxx b/include/invert_laplace.hxx deleted file mode 100644 index fbb04acaf1..0000000000 --- a/include/invert_laplace.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "invert_laplace.hxx" has moved to "bout/invert_laplace.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/invert_laplace.hxx" diff --git a/include/invert_parderiv.hxx b/include/invert_parderiv.hxx deleted file mode 100644 index 81a8ca4f49..0000000000 --- a/include/invert_parderiv.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "invert_parderiv.hxx" has moved to "bout/invert_parderiv.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/invert_parderiv.hxx" diff --git a/include/lapack_routines.hxx b/include/lapack_routines.hxx deleted file mode 100644 index 97fa2c6be9..0000000000 --- a/include/lapack_routines.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "lapack_routines.hxx" has moved to "bout/lapack_routines.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/lapack_routines.hxx" diff --git a/include/mask.hxx b/include/mask.hxx deleted file mode 100644 index cbeab65d85..0000000000 --- a/include/mask.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "mask.hxx" has moved to "bout/mask.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/mask.hxx" diff --git a/include/msg_stack.hxx b/include/msg_stack.hxx deleted file mode 100644 index 2503961748..0000000000 --- a/include/msg_stack.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "msg_stack.hxx" has moved to "bout/msg_stack.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/msg_stack.hxx" diff --git a/include/multiostream.hxx b/include/multiostream.hxx deleted file mode 100644 index 7e7101aad0..0000000000 --- a/include/multiostream.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "multiostream.hxx" has moved to "bout/multiostream.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/multiostream.hxx" diff --git a/include/options.hxx b/include/options.hxx deleted file mode 100644 index 4693422c13..0000000000 --- a/include/options.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "options.hxx" has moved to "bout/options.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/options.hxx" diff --git a/include/optionsreader.hxx b/include/optionsreader.hxx deleted file mode 100644 index 2c0f8344bf..0000000000 --- a/include/optionsreader.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "optionsreader.hxx" has moved to "bout/optionsreader.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/optionsreader.hxx" diff --git a/include/output.hxx b/include/output.hxx deleted file mode 100644 index 7eebcad478..0000000000 --- a/include/output.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "output.hxx" has moved to "bout/output.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/output.hxx" diff --git a/include/parallel_boundary_op.hxx b/include/parallel_boundary_op.hxx deleted file mode 100644 index e82a88d98f..0000000000 --- a/include/parallel_boundary_op.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "parallel_boundary_op.hxx" has moved to "bout/parallel_boundary_op.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/parallel_boundary_op.hxx" diff --git a/include/parallel_boundary_region.hxx b/include/parallel_boundary_region.hxx deleted file mode 100644 index dee2277007..0000000000 --- a/include/parallel_boundary_region.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "parallel_boundary_region.hxx" has moved to "bout/parallel_boundary_region.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/parallel_boundary_region.hxx" diff --git a/include/smoothing.hxx b/include/smoothing.hxx deleted file mode 100644 index b1a36adfb2..0000000000 --- a/include/smoothing.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "smoothing.hxx" has moved to "bout/smoothing.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/smoothing.hxx" diff --git a/include/sourcex.hxx b/include/sourcex.hxx deleted file mode 100644 index e09f3e89e4..0000000000 --- a/include/sourcex.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "sourcex.hxx" has moved to "bout/sourcex.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/sourcex.hxx" diff --git a/include/stencils.hxx b/include/stencils.hxx deleted file mode 100644 index fc877f3e1c..0000000000 --- a/include/stencils.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "stencils.hxx" has moved to "bout/stencils.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/stencils.hxx" diff --git a/include/unused.hxx b/include/unused.hxx deleted file mode 100644 index fa5ea7b6d1..0000000000 --- a/include/unused.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "unused.hxx" has moved to "bout/unused.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/unused.hxx" diff --git a/include/utils.hxx b/include/utils.hxx deleted file mode 100644 index d1a095e491..0000000000 --- a/include/utils.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "utils.hxx" has moved to "bout/utils.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/utils.hxx" diff --git a/include/vecops.hxx b/include/vecops.hxx deleted file mode 100644 index 1773418077..0000000000 --- a/include/vecops.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "vecops.hxx" has moved to "bout/vecops.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/vecops.hxx" diff --git a/include/vector2d.hxx b/include/vector2d.hxx deleted file mode 100644 index 6746d3f163..0000000000 --- a/include/vector2d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "vector2d.hxx" has moved to "bout/vector2d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/vector2d.hxx" diff --git a/include/vector3d.hxx b/include/vector3d.hxx deleted file mode 100644 index 747b6a75dd..0000000000 --- a/include/vector3d.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "vector3d.hxx" has moved to "bout/vector3d.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/vector3d.hxx" diff --git a/include/where.hxx b/include/where.hxx deleted file mode 100644 index e5b2bd9d30..0000000000 --- a/include/where.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "where.hxx" has moved to "bout/where.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/where.hxx" From afc4a3a25c8333cd397cc0bdaa00ec8a6e18c097 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 3 Nov 2025 13:47:09 +0000 Subject: [PATCH 238/259] Bump bundled fmt --- externalpackages/fmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/fmt b/externalpackages/fmt index 486e7ba579..407c905e45 160000 --- a/externalpackages/fmt +++ b/externalpackages/fmt @@ -1 +1 @@ -Subproject commit 486e7ba579a2c677772d004ecd0311142ba481be +Subproject commit 407c905e45ad75fc29bf0f9bb7c5c2fd3475976f From 760a24f30a31400b5256caf96bbd925d2d4ff9e0 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 3 Nov 2025 15:52:25 +0000 Subject: [PATCH 239/259] tests: Small refactor of FCI tests --- .../test-fci-boundary/get_par_bndry.cxx | 22 ++-- tests/integrated/test-fci-boundary/runtest | 36 ++---- tests/integrated/test-fci-mpi/fci_mpi.cxx | 59 +++++----- tests/integrated/test-fci-mpi/runtest | 107 +++++++++++------- 4 files changed, 116 insertions(+), 108 deletions(-) diff --git a/tests/integrated/test-fci-boundary/get_par_bndry.cxx b/tests/integrated/test-fci-boundary/get_par_bndry.cxx index ac0f5de2a6..ba282d8988 100644 --- a/tests/integrated/test-fci-boundary/get_par_bndry.cxx +++ b/tests/integrated/test-fci-boundary/get_par_bndry.cxx @@ -1,5 +1,5 @@ #include "bout/bout.hxx" -#include "bout/derivs.hxx" +#include "bout/field3d.hxx" #include "bout/field_factory.hxx" #include "bout/parallel_boundary_region.hxx" @@ -8,24 +8,24 @@ int main(int argc, char** argv) { using bout::globals::mesh; - std::vector fields; - fields.resize(static_cast(BoundaryParType::SIZE)); + std::vector fields (static_cast(BoundaryParType::SIZE), Field3D{0.0}); + Options dump; for (int i = 0; i < fields.size(); i++) { - fields[i] = Field3D{0.0}; + fields[i].allocate(); + const auto boundary = static_cast(i); + const auto boundary_name = toString(boundary); mesh->communicate(fields[i]); - for (const auto& bndry_par : - mesh->getBoundariesPar(static_cast(i))) { - output.write("{:s} region\n", toString(static_cast(i))); + for (const auto& bndry_par : mesh->getBoundariesPar(boundary)) { + output.write("{:s} region\n", boundary_name); for (bndry_par->first(); !bndry_par->isDone(); bndry_par->next()) { fields[i][bndry_par->ind()] += 1; - output.write("{:s} increment\n", toString(static_cast(i))); + output.write("{:s} increment\n", boundary_name); } } - output.write("{:s} done\n", toString(static_cast(i))); + output.write("{:s} done\n", boundary_name); - dump[fmt::format("field_{:s}", toString(static_cast(i)))] = - fields[i]; + dump[fmt::format("field_{:s}", boundary_name)] = fields[i]; } bout::writeDefaultOutputFile(dump); diff --git a/tests/integrated/test-fci-boundary/runtest b/tests/integrated/test-fci-boundary/runtest index 1b1460da53..e749055185 100755 --- a/tests/integrated/test-fci-boundary/runtest +++ b/tests/integrated/test-fci-boundary/runtest @@ -1,29 +1,15 @@ #!/usr/bin/env python3 # # Python script to run and analyse MMS test -# -# Cores: 2 -# only working with cmake -# requires: False from boututils.run_wrapper import launch_safe from boututils.datafile import DataFile -from boutdata.collect import collect as _collect +from boutdata.collect import collect import numpy as np -def collect(var): - return _collect( - var, - info=False, - path=directory, - xguards=False, - yguards=False, - ) - - -nprocs = [1] # , 2, 4] +nprocs = [1] mthread = 2 directory = "data" @@ -43,11 +29,6 @@ regions = { } regions = {k: v.astype(int) for k, v in regions.items()} -# for x in "xout", "xin": -# regions[x] = np.logical_or(regions[f"{x}_fwd"], regions[f"{x}_bwd"]) -# for x in "fwd", "bwd": -# regions[x] = np.logical_or(regions[f"xin_{x}"], regions[f"xout_{x}"]) -# regions["all"] = np.logical_or(regions["xin"], regions["xout"]) for x in "xout", "xin": regions[x] = regions[f"{x}_fwd"] + regions[f"{x}_bwd"] for x in "fwd", "bwd": @@ -56,15 +37,18 @@ regions["all"] = regions["xin"] + regions["xout"] for nproc in nprocs: cmd = "./get_par_bndry" - - # Launch using MPI _, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) for k, v in regions.items(): - # Collect data - data = collect(f"field_{k}") + data = collect( + f"field_{k}", + info=False, + path=directory, + xguards=False, + yguards=False, + ) assert np.allclose(data, v), ( - k + " does not match", + f"{k} does not match", np.sum(data), np.sum(v), np.max(data), diff --git a/tests/integrated/test-fci-mpi/fci_mpi.cxx b/tests/integrated/test-fci-mpi/fci_mpi.cxx index 94520dd4a6..cc4fba8ffe 100644 --- a/tests/integrated/test-fci-mpi/fci_mpi.cxx +++ b/tests/integrated/test-fci-mpi/fci_mpi.cxx @@ -1,38 +1,37 @@ +#include "fmt/format.h" #include "bout/bout.hxx" -#include "bout/derivs.hxx" #include "bout/field_factory.hxx" +namespace { +auto fci_mpi_test(int num, Options& dump) { + using bout::globals::mesh; + Field3D input{FieldFactory::get()->create3D(fmt::format("input_{:d}:function", num), + Options::getRoot(), mesh)}; + mesh->communicate(input); + + input.applyParallelBoundary("parallel_neumann_o2"); + + for (int slice = -mesh->ystart; slice <= mesh->ystart; ++slice) { + if (slice == 0) { + continue; + } + Field3D tmp{0.}; + BOUT_FOR(i, tmp.getRegion("RGN_NOBNDRY")) { + tmp[i] = input.ynext(slice)[i.yp(slice)]; + } + dump[fmt::format("output_{:d}_{:+d}", num, slice)] = tmp; + } +} +} // namespace + int main(int argc, char** argv) { BoutInitialise(argc, argv); - { - using bout::globals::mesh; - Options* options = Options::getRoot(); - int i = 0; - const std::string default_str{"not_set"}; - Options dump; - while (true) { - std::string temp_str; - options->get(fmt::format("input_{:d}:function", i), temp_str, default_str); - if (temp_str == default_str) { - break; - } - Field3D input{FieldFactory::get()->create3D(fmt::format("input_{:d}:function", i), - Options::getRoot(), mesh)}; - // options->get(fmt::format("input_{:d}:boundary_perp", i), temp_str, s"free_o3"); - mesh->communicate(input); - input.applyParallelBoundary("parallel_neumann_o2"); - for (int slice = -mesh->ystart; slice <= mesh->ystart; ++slice) { - if (slice != 0) { - Field3D tmp{0.}; - BOUT_FOR(i, tmp.getRegion("RGN_NOBNDRY")) { - tmp[i] = input.ynext(slice)[i.yp(slice)]; - } - dump[fmt::format("output_{:d}_{:+d}", i, slice)] = tmp; - } - } - ++i; - } - bout::writeDefaultOutputFile(dump); + Options dump; + + for (auto num : {0, 1, 2, 3}) { + fci_mpi_test(num, dump); } + + bout::writeDefaultOutputFile(dump); BoutFinalise(); } diff --git a/tests/integrated/test-fci-mpi/runtest b/tests/integrated/test-fci-mpi/runtest index 6676f8f7a5..828d8d4a50 100755 --- a/tests/integrated/test-fci-mpi/runtest +++ b/tests/integrated/test-fci-mpi/runtest @@ -1,57 +1,82 @@ #!/usr/bin/env python3 # # Python script to run and analyse MMS test -# - -# Cores: 8 -# requires: metric_3d -from boututils.run_wrapper import build_and_log, launch_safe, shell_safe +from boututils.run_wrapper import build_and_log, launch_safe from boutdata.collect import collect -import boutconfig as conf import itertools +import sys -import numpy as np +import numpy.testing as npt # Resolution in x and y -nlist = [1, 2, 4] +NLIST = [1, 2, 4] +MAXCORES = 8 +NSLICES = [1] -maxcores = 8 +build_and_log("FCI MMS test") -nslices = [1] +COLLECT_KW = dict(info=False, xguards=False, yguards=False, path="data") -success = True -build_and_log("FCI MMS test") +def run_case(nxpe: int, nype: int, mthread: int): + cmd = f"./fci_mpi NXPE={nxpe} NYPE={nype}" + print(f"Running command: {cmd}") + + _, out = launch_safe(cmd, nproc=nxpe * nype, mthread=mthread, pipe=True) + + # Save output to log file + with open(f"run.log.{nxpe}.{nype}.{nslice}.log", "w") as f: + f.write(out) + + +def test_case(nxpe: int, nype: int, mthread: int, ref: dict) -> bool: + run_case(nxpe, nype, mthread) + + failures = [] + + for name, val in ref.items(): + try: + npt.assert_allclose(val, collect(name, **COLLECT_KW)) + except AssertionError as e: + failures.append((nxpe, nype, name, e)) -for nslice in nslices: - for NXPE, NYPE in itertools.product(nlist, nlist): - if NXPE * NYPE > maxcores: + return failures + + +failures = [] + +for nslice in NSLICES: + # reference data! + run_case(1, 1, MAXCORES) + + ref = {} + for i in range(4): + for yp in range(1, nslice + 1): + for y in [-yp, yp]: + name = f"output_{i}_{y:+d}" + ref[name] = collect(name, **COLLECT_KW) + + for nxpe, nype in itertools.product(NLIST, NLIST): + if (nxpe, nype) == (1, 1): + # reference case, done above continue - args = f"NXPE={NXPE} NYPE={NYPE}" - # Command to run - cmd = f"./fci_mpi {args}" - - print(f"Running command: {cmd}") - - mthread = maxcores // (NXPE * NYPE) - # Launch using MPI - _, out = launch_safe(cmd, nproc=NXPE * NYPE, mthread=mthread, pipe=True) - - # Save output to log file - with open(f"run.log.{NXPE}.{NYPE}.{nslice}.log", "w") as f: - f.write(out) - - collect_kw = dict(info=False, xguards=False, yguards=False, path="data") - if NXPE == NYPE == 1: - # reference data! - ref = {} - for i in range(4): - for yp in range(1, nslice + 1): - for y in [-yp, yp]: - name = f"output_{i}_{y:+d}" - ref[name] = collect(name, **collect_kw) - else: - for name, val in ref.items(): - assert np.allclose(val, collect(name, **collect_kw)) + if nxpe * nype > MAXCORES: + continue + + mthread = MAXCORES // (nxpe * nype) + failures_ = test_case(nxpe, nype, mthread, ref) + failures.extend(failures_) + + +success = len(failures) == 0 +if success: + print("\nAll tests passed") +else: + print("\nSome tests failed:") + for (nxpe, nype, name, error) in failures: + print("----------") + print(f"case {nxpe=} {nype=} {name=}\n{error}") + +sys.exit(0 if success else 1) From 58e2673c1dbb519e2784a3a0fe365041993a1a35 Mon Sep 17 00:00:00 2001 From: ZedThree <1486942+ZedThree@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:05:43 +0000 Subject: [PATCH 240/259] Apply black changes --- tests/integrated/test-fci-mpi/runtest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-fci-mpi/runtest b/tests/integrated/test-fci-mpi/runtest index 828d8d4a50..c18ab0391d 100755 --- a/tests/integrated/test-fci-mpi/runtest +++ b/tests/integrated/test-fci-mpi/runtest @@ -75,7 +75,7 @@ if success: print("\nAll tests passed") else: print("\nSome tests failed:") - for (nxpe, nype, name, error) in failures: + for nxpe, nype, name, error in failures: print("----------") print(f"case {nxpe=} {nype=} {name=}\n{error}") From 1cce8e649d27cd217e48e632e2128f396b9b6ba0 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 11:10:29 +0100 Subject: [PATCH 241/259] BoutComm::get() might return int --- src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx index a116d78475..04abecfe05 100644 --- a/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx +++ b/src/invert/laplacexy/impls/petsc/laplacexy-petsc.cxx @@ -84,7 +84,7 @@ LaplaceXYpetsc::LaplaceXYpetsc(Mesh* m, Options* opt, const CELL_LOC loc) default_prefix = opt->name(); // Get MPI communicator - auto* comm = BoutComm::get(); + auto comm = BoutComm::get(); // Local size const int localN = localSize(); From c2b5e0e283e286d59aeb0e501306ffd3f650e669 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 12:30:46 +0100 Subject: [PATCH 242/259] Avoid mpi-compatibility issues MPI_Comm can be a pointer or an int (or anything else) Co-authored-by: Peter Hill --- .clang-tidy | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.clang-tidy b/.clang-tidy index 4caf530aee..a142355fc4 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -12,6 +12,12 @@ CheckOptions: - key: misc-include-cleaner.IgnoreHeaders value: 'petsc.*\.h;mpi\.h' + + - key: readability-qualified-auto.IgnoreAliasing + value: 'false' + + - key: readability-qualified-auto.AllowedTypes + value: 'MPI_Comm' --- Disabled checks and reasons: From 00b970e118dfeb8abf204f6b9511b3d7938da0c3 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 12:36:54 +0100 Subject: [PATCH 243/259] Remove configure left overs --- build-aux/config.guess | 1568 ------- build-aux/config.rpath | 0 build-aux/config.sub | 1788 -------- build-aux/install-sh | 527 --- build-aux/ltmain.sh | 9655 ---------------------------------------- build-aux/missing | 215 - 6 files changed, 13753 deletions(-) delete mode 100755 build-aux/config.guess delete mode 100644 build-aux/config.rpath delete mode 100755 build-aux/config.sub delete mode 100755 build-aux/install-sh delete mode 100644 build-aux/ltmain.sh delete mode 100755 build-aux/missing diff --git a/build-aux/config.guess b/build-aux/config.guess deleted file mode 100755 index c6fad2f5e5..0000000000 --- a/build-aux/config.guess +++ /dev/null @@ -1,1568 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-06-10' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD -# -# Please send patches with a ChangeLog entry to config-patches@gnu.org. - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - ;; -esac - -case "${UNAME_MACHINE}" in - i?86) - test -z "$VENDOR" && VENDOR=pc - ;; - *) - test -z "$VENDOR" && VENDOR=unknown - ;; -esac -test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-${VENDOR}-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-${VENDOR}-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-${VENDOR}-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-${VENDOR}-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-${VENDOR}-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-${VENDOR}-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-${VENDOR}-osf1mk - else - echo ${UNAME_MACHINE}-${VENDOR}-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-${VENDOR}-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-${VENDOR}-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-${VENDOR}-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-${VENDOR}-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-${VENDOR}-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-${VENDOR}-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-${VENDOR}-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-${VENDOR}-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-${VENDOR}-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-${LIBC}"; exit; } - ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-${VENDOR}-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-${VENDOR}-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-${VENDOR}-linux-${LIBC} ;; - PA8*) echo hppa2.0-${VENDOR}-linux-${LIBC} ;; - *) echo hppa-${VENDOR}-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-${VENDOR}-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-${VENDOR}-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-${VENDOR}-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-${VENDOR}-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-${VENDOR}-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-${VENODR}-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-${VENDOR}-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-${VENODR}-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-${VENDOR}-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-${VENDOR}-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-${VENDOR}-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-${VENDOR}-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-${VENDOR}-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-${VENDOR}-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-${VENDOR}-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-${VENDOR}-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-esx - exit ;; -esac - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build-aux/config.rpath b/build-aux/config.rpath deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/build-aux/config.sub b/build-aux/config.sub deleted file mode 100755 index 8b612ab89d..0000000000 --- a/build-aux/config.sub +++ /dev/null @@ -1,1788 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-04-24' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches with a ChangeLog entry to config-patches@gnu.org. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i386-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or1k-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build-aux/install-sh b/build-aux/install-sh deleted file mode 100755 index 377bb8687f..0000000000 --- a/build-aux/install-sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2011-11-20.07; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh deleted file mode 100644 index 63ae69dc6f..0000000000 --- a/build-aux/ltmain.sh +++ /dev/null @@ -1,9655 +0,0 @@ - -# libtool (GNU libtool) 2.4.2 -# Written by Gordon Matzigkeit , 1996 - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory -# -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. -# -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: -# -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 -# automake: $automake_version -# autoconf: $autoconf_version -# -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . - -PROGRAM=libtool -PACKAGE=libtool -VERSION=2.4.2 -TIMESTAMP="" -package_revision=1.3337 - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" - fi" -done -LC_ALL=C -LANGUAGE=C -export LANGUAGE LC_ALL - -$lt_unset CDPATH - - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" - - - -: ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -exit_status=$EXIT_SUCCESS - -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" - -dirname="s,/[^/]*$,," -basename="s,^.*/,," - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation - - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation - - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation - - -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' - -# func_normal_abspath PATH -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -# value returned in "$func_normal_abspath_result" -func_normal_abspath () -{ - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi - - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi -} - -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result - -# Make sure we have an absolute path for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=$func_dirname_result - progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" - ;; - *) - save_IFS="$IFS" - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS="$save_IFS" - test -x "$progdir/$progname" && break - done - IFS="$save_IFS" - test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' - -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" - -# Standard options: -opt_dry_run=false -opt_help=false -opt_quiet=false -opt_verbose=false -opt_warning=: - -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} - -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} - -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 - - # bash bug again: - : -} - -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" -} -help="Try \`$progname --help' for more information." ## default - - -# func_grep expression filename -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_mkdir_p directory-path -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - my_directory_path="$1" - my_dir_list= - - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" - - # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` - done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` - - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : - done - IFS="$save_mkdir_p_IFS" - - # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" - fi -} - - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$opt_dry_run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" - fi - - $ECHO "$my_tmpdir" -} - - -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. -func_quote_for_eval () -{ - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; - *) - func_quote_for_eval_unquoted_result="$1" ;; - esac - - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" - ;; - *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" - esac -} - - -# func_quote_for_expand arg -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - case $1 in - *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; - *) - my_arg="$1" ;; - esac - - case $my_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" - ;; - esac - - func_quote_for_expand_result="$my_arg" -} - - -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - - -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - -# func_tr_sh -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_version -# Echo version message to standard output and exit. -func_version () -{ - $opt_debug - - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? -} - -# func_usage -# Echo short help message to standard output and exit. -func_usage () -{ - $opt_debug - - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? -} - -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. -func_help () -{ - $opt_debug - - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi -} - -# func_missing_arg argname -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $opt_debug - - func_error "missing argument for $1." - exit_cmd=exit -} - - -# func_split_short_opt shortopt -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () -{ - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' - - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation - - -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () -{ - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' - - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation - -exit_cmd=: - - - - - -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" - -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation - -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () -{ - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation - - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation - - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation - - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation - - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation - - -# func_fatal_configuration arg... -# Echo program name prefixed message to standard error, followed by -# a configuration failure hint, and exit. -func_fatal_configuration () -{ - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." -} - - -# func_config -# Display the configuration for all the tags in this script. -func_config () -{ - re_begincf='^# ### BEGIN LIBTOOL' - re_endcf='^# ### END LIBTOOL' - - # Default configuration. - $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" - - # Now print the configurations for the tags. - for tagname in $taglist; do - $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" - done - - exit $? -} - -# func_features -# Display the features supported by this script. -func_features () -{ - echo "host: $host" - if test "$build_libtool_libs" = yes; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - - exit $? -} - -# func_enable_tag tagname -# Verify that TAGNAME is valid, and either flag an error and exit, or -# enable the TAGNAME tag. We also add TAGNAME to the global $taglist -# variable here. -func_enable_tag () -{ - # Global variable: - tagname="$1" - - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac - - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; - *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac -} - -# func_check_version_match -# Ensure that we are using m4 macros, and libtool script from the same -# release of libtool. -func_check_version_match () -{ - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from an older release. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - fi - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, -$progname: but the definition of this LT_INIT comes from revision $macro_revision. -$progname: You should recreate aclocal.m4 with macros from revision $package_revision -$progname: of $PACKAGE $VERSION and run autoconf again. -_LT_EOF - fi - - exit $EXIT_MISMATCH - fi -} - - -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - - - -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false - - -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. -{ - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; - - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; - - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; - esac - done - - # Validate options: - - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi - - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" - - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" - fi - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } - - - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE -} - - - - -## ----------- ## -## Main. ## -## ----------- ## - -# func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_lalib_p () -{ - test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - -# func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function implements the same check as func_lalib_p without -# resorting to external programs. To this end, it redirects stdin and -# closes it afterwards, without saving the original file descriptor. -# As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. -func_lalib_unsafe_p () -{ - lalib_p=no - if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then - for lalib_p_l in 1 2 3 4 - do - read lalib_p_line - case "$lalib_p_line" in - \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; - esac - done - exec 0<&5 5<&- - fi - test "$lalib_p" = yes -} - -# func_ltwrapper_script_p file -# True iff FILE is a libtool wrapper script -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_script_p () -{ - func_lalib_p "$1" -} - -# func_ltwrapper_executable_p file -# True iff FILE is a libtool wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_executable_p () -{ - func_ltwrapper_exec_suffix= - case $1 in - *.exe) ;; - *) func_ltwrapper_exec_suffix=.exe ;; - esac - $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 -} - -# func_ltwrapper_scriptname file -# Assumes file is an ltwrapper_executable -# uses $file to determine the appropriate filename for a -# temporary ltwrapper_script. -func_ltwrapper_scriptname () -{ - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" -} - -# func_ltwrapper_p file -# True iff FILE is a libtool wrapper script or wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_p () -{ - func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" -} - - -# func_execute_cmds commands fail_cmd -# Execute tilde-delimited COMMANDS. -# If FAIL_CMD is given, eval that upon failure. -# FAIL_CMD may read-access the current command in variable CMD! -func_execute_cmds () -{ - $opt_debug - save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$save_ifs - eval cmd=\"$cmd\" - func_show_eval "$cmd" "${2-:}" - done - IFS=$save_ifs -} - - -# func_source file -# Source FILE, adding directory component if necessary. -# Note that it is not necessary on cygwin/mingw to append a dot to -# FILE even if both FILE and FILE.exe exist: automatic-append-.exe -# behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. -func_source () -{ - $opt_debug - case $1 in - */* | *\\*) . "$1" ;; - *) . "./$1" ;; - esac -} - - -# func_resolve_sysroot PATH -# Replace a leading = in PATH with a sysroot. Store the result into -# func_resolve_sysroot_result -func_resolve_sysroot () -{ - func_resolve_sysroot_result=$1 - case $func_resolve_sysroot_result in - =*) - func_stripname '=' '' "$func_resolve_sysroot_result" - func_resolve_sysroot_result=$lt_sysroot$func_stripname_result - ;; - esac -} - -# func_replace_sysroot PATH -# If PATH begins with the sysroot, replace it with = and -# store the result into func_replace_sysroot_result. -func_replace_sysroot () -{ - case "$lt_sysroot:$1" in - ?*:"$lt_sysroot"*) - func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" - ;; - *) - # Including no sysroot. - func_replace_sysroot_result=$1 - ;; - esac -} - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - $opt_debug - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case "$@ " in - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" -# else -# func_verbose "using $tagname tagged configuration" - fi - ;; - esac - fi -} - - - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () -{ - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' - else - write_lobj=none - fi - - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' - else - write_oldobj=none - fi - - $opt_dry_run || { - cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then - func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` - else - func_convert_core_file_wine_to_w32_result= - fi - fi -} -# end: func_convert_core_file_wine_to_w32 - - -# func_convert_core_path_wine_to_w32 ARG -# Helper function used by path conversion functions when $build is *nix, and -# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly -# configured wine environment available, with the winepath program in $build's -# $PATH. Assumes ARG has no leading or trailing path separator characters. -# -# ARG is path to be converted from $build format to win32. -# Result is available in $func_convert_core_path_wine_to_w32_result. -# Unconvertible file (directory) names in ARG are skipped; if no directory names -# are convertible, then the result may be empty. -func_convert_core_path_wine_to_w32 () -{ - $opt_debug - # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" - if test -n "$1"; then - oldIFS=$IFS - IFS=: - for func_convert_core_path_wine_to_w32_f in $1; do - IFS=$oldIFS - func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then - if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" - else - func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" - fi - fi - done - IFS=$oldIFS - fi -} -# end: func_convert_core_path_wine_to_w32 - - -# func_cygpath ARGS... -# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when -# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) -# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or -# (2), returns the Cygwin file name or path in func_cygpath_result (input -# file name or path is assumed to be in w32 format, as previously converted -# from $build's *nix or MSYS format). In case (3), returns the w32 file name -# or path in func_cygpath_result (input file name or path is assumed to be in -# Cygwin format). Returns an empty string on error. -# -# ARGS are passed to cygpath, with the last one being the file name or path to -# be converted. -# -# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH -# environment variable; do not put it in $PATH. -func_cygpath () -{ - $opt_debug - if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then - func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` - if test "$?" -ne 0; then - # on failure, ensure result is empty - func_cygpath_result= - fi - else - func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" - fi -} -#end: func_cygpath - - -# func_convert_core_msys_to_w32 ARG -# Convert file name or path ARG from MSYS format to w32 format. Return -# result in func_convert_core_msys_to_w32_result. -func_convert_core_msys_to_w32 () -{ - $opt_debug - # awkward: cmd appends spaces to result - func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` -} -#end: func_convert_core_msys_to_w32 - - -# func_convert_file_check ARG1 ARG2 -# Verify that ARG1 (a file name in $build format) was converted to $host -# format in ARG2. Otherwise, emit an error message, but continue (resetting -# func_to_host_file_result to ARG1). -func_convert_file_check () -{ - $opt_debug - if test -z "$2" && test -n "$1" ; then - func_error "Could not determine host file name corresponding to" - func_error " \`$1'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback: - func_to_host_file_result="$1" - fi -} -# end func_convert_file_check - - -# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH -# Verify that FROM_PATH (a path in $build format) was converted to $host -# format in TO_PATH. Otherwise, emit an error message, but continue, resetting -# func_to_host_file_result to a simplistic fallback value (see below). -func_convert_path_check () -{ - $opt_debug - if test -z "$4" && test -n "$3"; then - func_error "Could not determine the host path corresponding to" - func_error " \`$3'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback. This is a deliberately simplistic "conversion" and - # should not be "improved". See libtool.info. - if test "x$1" != "x$2"; then - lt_replace_pathsep_chars="s|$1|$2|g" - func_to_host_path_result=`echo "$3" | - $SED -e "$lt_replace_pathsep_chars"` - else - func_to_host_path_result="$3" - fi - fi -} -# end func_convert_path_check - - -# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG -# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT -# and appending REPL if ORIG matches BACKPAT. -func_convert_path_front_back_pathsep () -{ - $opt_debug - case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" - ;; - esac - case $4 in - $2 ) func_append func_to_host_path_result "$3" - ;; - esac -} -# end func_convert_path_front_back_pathsep - - -################################################## -# $build to $host FILE NAME CONVERSION FUNCTIONS # -################################################## -# invoked via `$to_host_file_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# Result will be available in $func_to_host_file_result. - - -# func_to_host_file ARG -# Converts the file name ARG from $build format to $host format. Return result -# in func_to_host_file_result. -func_to_host_file () -{ - $opt_debug - $to_host_file_cmd "$1" -} -# end func_to_host_file - - -# func_to_tool_file ARG LAZY -# converts the file name ARG from $build format to toolchain format. Return -# result in func_to_tool_file_result. If the conversion in use is listed -# in (the comma separated) LAZY, no conversion takes place. -func_to_tool_file () -{ - $opt_debug - case ,$2, in - *,"$to_tool_file_cmd",*) - func_to_tool_file_result=$1 - ;; - *) - $to_tool_file_cmd "$1" - func_to_tool_file_result=$func_to_host_file_result - ;; - esac -} -# end func_to_tool_file - - -# func_convert_file_noop ARG -# Copy ARG to func_to_host_file_result. -func_convert_file_noop () -{ - func_to_host_file_result="$1" -} -# end func_convert_file_noop - - -# func_convert_file_msys_to_w32 ARG -# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_file_result. -func_convert_file_msys_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_w32 - - -# func_convert_file_cygwin_to_w32 ARG -# Convert file name ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_file_cygwin_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # because $build is cygwin, we call "the" cygpath in $PATH; no need to use - # LT_CYGPATH in this case. - func_to_host_file_result=`cygpath -m "$1"` - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_cygwin_to_w32 - - -# func_convert_file_nix_to_w32 ARG -# Convert file name ARG from *nix to w32 format. Requires a wine environment -# and a working winepath. Returns result in func_to_host_file_result. -func_convert_file_nix_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_w32 - - -# func_convert_file_msys_to_cygwin ARG -# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_file_msys_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_cygwin - - -# func_convert_file_nix_to_cygwin ARG -# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed -# in a wine environment, working winepath, and LT_CYGPATH set. Returns result -# in func_to_host_file_result. -func_convert_file_nix_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. - func_convert_core_file_wine_to_w32 "$1" - func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_cygwin - - -############################################# -# $build to $host PATH CONVERSION FUNCTIONS # -############################################# -# invoked via `$to_host_path_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# The result will be available in $func_to_host_path_result. -# -# Path separators are also converted from $build format to $host format. If -# ARG begins or ends with a path separator character, it is preserved (but -# converted to $host format) on output. -# -# All path conversion functions are named using the following convention: -# file name conversion function : func_convert_file_X_to_Y () -# path conversion function : func_convert_path_X_to_Y () -# where, for any given $build/$host combination the 'X_to_Y' value is the -# same. If conversion functions are added for new $build/$host combinations, -# the two new functions must follow this pattern, or func_init_to_host_path_cmd -# will break. - - -# func_init_to_host_path_cmd -# Ensures that function "pointer" variable $to_host_path_cmd is set to the -# appropriate value, based on the value of $to_host_file_cmd. -to_host_path_cmd= -func_init_to_host_path_cmd () -{ - $opt_debug - if test -z "$to_host_path_cmd"; then - func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" - fi -} - - -# func_to_host_path ARG -# Converts the path ARG from $build format to $host format. Return result -# in func_to_host_path_result. -func_to_host_path () -{ - $opt_debug - func_init_to_host_path_cmd - $to_host_path_cmd "$1" -} -# end func_to_host_path - - -# func_convert_path_noop ARG -# Copy ARG to func_to_host_path_result. -func_convert_path_noop () -{ - func_to_host_path_result="$1" -} -# end func_convert_path_noop - - -# func_convert_path_msys_to_w32 ARG -# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_path_result. -func_convert_path_msys_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from ARG. MSYS - # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; - # and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_msys_to_w32 - - -# func_convert_path_cygwin_to_w32 ARG -# Convert path ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_path_cygwin_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_cygwin_to_w32 - - -# func_convert_path_nix_to_w32 ARG -# Convert path ARG from *nix to w32 format. Requires a wine environment and -# a working winepath. Returns result in func_to_host_file_result. -func_convert_path_nix_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_nix_to_w32 - - -# func_convert_path_msys_to_cygwin ARG -# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_path_msys_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_msys_to_cygwin - - -# func_convert_path_nix_to_cygwin ARG -# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a -# a wine environment, working winepath, and LT_CYGPATH set. Returns result in -# func_to_host_file_result. -func_convert_path_nix_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from - # ARG. msys behavior is inconsistent here, cygpath turns them - # into '.;' and ';.', and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_nix_to_cygwin - - -# func_mode_compile arg... -func_mode_compile () -{ - $opt_debug - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - pie_flag= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" - arg_mode=target - continue - ;; - - -pie | -fpie | -fPIE) - func_append pie_flag " $arg" - continue - ;; - - -shared | -static | -prefer-pic | -prefer-non-pic) - func_append later " $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - func_append_quoted lastarg "$arg" - done - IFS="$save_ifs" - func_stripname ' ' '' "$lastarg" - lastarg=$func_stripname_result - - # Add the arguments to base_compile. - func_append base_compile " $lastarg" - continue - ;; - - *) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - func_append_quoted base_compile "$lastarg" - done # for arg - - case $arg_mode in - arg) - func_fatal_error "you must specify an argument for -Xcompile" - ;; - target) - func_fatal_error "you must specify a target with \`-o'" - ;; - *) - # Get the name of the library object. - test -z "$libobj" && { - func_basename "$srcfile" - libobj="$func_basename_result" - } - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - case $libobj in - *.[cCFSifmso] | \ - *.ada | *.adb | *.ads | *.asm | \ - *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ - *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) - func_xform "$libobj" - libobj=$func_xform_result - ;; - esac - - case $libobj in - *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; - *) - func_fatal_error "cannot determine name of library object from \`$libobj'" - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - continue - ;; - - -static) - build_libtool_libs=no - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ - && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." - func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname - - test -z "$base_compile" && \ - func_fatal_help "you must specify a compilation command" - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2* | cegcc*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $ECHO "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - func_append removelist " $output_obj" - $ECHO "$srcfile" > "$lockfile" - fi - - $opt_dry_run || $RM $removelist - func_append removelist " $lockfile" - trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - - func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 - srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result - - # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - if test "$pic_mode" != no; then - command="$base_compile $qsrcfile $pic_flag" - else - # Don't build PIC code - command="$base_compile $qsrcfile" - fi - - func_mkdir_p "$xdir$objdir" - - if test -z "$output_obj"; then - # Place PIC objects in $objdir - func_append command " -o $lobj" - fi - - func_show_eval_locale "$command" \ - 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - func_show_eval '$MV "$output_obj" "$lobj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - - # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then - suppress_output=' >/dev/null 2>&1' - fi - fi - - # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then - # Don't build PIC code - command="$base_compile $qsrcfile$pie_flag" - else - command="$base_compile $qsrcfile $pic_flag" - fi - if test "$compiler_c_o" = yes; then - func_append command " -o $obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - func_append command "$suppress_output" - func_show_eval_locale "$command" \ - '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - func_show_eval '$MV "$output_obj" "$obj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - fi - - $opt_dry_run || { - func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" - - # Unlock the critical section if it was locked - if test "$need_locks" != no; then - removelist=$lockfile - $RM "$lockfile" - fi - } - - exit $EXIT_SUCCESS -} - -$opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} -} - -func_mode_help () -{ - # We need to display help for each of the modes. - case $opt_mode in - "") - # Generic help is extracted from the usage comments - # at the start of this file. - func_help - ;; - - clean) - $ECHO \ -"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - - compile) - $ECHO \ -"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to build PIC objects only - -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - - execute) - $ECHO \ -"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - - finish) - $ECHO \ -"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - - install) - $ECHO \ -"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The following components of INSTALL-COMMAND are treated specially: - - -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - - link) - $ECHO \ -"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -bindir BINDIR specify path to binaries directory (for systems where - libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -shared only do dynamic linking of libtool libraries - -shrext SUFFIX override the standard shared library file extension - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -weak LIBNAME declare that the target provides the LIBNAME interface - -Wc,FLAG - -Xcompiler FLAG pass linker-specific FLAG directly to the compiler - -Wl,FLAG - -Xlinker FLAG pass linker-specific FLAG directly to the linker - -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - - uninstall) - $ECHO \ -"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - - *) - func_fatal_help "invalid operation mode \`$opt_mode'" - ;; - esac - - echo - $ECHO "Try \`$progname --help' for more information about other modes." -} - -# Now that we've collected a possible --mode arg, show help if necessary -if $opt_help; then - if test "$opt_help" = :; then - func_mode_help - else - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - func_mode_help - done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - echo - func_mode_help - done - } | - sed '1d - /^When reporting/,/^Report/{ - H - d - } - $x - /information about other modes/d - /more detailed .*MODE/d - s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' - fi - exit $? -fi - - -# func_mode_execute arg... -func_mode_execute () -{ - $opt_debug - # The first argument is the command name. - cmd="$nonopt" - test -z "$cmd" && \ - func_fatal_help "you must specify a COMMAND" - - # Handle -dlopen flags immediately. - for file in $opt_dlopen; do - test -f "$file" \ - || func_fatal_help "\`$file' is not a file" - - dir= - case $file in - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" - - # Read the libtool library. - dlname= - library_names= - func_source "$file" - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" - continue - fi - - func_dirname "$file" "" "." - dir="$func_dirname_result" - - if test -f "$dir/$objdir/$dlname"; then - func_append dir "/$objdir" - else - if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - func_dirname "$file" "" "." - dir="$func_dirname_result" - ;; - - *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -* | *.la | *.lo ) ;; - *) - # Do a test to see if this is really a libtool program. - if func_ltwrapper_script_p "$file"; then - func_source "$file" - # Transform arg to wrapped name. - file="$progdir/$program" - elif func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - func_source "$func_ltwrapper_scriptname_result" - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - func_append_quoted args "$file" - done - - if test "X$opt_dry_run" = Xfalse; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} - - -# func_mode_finish arg... -func_mode_finish () -{ - $opt_debug - libs= - libdirs= - admincmds= - - for opt in "$nonopt" ${1+"$@"} - do - if test -d "$opt"; then - func_append libdirs " $opt" - - elif test -f "$opt"; then - if func_lalib_unsafe_p "$opt"; then - func_append libs " $opt" - else - func_warning "\`$opt' is not a valid libtool archive" - fi - - else - func_fatal_error "invalid argument \`$opt'" - fi - done - - if test -n "$libs"; then - if test -n "$lt_sysroot"; then - sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` - sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" - else - sysroot_cmd= - fi - - # Remove sysroot references - if $opt_dry_run; then - for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" - done - else - tmpdir=`func_mktempdir` - for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ - > $tmpdir/tmp-la - mv -f $tmpdir/tmp-la $lib - done - ${RM}r "$tmpdir" - fi - fi - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - func_execute_cmds "$finish_cmds" 'admincmds="$admincmds -'"$cmd"'"' - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || func_append admincmds " - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $ECHO " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - echo - - echo "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" - echo "pages." - ;; - *) - echo "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - echo "----------------------------------------------------------------------" - fi - exit $EXIT_SUCCESS -} - -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} - - -# func_mode_install arg... -func_mode_install () -{ - $opt_debug - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then - # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " - arg=$1 - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" - install_shared_prog=$install_prog - case " $install_prog " in - *[\\\ /]cp\ *) install_cp=: ;; - *) install_cp=false ;; - esac - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - no_mode=: - for arg - do - arg2= - if test -n "$dest"; then - func_append files " $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) - if $install_cp; then :; else - prev=$arg - fi - ;; - -g | -m | -o) - prev=$arg - ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then - arg2=$install_override_mode - no_mode=false - fi - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" - if test -n "$arg2"; then - func_quote_for_eval "$arg2" - fi - func_append install_shared_prog " $func_quote_for_eval_result" - done - - test -z "$install_prog" && \ - func_fatal_help "you must specify an install program" - - test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" - - if test -n "$install_override_mode" && $no_mode; then - if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" - fi - fi - - if test -z "$files"; then - if test -z "$dest"; then - func_fatal_help "no file or destination specified" - else - func_fatal_help "you must specify a destination" - fi - fi - - # Strip any trailing slash from the destination. - func_stripname '' '/' "$dest" - dest=$func_stripname_result - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" - - # Not a directory, so check to see that there is only one file specified. - set dummy $files; shift - test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - func_fatal_help "\`$destdir' must be an absolute directory name" - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - func_append staticlibs " $file" - ;; - - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" - - library_names= - old_library= - relink_command= - func_source "$file" - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) func_append current_libdirs " $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) func_append future_libdirs " $libdir" ;; - esac - fi - - func_dirname "$file" "/" "" - dir="$func_dirname_result" - func_append dir "$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - func_warning "relinking \`$file'" - func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' - fi - - # See the names of the shared library. - set dummy $library_names; shift - if test -n "$1"; then - realname="$1" - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ - 'exit $?' - tstripme="$stripme" - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - case $realname in - *.dll.a) - tstripme="" - ;; - esac - ;; - esac - if test -n "$tstripme" && test -n "$striplib"; then - func_show_eval "$striplib $destdir/$realname" 'exit $?' - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - test "$linkname" != "$realname" \ - && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - func_execute_cmds "$postinstall_cmds" 'exit $?' - fi - - # Install the pseudo-library for information purposes. - func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i - func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' - - # Maybe install the static library, too. - test -n "$old_library" && func_append staticlibs " $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - func_lo2o "$destfile" - staticdest=$func_lo2o_result - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" - ;; - esac - - # Install the libtool object if requested. - test -n "$destfile" && \ - func_show_eval "$install_prog $file $destfile" 'exit $?' - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - func_lo2o "$file" - staticobj=$func_lo2o_result - func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - func_stripname '' '.exe' "$file" - file=$func_stripname_result - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin* | *mingw*) - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - wrapper=$func_ltwrapper_scriptname_result - else - func_stripname '' '.exe' "$file" - wrapper=$func_stripname_result - fi - ;; - *) - wrapper=$file - ;; - esac - if func_ltwrapper_script_p "$wrapper"; then - notinst_deplibs= - relink_command= - - func_source "$wrapper" - - # Check the variables that should have been set. - test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - func_source "$lib" - fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no - fi - done - - relink_command= - func_source "$wrapper" - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - $opt_dry_run || { - if test "$finalize" = yes; then - tmpdir=`func_mktempdir` - func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - - $opt_silent || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" - } - if eval "$relink_command"; then : - else - func_error "error: relink \`$file' with the above command before installing it" - $opt_dry_run || ${RM}r "$tmpdir" - continue - fi - file="$outputname" - else - func_warning "cannot relink \`$file'" - fi - } - else - # Install the binary that we compiled earlier. - file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - func_stripname '' '.exe' "$destfile" - destfile=$func_stripname_result - ;; - esac - ;; - esac - func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' - $opt_dry_run || if test -n "$outputname"; then - ${RM}r "$tmpdir" - fi - ;; - esac - done - - for file in $staticlibs; do - func_basename "$file" - name="$func_basename_result" - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - - func_show_eval "$install_prog \$file \$oldlib" 'exit $?' - - if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $tool_oldlib" 'exit $?' - fi - - # Do each command in the postinstall commands. - func_execute_cmds "$old_postinstall_cmds" 'exit $?' - done - - test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = install && func_mode_install ${1+"$@"} - - -# func_generate_dlsyms outputname originator pic_p -# Extract symbols from dlprefiles and create ${outputname}S.o with -# a dlpreopen symbol table. -func_generate_dlsyms () -{ - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` - my_dlsyms= - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" - else - func_error "not configured to extract global symbols from dlpreopened files" - fi - fi - - if test -n "$my_dlsyms"; then - case $my_dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" - - func_show_eval "$RM $nlist ${nlist}S ${nlist}T" - - # Parse the name list into a source file. - func_verbose "creating $output_objdir/$my_dlsyms" - - $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) -#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" -#endif - -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined(__osf__) -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" - - $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` - for progfile in $progfiles; do - func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" - $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $opt_dry_run || { - eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - if test -n "$export_symbols_regex"; then - $opt_dry_run || { - eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" - $opt_dry_run || { - $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - } - else - $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - } - fi - fi - - for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" - func_basename "$dlprefile" - name="$func_basename_result" - case $host in - *cygwin* | *mingw* | *cegcc* ) - # if an import library, we need to obtain dlname - if func_win32_import_lib_p "$dlprefile"; then - func_tr_sh "$dlprefile" - eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" - if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then - # Use subshell, to avoid clobbering current variable values - dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then - func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" - else - # no lafile. user explicitly requested -dlpreopen . - $sharedlib_from_linklib_cmd "$dlprefile" - dlprefile_dlbasename=$sharedlib_from_linklib_result - fi - fi - $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then - eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' - else - func_warning "Could not compute DLL name from $name" - eval '$ECHO ": $name " >> "$nlist"' - fi - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | - $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" - } - else # not an import lib - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - fi - ;; - *) - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - ;; - esac - done - - $opt_dry_run || { - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $MV "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$my_dlsyms" - fi - - echo >> "$output_objdir/$my_dlsyms" "\ - -/* The mapping between symbol names and symbols. */ -typedef struct { - const char *name; - void *address; -} lt_dlsymlist; -extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; -LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," - - case $need_lib_prefix in - no) - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - *) - eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - esac - echo >> "$output_objdir/$my_dlsyms" "\ - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_${my_prefix}_LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - } # !$opt_dry_run - - pic_flag_for_symtable= - case "$compile_command " in - *" -static "*) ;; - *) - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; - *-*-hpux*) - pic_flag_for_symtable=" $pic_flag" ;; - *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi - ;; - esac - ;; - esac - symtab_cflags= - for arg in $LTCFLAGS; do - case $arg in - -pie | -fpie | -fPIE) ;; - *) func_append symtab_cflags " $arg" ;; - esac - done - - # Now compile the dynamic symbol file. - func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' - - # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' - - # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" - case $host in - *cygwin* | *mingw* | *cegcc* ) - if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - else - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - fi - ;; - *) - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - ;; - esac - ;; - *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` - fi -} - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -# Despite the name, also deal with 64 bit binaries. -func_win32_libid () -{ - $opt_debug - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' - 1,100{ - / I /{ - s,.*,import, - p - q - } - }'` - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $ECHO "$win32_libid_type" -} - -# func_cygming_dll_for_implib ARG -# -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib () -{ - $opt_debug - sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` -} - -# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs -# -# The is the core of a fallback implementation of a -# platform-specific function to extract the name of the -# DLL associated with the specified import library LIBNAME. -# -# SECTION_NAME is either .idata$6 or .idata$7, depending -# on the platform and compiler that created the implib. -# -# Echos the name of the DLL associated with the -# specified import library. -func_cygming_dll_for_implib_fallback_core () -{ - $opt_debug - match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` - $OBJDUMP -s --section "$1" "$2" 2>/dev/null | - $SED '/^Contents of section '"$match_literal"':/{ - # Place marker at beginning of archive member dllname section - s/.*/====MARK====/ - p - d - } - # These lines can sometimes be longer than 43 characters, but - # are always uninteresting - /:[ ]*file format pe[i]\{,1\}-/d - /^In archive [^:]*:/d - # Ensure marker is printed - /^====MARK====/p - # Remove all lines with less than 43 characters - /^.\{43\}/!d - # From remaining lines, remove first 43 characters - s/^.\{43\}//' | - $SED -n ' - # Join marker and all lines until next marker into a single line - /^====MARK====/ b para - H - $ b para - b - :para - x - s/\n//g - # Remove the marker - s/^====MARK====// - # Remove trailing dots and whitespace - s/[\. \t]*$// - # Print - /./p' | - # we now have a list, one entry per line, of the stringified - # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is - # a '.' (that is, objdump's representation of an unprintable - # character.) This should work for all archives with less than - # 0x302f exports -- but will fail for DLLs whose name actually - # begins with a literal '.' or a single character followed by - # a '.'. - # - # Of those that remain, print the first one. - $SED -e '/^\./d;/^.\./d;q' -} - -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - -# func_cygming_dll_for_implib_fallback ARG -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# -# This fallback implementation is for use when $DLLTOOL -# does not support the --identify-strict option. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib_fallback () -{ - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then - # binutils import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then - # ms-generated import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` - else - # unknown - sharedlib_from_linklib_result="" - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then - lockfile=$f_ex_an_ar_oldlib.lock - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - fi - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ - 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then - $opt_dry_run || rm -f "$lockfile" - fi - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" - fi -} - - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - $opt_debug - my_gentop="$1"; shift - my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - func_basename "$my_xlib" - my_xlib="$func_basename_result" - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - func_arith $extracted_serial + 1 - extracted_serial=$func_arith_result - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" - - func_mkdir_p "$my_xdir" - - case $host in - *-darwin*) - func_verbose "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - $opt_dry_run || { - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` - darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` - if test -n "$darwin_arches"; then - darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" - cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" - done # $darwin_arches - ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` - $LIPO -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - $RM -rf unfat-$$ - cd "$darwin_orig_dir" - else - cd $darwin_orig_dir - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - } # !$opt_dry_run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` - done - - func_extract_archives_result="$my_oldobjs" -} - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=${1-no} - - $ECHO "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variables: - generated_by_libtool_version='$macro_version' - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$ECHO are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` - $ECHO "\ - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - ECHO=\"$qECHO\" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on -# windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's $0 value, followed by "$@". -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=\$0 - shift - for lt_opt - do - case \"\$lt_opt\" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` - test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. - lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` - cat \"\$lt_dump_D/\$lt_dump_F\" - exit 0 - ;; - --lt-*) - \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" - lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from \$@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case \" \$* \" in - *\\ --lt-*) - for lt_wr_arg - do - case \$lt_wr_arg in - --lt-*) ;; - *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; - esac - shift - done ;; - esac - func_exec_program_core \${1+\"\$@\"} -} - - # Parse options - func_parse_lt_options \"\$0\" \${1+\"\$@\"} - - # Find the directory that this script lives in. - thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 - if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then - # special case for '.' - if test \"\$thisdir\" = \".\"; then - thisdir=\`pwd\` - fi - # remove .libs from thisdir - case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; - $objdir ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $ECHO "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $MKDIR \"\$progdir\" - else - $RM \"\$progdir/\$file\" - fi" - - $ECHO "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $ECHO \"\$relink_command_output\" >&2 - $RM \"\$progdir/\$file\" - exit 1 - fi - fi - - $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $RM \"\$progdir/\$program\"; - $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $RM \"\$progdir/\$file\" - fi" - else - $ECHO "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $ECHO "\ - - if test -f \"\$progdir/\$program\"; then" - - # fixup the dll searchpath if we need to. - # - # Fix the DLL searchpath if we need to. Do this before prepending - # to shlibpath, because on Windows, both are PATH and uninstalled - # libraries must come first. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $ECHO "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` - - export $shlibpath_var -" - fi - - $ECHO "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. - func_exec_program \${1+\"\$@\"} - fi - else - # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 - \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" -} - - -# func_emit_cwrapperexe_src -# emit the source code for a wrapper executable on stdout -# Must ONLY be called from within func_mode_link because -# it depends on a number of variable set therein. -func_emit_cwrapperexe_src () -{ - cat < -#include -#ifdef _MSC_VER -# include -# include -# include -#else -# include -# include -# ifdef __CYGWIN__ -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -/* declarations of non-ANSI functions */ -#if defined(__MINGW32__) -# ifdef __STRICT_ANSI__ -int _putenv (const char *); -# endif -#elif defined(__CYGWIN__) -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif -/* #elif defined (other platforms) ... */ -#endif - -/* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -# define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -#elif defined(__CYGWIN__) -# define HAVE_SETENV -# define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ -#endif - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef S_IXOTH -# define S_IXOTH 0 -#endif -#ifndef S_IXGRP -# define S_IXGRP 0 -#endif - -/* path handling portability macros */ -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -# define HAVE_DOS_BASED_FILE_SYSTEM -# define FOPEN_WB "wb" -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#ifndef FOPEN_WB -# define FOPEN_WB "w" -#endif -#ifndef _O_BINARY -# define _O_BINARY 0 -#endif - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -#if defined(LT_DEBUGWRAPPER) -static int lt_debug = 1; -#else -static int lt_debug = 0; -#endif - -const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ - -void *xmalloc (size_t num); -char *xstrdup (const char *string); -const char *base_name (const char *name); -char *find_executable (const char *wrapper); -char *chase_symlinks (const char *pathspec); -int make_executable (const char *path); -int check_executable (const char *path); -char *strendzap (char *str, const char *pat); -void lt_debugprintf (const char *file, int line, const char *fmt, ...); -void lt_fatal (const char *file, int line, const char *message, ...); -static const char *nonnull (const char *s); -static const char *nonempty (const char *s); -void lt_setenv (const char *name, const char *value); -char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_update_exe_path (const char *name, const char *value); -void lt_update_lib_path (const char *name, const char *value); -char **prepare_spawn (char **argv); -void lt_dump_script (FILE *f); -EOF - - cat <= 0) - && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - return 1; - else - return 0; -} - -int -make_executable (const char *path) -{ - int rval = 0; - struct stat st; - - lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", - nonempty (path)); - if ((!path) || (!*path)) - return 0; - - if (stat (path, &st) >= 0) - { - rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); - } - return rval; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise - Does not chase symlinks, even on platforms that support them. -*/ -char * -find_executable (const char *wrapper) -{ - int has_slash = 0; - const char *p; - const char *p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - int tmp_len; - char *concat_name; - - lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", - nonempty (wrapper)); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char *path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char *q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR (*q)) - break; - p_len = q - p; - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = - XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = - XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - return NULL; -} - -char * -chase_symlinks (const char *pathspec) -{ -#ifndef S_ISLNK - return xstrdup (pathspec); -#else - char buf[LT_PATHMAX]; - struct stat s; - char *tmp_pathspec = xstrdup (pathspec); - char *p; - int has_symlinks = 0; - while (strlen (tmp_pathspec) && !has_symlinks) - { - lt_debugprintf (__FILE__, __LINE__, - "checking path component for symlinks: %s\n", - tmp_pathspec); - if (lstat (tmp_pathspec, &s) == 0) - { - if (S_ISLNK (s.st_mode) != 0) - { - has_symlinks = 1; - break; - } - - /* search backwards for last DIR_SEPARATOR */ - p = tmp_pathspec + strlen (tmp_pathspec) - 1; - while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - p--; - if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - { - /* no more DIR_SEPARATORS left */ - break; - } - *p = '\0'; - } - else - { - lt_fatal (__FILE__, __LINE__, - "error accessing file \"%s\": %s", - tmp_pathspec, nonnull (strerror (errno))); - } - } - XFREE (tmp_pathspec); - - if (!has_symlinks) - { - return xstrdup (pathspec); - } - - tmp_pathspec = realpath (pathspec, buf); - if (tmp_pathspec == 0) - { - lt_fatal (__FILE__, __LINE__, - "could not follow symlinks for %s", pathspec); - } - return xstrdup (tmp_pathspec); -#endif -} - -char * -strendzap (char *str, const char *pat) -{ - size_t len, patlen; - - assert (str != NULL); - assert (pat != NULL); - - len = strlen (str); - patlen = strlen (pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp (str, pat) == 0) - *str = '\0'; - } - return str; -} - -void -lt_debugprintf (const char *file, int line, const char *fmt, ...) -{ - va_list args; - if (lt_debug) - { - (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); - } -} - -static void -lt_error_core (int exit_status, const char *file, - int line, const char *mode, - const char *message, va_list ap) -{ - fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *file, int line, const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); - va_end (ap); -} - -static const char * -nonnull (const char *s) -{ - return s ? s : "(null)"; -} - -static const char * -nonempty (const char *s) -{ - return (s && !*s) ? "(empty)" : nonnull (s); -} - -void -lt_setenv (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_setenv) setting '%s' to '%s'\n", - nonnull (name), nonnull (value)); - { -#ifdef HAVE_SETENV - /* always make a copy, for consistency with !HAVE_SETENV */ - char *str = xstrdup (value); - setenv (name, str, 1); -#else - int len = strlen (name) + 1 + strlen (value) + 1; - char *str = XMALLOC (char, len); - sprintf (str, "%s=%s", name, value); - if (putenv (str) != EXIT_SUCCESS) - { - XFREE (str); - } -#endif - } -} - -char * -lt_extend_str (const char *orig_value, const char *add, int to_end) -{ - char *new_value; - if (orig_value && *orig_value) - { - int orig_value_len = strlen (orig_value); - int add_len = strlen (add); - new_value = XMALLOC (char, add_len + orig_value_len + 1); - if (to_end) - { - strcpy (new_value, orig_value); - strcpy (new_value + orig_value_len, add); - } - else - { - strcpy (new_value, add); - strcpy (new_value + add_len, orig_value); - } - } - else - { - new_value = xstrdup (add); - } - return new_value; -} - -void -lt_update_exe_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - /* some systems can't cope with a ':'-terminated path #' */ - int len = strlen (new_value); - while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) - { - new_value[len-1] = '\0'; - } - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -void -lt_update_lib_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -EOF - case $host_os in - mingw*) - cat <<"EOF" - -/* Prepares an argument vector before calling spawn(). - Note that spawn() does not by itself call the command interpreter - (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : - ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&v); - v.dwPlatformId == VER_PLATFORM_WIN32_NT; - }) ? "cmd.exe" : "command.com"). - Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() - interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a - special way: - - Space and tab are interpreted as delimiters. They are not treated as - delimiters if they are surrounded by double quotes: "...". - - Unescaped double quotes are removed from the input. Their only effect is - that within double quotes, space and tab are treated like normal - characters. - - Backslashes not followed by double quotes are not special. - - But 2*n+1 backslashes followed by a double quote become - n backslashes followed by a double quote (n >= 0): - \" -> " - \\\" -> \" - \\\\\" -> \\" - */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -char ** -prepare_spawn (char **argv) -{ - size_t argc; - char **new_argv; - size_t i; - - /* Count number of arguments. */ - for (argc = 0; argv[argc] != NULL; argc++) - ; - - /* Allocate new argument vector. */ - new_argv = XMALLOC (char *, argc + 1); - - /* Put quoted arguments into the new argument vector. */ - for (i = 0; i < argc; i++) - { - const char *string = argv[i]; - - if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); - else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = XMALLOC (char, length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } - else - new_argv[i] = (char *) string; - } - new_argv[argc] = NULL; - - return new_argv; -} -EOF - ;; - esac - - cat <<"EOF" -void lt_dump_script (FILE* f) -{ -EOF - func_emit_wrapper yes | - $SED -n -e ' -s/^\(.\{79\}\)\(..*\)/\1\ -\2/ -h -s/\([\\"]\)/\\\1/g -s/$/\\n/ -s/\([^\n]*\).*/ fputs ("\1", f);/p -g -D' - cat <<"EOF" -} -EOF -} -# end: func_emit_cwrapperexe_src - -# func_win32_import_lib_p ARG -# True if ARG is an import lib, as indicated by $file_magic_cmd -func_win32_import_lib_p () -{ - $opt_debug - case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in - *import*) : ;; - *) false ;; - esac -} - -# func_mode_link arg... -func_mode_link () -{ - $opt_debug - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra - # flag for every libtool invocation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - ;; - *) - allow_undefined=yes - ;; - esac - libtool_args=$nonopt - base_compile="$nonopt $@" - compile_command=$nonopt - finalize_command=$nonopt - - compile_rpath= - finalize_rpath= - compile_shlibpath= - finalize_shlibpath= - convenience= - old_convenience= - deplibs= - old_deplibs= - compiler_flags= - linker_flags= - dllsearchpath= - lib_search_path=`pwd` - inst_prefix_dir= - new_inherited_linker_flags= - - avoid_version=no - bindir= - dlfiles= - dlprefiles= - dlself=no - export_dynamic=no - export_symbols= - export_symbols_regex= - generated= - libobjs= - ltlibs= - module=no - no_install=no - objs= - non_pic_objects= - precious_files_regex= - prefer_static_libs=no - preload=no - prev= - prevarg= - release= - rpath= - xrpath= - perm_rpath= - temp_rpath= - thread_safe=no - vinfo= - vinfo_number=no - weak_libs= - single_module="${wl}-single_module" - func_infer_tag $base_compile - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - break - ;; - -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then - func_warning "complete static linking is impossible in this configuration" - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - func_append compile_command " @OUTPUT@" - func_append finalize_command " @OUTPUT@" - ;; - esac - - case $prev in - bindir) - bindir="$arg" - prev= - continue - ;; - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - func_append compile_command " @SYMFILE@" - func_append finalize_command " @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - func_append dlfiles " $arg" - else - func_append dlprefiles " $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - framework) - case $host in - *-*-darwin*) - case "$deplibs " in - *" $qarg.ltframework "*) ;; - *) func_append deplibs " $qarg.ltframework" # this is fixed later - ;; - esac - ;; - esac - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat "$save_arg"` - do -# func_append moreargs " $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - done - else - func_fatal_error "link input file \`$arg' does not exist" - fi - arg=$save_arg - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) func_append rpath " $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) func_append xrpath " $arg" ;; - esac - fi - prev= - continue - ;; - shrext) - shrext_cmds="$arg" - prev= - continue - ;; - weak) - func_append weak_libs " $arg" - prev= - continue - ;; - xcclinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xcompiler) - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xlinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $wl$qarg" - prev= - func_append compile_command " $wl$qarg" - func_append finalize_command " $wl$qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - # See comment for -static flag below, for more details. - func_append compile_command " $link_static_flag" - func_append finalize_command " $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -bindir) - prev=bindir - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - func_fatal_error "more than one -exported-symbols argument is not allowed" - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework) - prev=framework - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - func_append compile_command " $arg" - func_append finalize_command " $arg" - ;; - esac - continue - ;; - - -L*) - func_stripname "-L" '' "$arg" - if test -z "$func_stripname_result"; then - if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" - else - func_fatal_error "need path for \`-L' option" - fi - fi - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "* | *" $arg "*) - # Will only happen for absolute or sysroot arguments - ;; - *) - # Preserve sysroot, but never include relative directories - case $dir in - [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; - *) func_append deplibs " -L$dir" ;; - esac - func_append lib_search_path " $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - ::) dllsearchpath=$dir;; - *) func_append dllsearchpath ":$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - func_append deplibs " System.ltframework" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test "X$arg" = "X-lc" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue - ;; - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - func_append deplibs " $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot|--sysroot) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case "$new_inherited_linker_flags " in - *" $arg "*) ;; - * ) func_append new_inherited_linker_flags " $arg" ;; - esac - continue - ;; - - -multi_module) - single_module="${wl}-multi_module" - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - func_stripname '-R' '' "$arg" - dir=$func_stripname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - =*) - func_stripname '=' '' "$dir" - dir=$lt_sysroot$func_stripname_result - ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - continue - ;; - - -shared) - # The effects of -shared are defined in a previous loop. - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -weak) - prev=weak - continue - ;; - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Wl,*) - func_stripname '-Wl,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # -msg_* for osf cc - -msg_*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - # Flags to be passed through unchanged, with rationale: - # -64, -mips[0-9] enable 64-bit mode for the SGI compiler - # -r[0-9][0-9]* specify processor for the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler - # +DA*, +DD* enable 64-bit mode for the HP compiler - # -q* compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* architecture-specific flags for GCC - # -F/path path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # @file GCC response files - # -tp=* Portland pgcc target processor selection - # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - func_append compile_command " $arg" - func_append finalize_command " $arg" - func_append compiler_flags " $arg" - continue - ;; - - # Some other compiler flag. - -* | +*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - *.$objext) - # A standard object. - func_append objs " $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - ;; - - *.$libext) - # An archive. - func_append deplibs " $arg" - func_append old_deplibs " $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - func_append dlfiles " $func_resolve_sysroot_result" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - func_append dlprefiles " $func_resolve_sysroot_result" - prev= - else - func_append deplibs " $func_resolve_sysroot_result" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - done # argument parsing loop - - test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" - func_to_tool_file "$output_objdir/" - tool_output_objdir=$func_to_tool_file_result - # Create the object directory. - func_mkdir_p "$output_objdir" - - # Determine the type of output - case $output in - "") - func_fatal_help "you must specify an output file" - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then - case "$libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append libs " $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if $opt_duplicate_compiler_generated_deps; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; - esac - func_append pre_post_deps " $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - - case $linkmode in - lib) - passes="conv dlpreopen link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - - for pass in $passes; do - # The preopen pass in lib mode reverses $deplibs; put it back here - # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then - ## FIXME: Find the place where the list is rebuilt in the wrong - ## order, and fix it there properly - tmp_deplibs= - for deplib in $deplibs; do - tmp_deplibs="$deplib $tmp_deplibs" - done - deplibs="$tmp_deplibs" - fi - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; - esac - fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then - # Collect and forward deplibs of preopened libtool libs - for lib in $dlprefiles; do - # Ignore non-libtool-libs - dependency_libs= - func_resolve_sysroot "$lib" - case $lib in - *.la) func_source "$func_resolve_sysroot_result" ;; - esac - - # Collect preopened libtool deplibs, except any this library - # has declared as weak libs - for deplib in $dependency_libs; do - func_basename "$deplib" - deplib_base=$func_basename_result - case " $weak_libs " in - *" $deplib_base "*) ;; - *) func_append deplibs " $deplib" ;; - esac - done - done - libs="$dlprefiles" - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" - continue - fi - func_stripname '-l' '' "$deplib" - name=$func_stripname_result - if test "$linkmode" = lib; then - searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" - else - searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" - fi - for searchdir in $searchdirs; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if func_lalib_p "$lib"; then - library_names= - old_library= - func_source "$lib" - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - *) - func_warning "\`-L' is ignored for archives/objects" - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - func_stripname '-R' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) - func_resolve_sysroot "$deplib" - lib=$func_resolve_sysroot_result - ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. - case " $dlpreconveniencelibs " in - *" $deplib "*) ;; - *) - valid_a_lib=no - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes - fi - ;; - pass_all) - valid_a_lib=yes - ;; - esac - if test "$valid_a_lib" != yes; then - echo - $ECHO "*** Warning: Trying to link with static lib archive $deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because the file extensions .$libext of this argument makes me believe" - echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - ;; - esac - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - func_append newdlprefiles " $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append newdlfiles " $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" - - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - inherited_linker_flags= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - func_source "$lib" - - # Convert "-framework foo" to "foo.ltframework" - if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` - for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do - case " $new_inherited_linker_flags " in - *" $tmp_inherited_linker_flag "*) ;; - *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; - esac - done - fi - dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && func_append dlfiles " $dlopen" - test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - # It is a libtool convenience library, so add in its objects. - func_append convenience " $ladir/$objdir/$old_library" - func_append old_convenience " $ladir/$objdir/$old_library" - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" - fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then - linklib=$old_library - else - for l in $old_library $library_names; do - linklib="$l" - done - fi - if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi - if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - func_append dlprefiles " $lib $dependency_libs" - else - func_append newdlfiles " $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" - func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" - fi - ;; - esac - func_basename "$lib" - laname="$func_basename_result" - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" - fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - fi - fi # $installed = yes - func_stripname 'lib' '.la' "$laname" - name=$func_stripname_result - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" - fi - case "$host" in - # special handling for platforms with PE-DLLs. - *cygwin* | *mingw* | *cegcc* ) - # Linker will automatically link against shared library if both - # static and shared are present. Therefore, ensure we extract - # symbols from the import library if a shared library is present - # (otherwise, the dlopen module name will be incorrect). We do - # this by putting the import library name into $newdlprefiles. - # We recover the dlopen module name by 'saving' the la file - # name in a special purpose variable, and (later) extracting the - # dlname from the la file. - if test -n "$dlname"; then - func_tr_sh "$dir/$linklib" - eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" - func_append newdlprefiles " $dir/$linklib" - else - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - fi - ;; - * ) - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - func_append newdlprefiles " $dir/$dlname" - else - func_append newdlprefiles " $dir/$linklib" - fi - ;; - esac - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - func_append newlib_search_path " $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in - *"$absdir:"*) ;; - *) func_append temp_rpath "$absdir:" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then - use_static_libs=no - fi - if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then - case $host in - *cygwin* | *mingw* | *cegcc*) - # No point in relinking DLLs because paths are not encoded - func_append notinst_deplibs " $lib" - need_relink=no - ;; - *) - if test "$installed" = no; then - func_append notinst_deplibs " $lib" - need_relink=yes - fi - ;; - esac - # This is a shared library - - # Warn about portability, can't link against -module's on some - # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" - for dlpremoduletest in $dlprefiles; do - if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" - break - fi - done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then - echo - if test "$linkmode" = prog; then - $ECHO "*** Warning: Linking the executable $output against the loadable module" - else - $ECHO "*** Warning: Linking the shared library $output against the loadable module" - fi - $ECHO "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - shift - realname="$1" - shift - libname=`eval "\\$ECHO \"$libname_spec\""` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw* | *cegcc*) - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - func_basename "$soroot" - soname="$func_basename_result" - func_stripname 'lib' '.dll' "$soname" - newlib=libimp-$func_stripname_result.a - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - func_verbose "extracting exported symbol list from \`$soname'" - func_execute_cmds "$extract_expsyms_cmds" 'exit $?' - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" - func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$opt_mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not - # link against it, someone is ignoring the earlier warnings - if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then - if test "X$dlopenmodule" != "X$lib"; then - $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - echo - echo "*** And there doesn't seem to be a static archive available" - echo "*** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - elif test -n "$old_library"; then - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - func_fatal_configuration "unsupported hardcode properties" - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) func_append compile_shlibpath "$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$opt_mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - echo "*** But as you try to build a module library, libtool will still create " - echo "*** a static module, that should work as long as the dlopening application" - echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) func_stripname '-R' '' "$libdir" - temp_xrpath=$func_stripname_result - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) func_append xrpath " $temp_xrpath";; - esac;; - *) func_append temp_deplibs " $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - func_append newlib_search_path " $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result";; - *) func_resolve_sysroot "$deplib" ;; - esac - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $func_resolve_sysroot_result "*) - func_append specialdeplibs " $func_resolve_sysroot_result" ;; - esac - fi - func_append tmp_libs " $func_resolve_sysroot_result" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - path= - case $deplib in - -L*) path="$deplib" ;; - *.la) - func_resolve_sysroot "$deplib" - deplib=$func_resolve_sysroot_result - func_dirname "$deplib" "" "." - dir=$func_dirname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" - fi - ;; - esac - if $GREP "^installed=no" $deplib > /dev/null; then - case $host in - *-*-darwin*) - depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" - path= - fi - fi - ;; - *) - path="-L$absdir/$objdir" - ;; - esac - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - test "$absdir" != "$libdir" && \ - func_warning "\`$deplib' seems to be moved" - - path="-L$absdir" - fi - ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then - compile_deplibs="$new_inherited_linker_flags $compile_deplibs" - finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" - else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - fi - fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) func_append lib_search_path " $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) func_append tmp_libs " $deplib" ;; - esac - ;; - *) func_append tmp_libs " $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - func_append tmp_libs " $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" - - test -n "$release" && \ - func_warning "\`-release' is ignored for archives" - - test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - func_append objs "$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - func_stripname 'lib' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" - - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - func_stripname '' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - func_stripname '' '.la' "$outputname" - libname=$func_stripname_result - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" - else - echo - $ECHO "*** Warning: Linking the shared library $output against the non-libtool" - $ECHO "*** objects $objs is not portable!" - func_append libobjs " $objs" - fi - fi - - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" - - set dummy $rpath - shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" - - install_libdir="$1" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" - - test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - shift - IFS="$save_ifs" - - test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$1" - number_minor="$2" - number_revision="$3" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_minor" - lt_irix_increment=no - ;; - esac - ;; - no) - current="$1" - revision="$2" - age="$3" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - func_arith $current + 1 - minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current" - ;; - - irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then - func_arith $current - $age - else - func_arith $current - $age + 1 - fi - major=$func_arith_result - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - func_arith $revision - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) # correct to gnu/linux during the next big refactor - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - ;; - - osf) - func_arith $current - $age - major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - func_arith $current - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - func_append verstring ":${current}.0" - ;; - - qnx) - major=".$current" - versuffix=".$current" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - - *) - func_fatal_configuration "unknown library version type \`$version_type'" - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - - fi - - func_generate_dlsyms "$libname" "$libname" "yes" - func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= - - if test "$opt_mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$ECHO "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext | *.gcno) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then - if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - func_append removelist " $p" - ;; - *) ;; - esac - done - test -n "$removelist" && \ - func_show_eval "${RM}r \$removelist" - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - func_append oldlibs " $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` - # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` - # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - func_replace_sysroot "$libdir" - func_append temp_xrpath " -R$func_replace_sysroot_result" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) func_append dlfiles " $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) func_append dlprefiles " $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - func_append deplibs " System.ltframework" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - func_append deplibs " -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $opt_dry_run || $RM conftest.c - cat > conftest.c </dev/null` - $nocaseglob - else - potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` - fi - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null | - $GREP " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | - $SED -e 10q | - $EGREP "$file_magic_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for file magic test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a file magic. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - for a_deplib in $deplibs; do - case $a_deplib in - -l*) - func_stripname -l '' "$a_deplib" - name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - func_append newdeplibs " $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval "\\$ECHO \"$libname_spec\""` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ - $EGREP "$match_pattern_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a regex pattern. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` - done - fi - case $tmp_deplibs in - *[!\ \ ]*) - echo - if test "X$deplibs_check_method" = "Xnone"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - ;; - esac - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - echo - echo "*** Since this library must not contain undefined symbols," - echo "*** because either the platform does not support them or" - echo "*** it was explicitly requested with -no-undefined," - echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - case $host in - *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - deplibs="$new_libs" - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. - # FIXME: should test the right _cmds variable. - case $archive_cmds in - *\$LD\ *) wl= ;; - esac - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - func_replace_sysroot "$libdir" - libdir=$func_replace_sysroot_result - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append dep_rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - shift - realname="$1" - shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - linknames= - for link - do - func_append linknames " $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` - test "X$libobjs" = "X " && libobjs= - - delfiles= - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" - func_append delfiles " $export_symbols" - fi - - orig_export_symbols= - case $host_os in - cygwin* | mingw* | cegcc*) - if test -n "$export_symbols" && test -z "$export_symbols_regex"; then - # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then - # and it's NOT already a .def file. Must figure out - # which of the given symbols are data symbols and tag - # them as such. So, trigger use of export_symbols_cmds. - # export_symbols gets reassigned inside the "prepare - # the list of exported symbols" if statement, so the - # include_expsyms logic still works. - orig_export_symbols="$export_symbols" - export_symbols= - always_export_symbols=yes - fi - fi - ;; - esac - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd1 in $cmds; do - IFS="$save_ifs" - # Take the normal branch if the nm_file_list_spec branch - # doesn't work or if tool conversion is not needed. - case $nm_file_list_spec~$to_tool_file_cmd in - *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) - try_normal_branch=yes - eval cmd=\"$cmd1\" - func_len " $cmd" - len=$func_len_result - ;; - *) - try_normal_branch=no - ;; - esac - if test "$try_normal_branch" = yes \ - && { test "$len" -lt "$max_cmd_len" \ - || test "$max_cmd_len" -le -1; } - then - func_show_eval "$cmd" 'exit $?' - skipped_export=false - elif test -n "$nm_file_list_spec"; then - func_basename "$output" - output_la=$func_basename_result - save_libobjs=$libobjs - save_output=$output - output=${output_objdir}/${output_la}.nm - func_to_tool_file "$output" - libobjs=$nm_file_list_spec$func_to_tool_file_result - func_append delfiles " $output" - func_verbose "creating $NM input file list: $output" - for obj in $save_libobjs; do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > "$output" - eval cmd=\"$cmd1\" - func_show_eval "$cmd" 'exit $?' - output=$save_output - libobjs=$save_libobjs - skipped_export=false - else - # The command line is too long to execute in one step. - func_verbose "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - func_append tmp_deplibs " $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && - test -z "$libobjs"; then - # extract the archives, so we have objects to list. - # TODO: could optimize this to just extract one archive. - whole_archive_flag_spec= - fi - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - else - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - func_append linker_flags " $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && - func_len " $test_cmds" && - len=$func_len_result && - test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise - # or, if using GNU ld and skipped_export is not :, use a linker - # script. - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - func_basename "$output" - output_la=$func_basename_result - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - last_robj= - k=1 - - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript - func_verbose "creating GNU ld script: $output" - echo 'INPUT (' > $output - for obj in $save_libobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - echo ')' >> $output - func_append delfiles " $output" - func_to_tool_file "$output" - output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk - func_verbose "creating linker input file list: $output" - : > $output - set x $save_libobjs - shift - firstobj= - if test "$compiler_needs_object" = yes; then - firstobj="$1 " - shift - fi - for obj - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - func_append delfiles " $output" - func_to_tool_file "$output" - output=$firstobj\"$file_list_spec$func_to_tool_file_result\" - else - if test -n "$save_libobjs"; then - func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext - eval test_cmds=\"$reload_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - if test "X$objlist" = X || - test "$len" -lt "$max_cmd_len"; then - func_append objlist " $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - reload_objs=$objlist - eval concat_cmds=\"$reload_cmds\" - else - # All subsequent reloadable object files will link in - # the last one created. - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - func_arith $k + 1 - k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext - objlist=" $obj" - func_len " $last_robj" - func_arith $len0 + $func_len_result - len=$func_arith_result - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" - fi - func_append delfiles " $output" - - else - output= - fi - - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - libobjs=$output - # Append the command to create the export file. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - fi - - test -n "$save_libobjs" && - func_verbose "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - if test -n "$export_symbols_regex" && ${skipped_export-false}; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - - if ${skipped_export-false}; then - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - fi - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - fi - - if test -n "$delfiles"; then - # Append the command to remove temporary files to $cmds. - eval cmds=\"\$cmds~\$RM $delfiles\" - fi - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - func_show_eval '${RM}r "$gentop"' - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" - - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" - - test -n "$release" && \ - func_warning "\`-release' is ignored for objects" - - case $output in - *.lo) - test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" - - libobj=$output - func_lo2o "$libobj" - obj=$func_lo2o_result - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $opt_dry_run || $RM $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - else - gentop="$output_objdir/${obj}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - func_execute_cmds "$reload_cmds" 'exit $?' - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - func_execute_cmds "$reload_cmds" 'exit $?' - fi - - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) func_stripname '' '.exe' "$output" - output=$func_stripname_result.exe;; - esac - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" - - test -n "$release" && \ - func_warning "\`-release' is ignored for programs" - - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - case $host in - *-*-darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then - case ${MACOSX_DEPLOYMENT_TARGET-10.0} in - 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" - ;; - esac - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - compile_deplibs="$new_libs" - - - func_append compile_command " $compile_deplibs" - func_append finalize_command " $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - ::) dllsearchpath=$libdir;; - *) func_append dllsearchpath ":$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) func_append finalize_perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - fi - - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" - - # template prelinking step - if test -n "$prelink_cmds"; then - func_execute_cmds "$prelink_cmds" 'exit $?' - fi - - wrappers_required=yes - case $host in - *cegcc* | *mingw32ce*) - # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no - ;; - *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - esac - if test "$wrappers_required" = no; then - # Replace the output file specification. - compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - exit_status=0 - func_show_eval "$link_command" 'exit_status=$?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' - fi - - exit $exit_status - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - func_append rpath "$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $opt_dry_run || $RM $output - # Link the executable and exit - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - exit $EXIT_SUCCESS - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname - - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output_objdir/$outputname" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Now create the wrapper script. - func_verbose "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - fi - - # Only actually do things if not in dry run mode. - $opt_dry_run || { - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) func_stripname '' '.exe' "$output" - output=$func_stripname_result ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - func_stripname '' '.exe' "$outputname" - outputname=$func_stripname_result ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - func_dirname_and_basename "$output" "" "." - output_name=$func_basename_result - output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" - $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - func_emit_cwrapperexe_src > $cwrappersource - - # The wrapper executable is built using the $host compiler, - # because it contains $host paths and files. If cross- - # compiling, it, like the target executable, must be - # executed on the $host or under an emulation environment. - $opt_dry_run || { - $LTCC $LTCFLAGS -o $cwrapper $cwrappersource - $STRIP $cwrapper - } - - # Now, create the wrapper script for func_source use: - func_ltwrapper_scriptname $cwrapper - $RM $func_ltwrapper_scriptname_result - trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 - $opt_dry_run || { - # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then - $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result - else - func_emit_wrapper no > $func_ltwrapper_scriptname_result - fi - } - ;; - * ) - $RM $output - trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 - - func_emit_wrapper no > $output - chmod +x $output - ;; - esac - } - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $addlibs - func_append oldobjs " $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append oldobjs " $func_extract_archives_result" - fi - - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else - echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - func_basename "$obj" - objbase="$func_basename_result" - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - func_arith $counter + 1 - counter=$func_arith_result - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - func_append oldobjs " $gentop/$newobj" - ;; - *) func_append oldobjs " $obj" ;; - esac - done - fi - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - eval cmds=\"$old_archive_cmds\" - - func_len " $cmds" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - elif test -n "$archiver_list_spec"; then - func_verbose "using command file archive linking..." - for obj in $oldobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > $output_objdir/$libname.libcmd - func_to_tool_file "$output_objdir/$libname.libcmd" - oldobjs=" $archiver_list_spec$func_to_tool_file_result" - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - func_verbose "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - oldobjs= - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - eval test_cmds=\"$old_archive_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - for obj in $save_oldobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - func_append objlist " $obj" - if test "$len" -lt "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - len=$len0 - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - func_execute_cmds "$cmds" 'exit $?' - done - - test -n "$generated" && \ - func_show_eval "${RM}r$generated" - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - func_verbose "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - - # Only create the output if not a dry run. - $opt_dry_run || { - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - func_basename "$deplib" - name="$func_basename_result" - func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" - ;; - -L*) - func_stripname -L '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -L$func_replace_sysroot_result" - ;; - -R*) - func_stripname -R '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -R$func_replace_sysroot_result" - ;; - *) func_append newdependency_libs " $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - - for lib in $dlfiles; do - case $lib in - *.la) - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" - ;; - *) func_append newdlfiles " $lib" ;; - esac - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - *.la) - # Only pass preopened files to the pseudo-archive (for - # eventual linking with the app. that links it) if we - # didn't already link the preopened objects directly into - # the library: - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" - ;; - esac - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlfiles " $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlprefiles " $abs" - done - dlprefiles="$newdlprefiles" - fi - $RM $output - # place dlname in correct position for cygwin - # In fact, it would be nice if we could use this code for all target - # systems that can't hard-code library paths into their executables - # and that have no shared library path variable independent of PATH, - # but it turns out we can't easily determine that from inspecting - # libtool variables, so we have to hard-code the OSs to which it - # applies here; at the moment, that means platforms that use the PE - # object format with DLL files. See the long comment at the top of - # tests/bindir.at for full details. - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) - # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then - func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname - else - # Otherwise fall back on heuristic. - tdlname=../bin/$dlname - fi - ;; - esac - $ECHO > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Linker flags that can not go in dependency_libs. -inherited_linker_flags='$new_inherited_linker_flags' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Names of additional weak libraries provided by this library -weak_library_names='$weak_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $ECHO >> $output "\ -relink_command=\"$relink_command\"" - fi - done - } - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' - ;; - esac - exit $EXIT_SUCCESS -} - -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} - - -# func_mode_uninstall arg... -func_mode_uninstall () -{ - $opt_debug - RM="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; - -*) func_append RM " $arg" ;; - *) func_append files " $arg" ;; - esac - done - - test -z "$RM" && \ - func_fatal_help "you must specify an RM program" - - rmdirs= - - for file in $files; do - func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" - else - odir="$dir/$objdir" - fi - func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" - - # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then - case " $rmdirs " in - *" $odir "*) ;; - *) func_append rmdirs " $odir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if { test -L "$file"; } >/dev/null 2>&1 || - { test -h "$file"; } >/dev/null 2>&1 || - test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if func_lalib_p "$file"; then - func_source $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - func_append rmfiles " $odir/$n" - done - test -n "$old_library" && func_append rmfiles " $odir/$old_library" - - case "$opt_mode" in - clean) - case " $library_names " in - *" $dlname "*) ;; - *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; - esac - test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if func_lalib_p "$file"; then - - # Read the .lo file - func_source $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then - func_append rmfiles " $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then - func_append rmfiles " $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$opt_mode" = clean ; then - noexename=$name - case $file in - *.exe) - func_stripname '' '.exe' "$file" - file=$func_stripname_result - func_stripname '' '.exe' "$name" - noexename=$func_stripname_result - # $file with .exe has already been added to rmfiles, - # add $file without .exe - func_append rmfiles " $file" - ;; - esac - # Do a test to see if this is a libtool program. - if func_ltwrapper_p "$file"; then - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - relink_command= - func_source $func_ltwrapper_scriptname_result - func_append rmfiles " $func_ltwrapper_scriptname_result" - else - relink_command= - func_source $dir/$noexename - fi - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - func_show_eval "$RM $rmfiles" 'exit_status=1' - done - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - func_show_eval "rmdir $dir >/dev/null 2>&1" - fi - done - - exit $exit_status -} - -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} - -test -z "$opt_mode" && { - help="$generic_help" - func_fatal_help "you must specify a MODE" -} - -test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" - -if test -n "$exec_cmd"; then - eval exec "$exec_cmd" - exit $EXIT_FAILURE -fi - -exit $exit_status - - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: -# vi:sw=2 - diff --git a/build-aux/missing b/build-aux/missing deleted file mode 100755 index cdea514931..0000000000 --- a/build-aux/missing +++ /dev/null @@ -1,215 +0,0 @@ -#! /bin/sh -# Common wrapper for a few potentially missing GNU programs. - -scriptversion=2012-06-26.16; # UTC - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# Originally written by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try '$0 --help' for more information" - exit 1 -fi - -case $1 in - - --is-lightweight) - # Used by our autoconf macros to check whether the available missing - # script is modern enough. - exit 0 - ;; - - --run) - # Back-compat with the calling convention used by older automake. - shift - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due -to PROGRAM being missing or too old. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man - -Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and -'g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: unknown '$1' option" - echo 1>&2 "Try '$0 --help' for more information" - exit 1 - ;; - -esac - -# Run the given program, remember its exit status. -"$@"; st=$? - -# If it succeeded, we are done. -test $st -eq 0 && exit 0 - -# Also exit now if we it failed (or wasn't found), and '--version' was -# passed; such an option is passed most likely to detect whether the -# program is present and works. -case $2 in --version|--help) exit $st;; esac - -# Exit code 63 means version mismatch. This often happens when the user -# tries to use an ancient version of a tool on a file that requires a -# minimum version. -if test $st -eq 63; then - msg="probably too old" -elif test $st -eq 127; then - # Program was missing. - msg="missing on your system" -else - # Program was found and executed, but failed. Give up. - exit $st -fi - -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software - -program_details () -{ - case $1 in - aclocal|automake) - echo "The '$1' program is part of the GNU Automake package:" - echo "<$gnu_software_URL/automake>" - echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/autoconf>" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - autoconf|autom4te|autoheader) - echo "The '$1' program is part of the GNU Autoconf package:" - echo "<$gnu_software_URL/autoconf/>" - echo "It also requires GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - esac -} - -give_advice () -{ - # Normalize program name to check for. - normalized_program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - - printf '%s\n' "'$1' is $msg." - - configure_deps="'configure.ac' or m4 files included by 'configure.ac'" - case $normalized_program in - autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' - ;; - autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" - echo "$configure_deps." - program_details 'autoheader' - ;; - automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" - echo "$configure_deps." - program_details 'aclocal' - ;; - autom4te*) - echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." - program_details 'autom4te' - ;; - bison*|yacc*) - echo "You should only need it if you modified a '.y' file." - echo "You may want to install the GNU Bison package:" - echo "<$gnu_software_URL/bison/>" - ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; - help2man*) - echo "You should only need it if you modified a dependency" \ - "of a man page." - echo "You may want to install the GNU Help2man package:" - echo "<$gnu_software_URL/help2man/>" - ;; - makeinfo*) - echo "You should only need it if you modified a '.texi' file, or" - echo "any other file indirectly affecting the aspect of the manual." - echo "You might want to install the Texinfo package:" - echo "<$gnu_software_URL/texinfo/>" - echo "The spurious makeinfo call might also be the consequence of" - echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" - echo "want to install GNU make:" - echo "<$gnu_software_URL/make/>" - ;; - *) - echo "You might have modified some files without having the proper" - echo "tools for further handling them. Check the 'README' file, it" - echo "often tells you about the needed prerequisites for installing" - echo "this package. You may also peek at any GNU archive site, in" - echo "case some other package contains this missing '$1' program." - ;; - esac -} - -give_advice "$1" | sed -e '1s/^/WARNING: /' \ - -e '2,$s/^/ /' >&2 - -# Propagate the correct exit status (expected to be 127 for a program -# not found, 63 for a program that failed due to version mismatch). -exit $st - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: From 5587f5bded46e94d639b7de8475b8b2829592be2 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 12:42:01 +0100 Subject: [PATCH 244/259] Remove makefiles They are not needed anymore with cmake --- externalpackages/PVODE/makefile | 16 --- output.make | 22 ---- tests/MMS/GBS/makefile | 6 - tests/MMS/advection/makefile | 6 - tests/MMS/diffusion/makefile | 8 -- tests/MMS/diffusion2/makefile | 8 -- tests/MMS/elm-pb/makefile | 6 - tests/MMS/elm-pb/makegrids.py | 65 ---------- tests/MMS/fieldalign/doc/makefile | 12 -- tests/MMS/fieldalign/makefile | 7 -- tests/MMS/hw/makefile | 6 - tests/MMS/laplace/makefile | 6 - tests/MMS/makefile | 1 - tests/MMS/spatial/advection/makefile | 6 - tests/MMS/spatial/d2dx2/makefile | 6 - tests/MMS/spatial/d2dz2/makefile | 6 - tests/MMS/spatial/diffusion/makefile | 8 -- tests/MMS/spatial/fci/makefile | 6 - tests/MMS/test_suite_make | 1 - tests/MMS/time/makefile | 6 - tests/MMS/tokamak/makefile | 6 - tests/MMS/wave-1d-y/makefile | 8 -- tests/MMS/wave-1d/makefile | 8 -- tests/integrated/makefile | 33 ----- tests/integrated/test-backtrace/makefile | 6 - tests/integrated/test-beuler/makefile | 5 - .../makefile | 6 - tests/integrated/test-collect/makefile | 6 - tests/integrated/test-command-args/makefile | 6 - tests/integrated/test-communications/makefile | 6 - .../test-coordinates-initialization/makefile | 6 - tests/integrated/test-cyclic/makefile | 6 - tests/integrated/test-datafilefacade/makefile | 5 - tests/integrated/test-dataformat/makefile | 6 - tests/integrated/test-delp2/makefile | 6 - .../test-drift-instability-staggered/makefile | 1 - .../test-drift-instability/make_d.pro | 23 ---- .../test-drift-instability/makefile | 5 - tests/integrated/test-fieldgroupComm/makefile | 3 - tests/integrated/test-globalfield/makefile | 6 - .../test-griddata-yboundary-guards/makefile | 6 - tests/integrated/test-griddata/makefile | 6 - tests/integrated/test-gyro/makefile | 6 - tests/integrated/test-include/makefile | 4 - tests/integrated/test-initial/makefile | 6 - tests/integrated/test-integrate/makefile | 6 - .../test-interchange-instability/makefile | 5 - tests/integrated/test-interpolate-z/makefile | 6 - tests/integrated/test-interpolate/makefile | 6 - .../test-invertable-operator/makefile | 5 - tests/integrated/test-invpar/makefile | 6 - .../integrated/test-laplace-hypre3d/makefile | 5 - .../integrated/test-laplace-petsc3d/makefile | 5 - tests/integrated/test-laplace/makefile | 6 - tests/integrated/test-laplace2/makefile | 6 - tests/integrated/test-laplacexy-fv/makefile | 5 - .../integrated/test-laplacexy-short/makefile | 5 - tests/integrated/test-laplacexy/makefile | 5 - .../integrated/test-laplacexy2-hypre/makefile | 5 - tests/integrated/test-laplacexz/makefile | 6 - .../test-multigrid_laplace/makefile | 5 - tests/integrated/test-naulin-laplace/makefile | 5 - tests/integrated/test-nonuniform/makefile | 6 - tests/integrated/test-options-adios/makefile | 6 - tests/integrated/test-options-netcdf/makefile | 6 - tests/integrated/test-petsc_laplace/makefile | 9 -- .../test-petsc_laplace_MAST-grid/makefile | 9 -- .../integrated/test-region-iterator/makefile | 6 - tests/integrated/test-restart-io/makefile | 5 - tests/integrated/test-restarting/makefile | 6 - tests/integrated/test-slepc-solver/makefile | 5 - tests/integrated/test-smooth/makefile | 6 - tests/integrated/test-snb/makefile | 6 - tests/integrated/test-solver/makefile | 5 - tests/integrated/test-squash/makefile | 6 - tests/integrated/test-stopCheck-file/makefile | 6 - tests/integrated/test-stopCheck/makefile | 6 - tests/integrated/test-subdir/bar/makefile | 6 - tests/integrated/test-subdir/fuu/makefile | 6 - tests/integrated/test-subdir/makefile | 10 -- .../test-twistshift-staggered/makefile | 5 - tests/integrated/test-twistshift/makefile | 5 - tests/integrated/test-vec/makefile | 6 - .../integrated/test-yupdown-weights/makefile | 6 - tests/integrated/test-yupdown/makefile | 6 - tests/integrated/test_suite_make | 3 - tests/unit/makefile | 114 ------------------ tools/pdb2idl/make.config.in | 19 --- 88 files changed, 764 deletions(-) delete mode 100644 externalpackages/PVODE/makefile delete mode 100644 output.make delete mode 100644 tests/MMS/GBS/makefile delete mode 100644 tests/MMS/advection/makefile delete mode 100644 tests/MMS/diffusion/makefile delete mode 100644 tests/MMS/diffusion2/makefile delete mode 100644 tests/MMS/elm-pb/makefile delete mode 100644 tests/MMS/elm-pb/makegrids.py delete mode 100644 tests/MMS/fieldalign/doc/makefile delete mode 100644 tests/MMS/fieldalign/makefile delete mode 100644 tests/MMS/hw/makefile delete mode 100644 tests/MMS/laplace/makefile delete mode 120000 tests/MMS/makefile delete mode 100644 tests/MMS/spatial/advection/makefile delete mode 100644 tests/MMS/spatial/d2dx2/makefile delete mode 100644 tests/MMS/spatial/d2dz2/makefile delete mode 100644 tests/MMS/spatial/diffusion/makefile delete mode 100644 tests/MMS/spatial/fci/makefile delete mode 120000 tests/MMS/test_suite_make delete mode 100644 tests/MMS/time/makefile delete mode 100644 tests/MMS/tokamak/makefile delete mode 100644 tests/MMS/wave-1d-y/makefile delete mode 100644 tests/MMS/wave-1d/makefile delete mode 100644 tests/integrated/makefile delete mode 100644 tests/integrated/test-backtrace/makefile delete mode 100644 tests/integrated/test-beuler/makefile delete mode 100644 tests/integrated/test-bout-override-default-option/makefile delete mode 100644 tests/integrated/test-collect/makefile delete mode 100644 tests/integrated/test-command-args/makefile delete mode 100644 tests/integrated/test-communications/makefile delete mode 100644 tests/integrated/test-coordinates-initialization/makefile delete mode 100644 tests/integrated/test-cyclic/makefile delete mode 100644 tests/integrated/test-datafilefacade/makefile delete mode 100644 tests/integrated/test-dataformat/makefile delete mode 100644 tests/integrated/test-delp2/makefile delete mode 120000 tests/integrated/test-drift-instability-staggered/makefile delete mode 100644 tests/integrated/test-drift-instability/make_d.pro delete mode 100644 tests/integrated/test-drift-instability/makefile delete mode 100644 tests/integrated/test-fieldgroupComm/makefile delete mode 100644 tests/integrated/test-globalfield/makefile delete mode 100644 tests/integrated/test-griddata-yboundary-guards/makefile delete mode 100644 tests/integrated/test-griddata/makefile delete mode 100644 tests/integrated/test-gyro/makefile delete mode 100644 tests/integrated/test-include/makefile delete mode 100644 tests/integrated/test-initial/makefile delete mode 100644 tests/integrated/test-integrate/makefile delete mode 100644 tests/integrated/test-interchange-instability/makefile delete mode 100644 tests/integrated/test-interpolate-z/makefile delete mode 100644 tests/integrated/test-interpolate/makefile delete mode 100644 tests/integrated/test-invertable-operator/makefile delete mode 100644 tests/integrated/test-invpar/makefile delete mode 100644 tests/integrated/test-laplace-hypre3d/makefile delete mode 100644 tests/integrated/test-laplace-petsc3d/makefile delete mode 100644 tests/integrated/test-laplace/makefile delete mode 100644 tests/integrated/test-laplace2/makefile delete mode 100644 tests/integrated/test-laplacexy-fv/makefile delete mode 100644 tests/integrated/test-laplacexy-short/makefile delete mode 100644 tests/integrated/test-laplacexy/makefile delete mode 100644 tests/integrated/test-laplacexy2-hypre/makefile delete mode 100644 tests/integrated/test-laplacexz/makefile delete mode 100644 tests/integrated/test-multigrid_laplace/makefile delete mode 100644 tests/integrated/test-naulin-laplace/makefile delete mode 100644 tests/integrated/test-nonuniform/makefile delete mode 100644 tests/integrated/test-options-adios/makefile delete mode 100644 tests/integrated/test-options-netcdf/makefile delete mode 100644 tests/integrated/test-petsc_laplace/makefile delete mode 100644 tests/integrated/test-petsc_laplace_MAST-grid/makefile delete mode 100644 tests/integrated/test-region-iterator/makefile delete mode 100644 tests/integrated/test-restart-io/makefile delete mode 100644 tests/integrated/test-restarting/makefile delete mode 100644 tests/integrated/test-slepc-solver/makefile delete mode 100644 tests/integrated/test-smooth/makefile delete mode 100644 tests/integrated/test-snb/makefile delete mode 100644 tests/integrated/test-solver/makefile delete mode 100644 tests/integrated/test-squash/makefile delete mode 100644 tests/integrated/test-stopCheck-file/makefile delete mode 100644 tests/integrated/test-stopCheck/makefile delete mode 100644 tests/integrated/test-subdir/bar/makefile delete mode 100644 tests/integrated/test-subdir/fuu/makefile delete mode 100644 tests/integrated/test-subdir/makefile delete mode 100644 tests/integrated/test-twistshift-staggered/makefile delete mode 100644 tests/integrated/test-twistshift/makefile delete mode 100644 tests/integrated/test-vec/makefile delete mode 100644 tests/integrated/test-yupdown-weights/makefile delete mode 100644 tests/integrated/test-yupdown/makefile delete mode 100755 tests/integrated/test_suite_make delete mode 100644 tests/unit/makefile delete mode 100644 tools/pdb2idl/make.config.in diff --git a/externalpackages/PVODE/makefile b/externalpackages/PVODE/makefile deleted file mode 100644 index 410470a320..0000000000 --- a/externalpackages/PVODE/makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Makefile for example codes -# Works in the same way as the root Makefile - -TARGET?=all - -DIRS = source precon - -all: $(DIRS) - -.PHONY: $(DIRS) - -$(DIRS): - @$(MAKE) -s --no-print-directory TARGET=$(TARGET) -C $@ $(TARGET) - -clean:: - @for pp in $(DIRS); do echo " " $$pp cleaned; $(MAKE) --no-print-directory -C $$pp clean; done diff --git a/output.make b/output.make deleted file mode 100644 index eae6b1be64..0000000000 --- a/output.make +++ /dev/null @@ -1,22 +0,0 @@ -BOUT_TOP ?= . - -include make.config - -# These expand to literals of the same name, which are then -# set in the bout.config script. This enables -# the final paths to the include and lib files to be set -# in the make/make install targets - -BOUT_INCLUDE_PATH="\$$BOUT_INCLUDE_PATH" -BOUT_LIB_PATH="\$$BOUT_LIB_PATH" -MPARK_VARIANT_INCLUDE_PATH="\$$MPARK_VARIANT_INCLUDE_PATH" -FMT_INCLUDE_PATH="\$$FMT_INCLUDE_PATH" - -.PHONY: cflags -cflags: - @echo $(BOUT_INCLUDE) $(BOUT_FLAGS) - -.PHONY: ldflags -ldflags: - @echo $(LDFLAGS) $(BOUT_LIBS) - diff --git a/tests/MMS/GBS/makefile b/tests/MMS/GBS/makefile deleted file mode 100644 index 7dbf15255f..0000000000 --- a/tests/MMS/GBS/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = gbs.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/advection/makefile b/tests/MMS/advection/makefile deleted file mode 100644 index 305cd9bebe..0000000000 --- a/tests/MMS/advection/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = advection.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/diffusion/makefile b/tests/MMS/diffusion/makefile deleted file mode 100644 index 4b4c30ff62..0000000000 --- a/tests/MMS/diffusion/makefile +++ /dev/null @@ -1,8 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = diffusion.cxx -SOURCEH = mathematica.h -TARGET = cyto - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/diffusion2/makefile b/tests/MMS/diffusion2/makefile deleted file mode 100644 index 4b4c30ff62..0000000000 --- a/tests/MMS/diffusion2/makefile +++ /dev/null @@ -1,8 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = diffusion.cxx -SOURCEH = mathematica.h -TARGET = cyto - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/elm-pb/makefile b/tests/MMS/elm-pb/makefile deleted file mode 100644 index 815a018b94..0000000000 --- a/tests/MMS/elm-pb/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = elm_pb.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/elm-pb/makegrids.py b/tests/MMS/elm-pb/makegrids.py deleted file mode 100644 index b627977469..0000000000 --- a/tests/MMS/elm-pb/makegrids.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 -# -# Creates the grid files and input options for -# a set of simulations. These can then be submitted -# to a batch queue and then processed with runtest -# (setting "running = False") -# - -from __future__ import print_function -from __future__ import division - -nxlist = [4, 8, 16, 32, 64, 128] - -from boututils.datafile import DataFile -from boututils.run_wrapper import shell - -from os.path import isfile - -from boutdata.mms import SimpleTokamak, x, y -from sympy import sin, cos - -from math import pi - -shape = SimpleTokamak() - -## Add equilibrium profiles -MU0 = 4.0e-7 * pi - -J0 = 1 - x - sin(x * pi) ** 2 * cos(y) # Parallel current -P0 = 2 + cos(x * pi) # Pressure pedestal -bxcvz = -((1.0 / shape.Rxy) ** 2) * cos(y) # Curvature - -# Normalisation -Lbar = 1.0 -Bbar = 1.0 -J0 = -J0 * shape.Bxy / (MU0 * Lbar) # Turn into A/m^2 -P0 = P0 * Bbar**2 / (2.0 * MU0) # Pascals - -shape.add(P0, "pressure") -shape.add(J0, "Jpar0") -shape.add(bxcvz, "bxcvz") - -for nx in nxlist: - # Generate a new mesh file - - filename = "grid%d.nc" % nx - - if isfile(filename): - print("Grid file '%s' already exists" % filename) - else: - print("Creating grid file '%s'" % filename) - f = DataFile(filename, create=True) - shape.write(nx, nx, f) - f.close() - - # Generate BOUT.inp file - - directory = "grid%d" % nx - shell("mkdir " + directory) - shell("cp data/BOUT.inp " + directory) - shell("sed -i 's/MZ = 17/MZ = %d/g' %s/BOUT.inp" % (nx, directory)) - shell( - 'sed -i \'s/grid = "grid16.nc"/grid = "%s"/g\' %s/BOUT.inp' - % (filename, directory) - ) diff --git a/tests/MMS/fieldalign/doc/makefile b/tests/MMS/fieldalign/doc/makefile deleted file mode 100644 index 70bb3220d0..0000000000 --- a/tests/MMS/fieldalign/doc/makefile +++ /dev/null @@ -1,12 +0,0 @@ - -DOCS = fieldalign.pdf - -.PHONY: all - -all: $(DOCS) - -%.pdf: %.tex - latexmk -pdf $< -interaction=batchmode - -clean: - latexmk -C diff --git a/tests/MMS/fieldalign/makefile b/tests/MMS/fieldalign/makefile deleted file mode 100644 index 30f47ccf0a..0000000000 --- a/tests/MMS/fieldalign/makefile +++ /dev/null @@ -1,7 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = fieldalign.cxx -SOURCEH = mathematica.h - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/hw/makefile b/tests/MMS/hw/makefile deleted file mode 100644 index 0a68a26d50..0000000000 --- a/tests/MMS/hw/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = hw.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/laplace/makefile b/tests/MMS/laplace/makefile deleted file mode 100644 index fa561d91da..0000000000 --- a/tests/MMS/laplace/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = laplace.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/makefile b/tests/MMS/makefile deleted file mode 120000 index 065bc377f3..0000000000 --- a/tests/MMS/makefile +++ /dev/null @@ -1 +0,0 @@ -../integrated/makefile \ No newline at end of file diff --git a/tests/MMS/spatial/advection/makefile b/tests/MMS/spatial/advection/makefile deleted file mode 100644 index fdb2043641..0000000000 --- a/tests/MMS/spatial/advection/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../.. - -SOURCEC = advection.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/spatial/d2dx2/makefile b/tests/MMS/spatial/d2dx2/makefile deleted file mode 100644 index 8975c2c713..0000000000 --- a/tests/MMS/spatial/d2dx2/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../../ - -SOURCEC = test_d2dx2.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/spatial/d2dz2/makefile b/tests/MMS/spatial/d2dz2/makefile deleted file mode 100644 index 043b0567dd..0000000000 --- a/tests/MMS/spatial/d2dz2/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../../ - -SOURCEC = test_d2dz2.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/spatial/diffusion/makefile b/tests/MMS/spatial/diffusion/makefile deleted file mode 100644 index 47a79d0916..0000000000 --- a/tests/MMS/spatial/diffusion/makefile +++ /dev/null @@ -1,8 +0,0 @@ - -BOUT_TOP = ../../../.. - -SOURCEC = diffusion.cxx -SOURCEH = mathematica.h -TARGET = diffusion - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/spatial/fci/makefile b/tests/MMS/spatial/fci/makefile deleted file mode 100644 index 88ba6c77e7..0000000000 --- a/tests/MMS/spatial/fci/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../.. - -SOURCEC = fci_mms.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/test_suite_make b/tests/MMS/test_suite_make deleted file mode 120000 index 97f7df4edb..0000000000 --- a/tests/MMS/test_suite_make +++ /dev/null @@ -1 +0,0 @@ -../integrated/test_suite_make \ No newline at end of file diff --git a/tests/MMS/time/makefile b/tests/MMS/time/makefile deleted file mode 100644 index a45b4a3888..0000000000 --- a/tests/MMS/time/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = time.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/tokamak/makefile b/tests/MMS/tokamak/makefile deleted file mode 100644 index f94969cccf..0000000000 --- a/tests/MMS/tokamak/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = tokamak.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/wave-1d-y/makefile b/tests/MMS/wave-1d-y/makefile deleted file mode 100644 index fb4dd1430a..0000000000 --- a/tests/MMS/wave-1d-y/makefile +++ /dev/null @@ -1,8 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = wave.cxx -SOURCEH = mathematica.h -TARGET = wave - -include $(BOUT_TOP)/make.config diff --git a/tests/MMS/wave-1d/makefile b/tests/MMS/wave-1d/makefile deleted file mode 100644 index fb4dd1430a..0000000000 --- a/tests/MMS/wave-1d/makefile +++ /dev/null @@ -1,8 +0,0 @@ - -BOUT_TOP = ../../../ - -SOURCEC = wave.cxx -SOURCEH = mathematica.h -TARGET = wave - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/makefile b/tests/integrated/makefile deleted file mode 100644 index 29215a7185..0000000000 --- a/tests/integrated/makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Makefile for example codes -# Works in the same way as the root Makefile - -BOUT_TOP = ../.. - -BUILD = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite_make --get-list) -BUILD_ALL = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite_make --get-list --all) - -CHECKING = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite --get-list) -CHECKING_ALL = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite --get-list --all) - -include $(BOUT_TOP)/make.config - -CHECKING_ = $(CHECKING:%=%_checking) -CHECKING_ALL_ = $(CHECKING_ALL:%=%_checking) - -DIRS_CLEAN = $(BUILD) - -.PHONY: $(BUILD_ALL) $(CHECKING_ALL) check - -all: $(BUILD) - -all-all: $(BUILD_ALL) - -buildncheck: all check - -$(BUILDALL): - @$(MAKE) --no-print-directory -C $@ - -check: $(CHECKING_) - -$(CHECKING_ALL_): - @$(MAKE) --no-print-directory -C $(@:%_checking=%) runtest diff --git a/tests/integrated/test-backtrace/makefile b/tests/integrated/test-backtrace/makefile deleted file mode 100644 index 27a1ecaf3a..0000000000 --- a/tests/integrated/test-backtrace/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP ?= ../../.. - -SOURCEC = boutexcept.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-beuler/makefile b/tests/integrated/test-beuler/makefile deleted file mode 100644 index 4eb9387e29..0000000000 --- a/tests/integrated/test-beuler/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test_beuler.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-bout-override-default-option/makefile b/tests/integrated/test-bout-override-default-option/makefile deleted file mode 100644 index 72fb7693e9..0000000000 --- a/tests/integrated/test-bout-override-default-option/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-bout-override-default-option.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-collect/makefile b/tests/integrated/test-collect/makefile deleted file mode 100644 index d599972ccb..0000000000 --- a/tests/integrated/test-collect/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-collect.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-command-args/makefile b/tests/integrated/test-command-args/makefile deleted file mode 100644 index 395ef9b6fa..0000000000 --- a/tests/integrated/test-command-args/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = command-args.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-communications/makefile b/tests/integrated/test-communications/makefile deleted file mode 100644 index 62bfa7e1ca..0000000000 --- a/tests/integrated/test-communications/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-communications.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-coordinates-initialization/makefile b/tests/integrated/test-coordinates-initialization/makefile deleted file mode 100644 index 805ac0e1da..0000000000 --- a/tests/integrated/test-coordinates-initialization/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-coordinates-initialization.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-cyclic/makefile b/tests/integrated/test-cyclic/makefile deleted file mode 100644 index 9d67f1fce2..0000000000 --- a/tests/integrated/test-cyclic/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_cyclic.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-datafilefacade/makefile b/tests/integrated/test-datafilefacade/makefile deleted file mode 100644 index 26b62c9998..0000000000 --- a/tests/integrated/test-datafilefacade/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-datafile-facade.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-dataformat/makefile b/tests/integrated/test-dataformat/makefile deleted file mode 100644 index ccf812ed6f..0000000000 --- a/tests/integrated/test-dataformat/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_dataformat.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-delp2/makefile b/tests/integrated/test-delp2/makefile deleted file mode 100644 index 0c6ba8b3a9..0000000000 --- a/tests/integrated/test-delp2/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_delp2.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-drift-instability-staggered/makefile b/tests/integrated/test-drift-instability-staggered/makefile deleted file mode 120000 index 4970135770..0000000000 --- a/tests/integrated/test-drift-instability-staggered/makefile +++ /dev/null @@ -1 +0,0 @@ -../test-drift-instability/makefile \ No newline at end of file diff --git a/tests/integrated/test-drift-instability/make_d.pro b/tests/integrated/test-drift-instability/make_d.pro deleted file mode 100644 index 861f846307..0000000000 --- a/tests/integrated/test-drift-instability/make_d.pro +++ /dev/null @@ -1,23 +0,0 @@ -function make_d, path=path - -if not keyword_set(PATH) then path='' - -ni=collect(path=path, var="Ni") -phi=collect(path=path, var="phi") -ni=ni[2,*,*,*] -phi=phi[2,*,*,*] - -du=file_import("uedge.grd_std.cdl") - -new_zmax = collect(path=path, var="ZMAX") ;-fraction of 2PI -rho_s = collect(path=path, var="rho_s") -wci = collect(path=path, var="wci") -t_array = collect(path=path, var="t_array") - -old_zmax=new_zmax/(rho_s/du.hthe0) -print, 'new_zmax=', new_zmax, "; old_zmax=", old_zmax - -d={ni_xyzt:ni, phi_xyzt:phi, rho_s:rho_s, zmax:old_zmax, Zeff:0., AA:0.0, t_array:t_array, wci:wci} - -return,d -end diff --git a/tests/integrated/test-drift-instability/makefile b/tests/integrated/test-drift-instability/makefile deleted file mode 100644 index 419aa3c503..0000000000 --- a/tests/integrated/test-drift-instability/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP ?= ../../.. - -SOURCEC = 2fluid.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-fieldgroupComm/makefile b/tests/integrated/test-fieldgroupComm/makefile deleted file mode 100644 index f3215eccde..0000000000 --- a/tests/integrated/test-fieldgroupComm/makefile +++ /dev/null @@ -1,3 +0,0 @@ -BOUT_TOP = ../../../ -SOURCEC = test_fieldgroupcomm.cxx -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-globalfield/makefile b/tests/integrated/test-globalfield/makefile deleted file mode 100644 index fddd978535..0000000000 --- a/tests/integrated/test-globalfield/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_globalfield.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-griddata-yboundary-guards/makefile b/tests/integrated/test-griddata-yboundary-guards/makefile deleted file mode 100644 index f2ff47b18b..0000000000 --- a/tests/integrated/test-griddata-yboundary-guards/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_griddata.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-griddata/makefile b/tests/integrated/test-griddata/makefile deleted file mode 100644 index f2ff47b18b..0000000000 --- a/tests/integrated/test-griddata/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_griddata.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-gyro/makefile b/tests/integrated/test-gyro/makefile deleted file mode 100644 index 72dcff3424..0000000000 --- a/tests/integrated/test-gyro/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_gyro.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-include/makefile b/tests/integrated/test-include/makefile deleted file mode 100644 index 6b94f31f99..0000000000 --- a/tests/integrated/test-include/makefile +++ /dev/null @@ -1,4 +0,0 @@ - -BOUT_TOP = ../../.. - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-initial/makefile b/tests/integrated/test-initial/makefile deleted file mode 100644 index b314e92006..0000000000 --- a/tests/integrated/test-initial/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_initial.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-integrate/makefile b/tests/integrated/test-integrate/makefile deleted file mode 100644 index 2c1dc520b6..0000000000 --- a/tests/integrated/test-integrate/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_integrate.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-interchange-instability/makefile b/tests/integrated/test-interchange-instability/makefile deleted file mode 100644 index 23554affba..0000000000 --- a/tests/integrated/test-interchange-instability/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = 2fluid.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-interpolate-z/makefile b/tests/integrated/test-interpolate-z/makefile deleted file mode 100644 index 5b925e1a97..0000000000 --- a/tests/integrated/test-interpolate-z/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_interpolate.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-interpolate/makefile b/tests/integrated/test-interpolate/makefile deleted file mode 100644 index 5b925e1a97..0000000000 --- a/tests/integrated/test-interpolate/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_interpolate.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-invertable-operator/makefile b/tests/integrated/test-invertable-operator/makefile deleted file mode 100644 index e0b6d92849..0000000000 --- a/tests/integrated/test-invertable-operator/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = invertable_operator.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-invpar/makefile b/tests/integrated/test-invpar/makefile deleted file mode 100644 index fc4b99517a..0000000000 --- a/tests/integrated/test-invpar/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_invpar.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplace-hypre3d/makefile b/tests/integrated/test-laplace-hypre3d/makefile deleted file mode 100644 index 88af7fb5e1..0000000000 --- a/tests/integrated/test-laplace-hypre3d/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-laplace3d.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplace-petsc3d/makefile b/tests/integrated/test-laplace-petsc3d/makefile deleted file mode 100644 index 88af7fb5e1..0000000000 --- a/tests/integrated/test-laplace-petsc3d/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-laplace3d.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplace/makefile b/tests/integrated/test-laplace/makefile deleted file mode 100644 index a8a63959d3..0000000000 --- a/tests/integrated/test-laplace/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_laplace.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplace2/makefile b/tests/integrated/test-laplace2/makefile deleted file mode 100644 index a8a63959d3..0000000000 --- a/tests/integrated/test-laplace2/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_laplace.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplacexy-fv/makefile b/tests/integrated/test-laplacexy-fv/makefile deleted file mode 100644 index e7789b2203..0000000000 --- a/tests/integrated/test-laplacexy-fv/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-laplacexy.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplacexy-short/makefile b/tests/integrated/test-laplacexy-short/makefile deleted file mode 100644 index e7789b2203..0000000000 --- a/tests/integrated/test-laplacexy-short/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-laplacexy.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplacexy/makefile b/tests/integrated/test-laplacexy/makefile deleted file mode 100644 index e7789b2203..0000000000 --- a/tests/integrated/test-laplacexy/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-laplacexy.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplacexy2-hypre/makefile b/tests/integrated/test-laplacexy2-hypre/makefile deleted file mode 100644 index e7789b2203..0000000000 --- a/tests/integrated/test-laplacexy2-hypre/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-laplacexy.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-laplacexz/makefile b/tests/integrated/test-laplacexz/makefile deleted file mode 100644 index 49ac5e5baf..0000000000 --- a/tests/integrated/test-laplacexz/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-laplacexz.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-multigrid_laplace/makefile b/tests/integrated/test-multigrid_laplace/makefile deleted file mode 100644 index 6eddb8b84d..0000000000 --- a/tests/integrated/test-multigrid_laplace/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test_multigrid_laplace.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-naulin-laplace/makefile b/tests/integrated/test-naulin-laplace/makefile deleted file mode 100644 index fb89ff2e71..0000000000 --- a/tests/integrated/test-naulin-laplace/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test_naulin_laplace.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-nonuniform/makefile b/tests/integrated/test-nonuniform/makefile deleted file mode 100644 index 0c6ba8b3a9..0000000000 --- a/tests/integrated/test-nonuniform/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_delp2.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-options-adios/makefile b/tests/integrated/test-options-adios/makefile deleted file mode 100644 index 7dbbce8736..0000000000 --- a/tests/integrated/test-options-adios/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-options-adios.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-options-netcdf/makefile b/tests/integrated/test-options-netcdf/makefile deleted file mode 100644 index f9197480fb..0000000000 --- a/tests/integrated/test-options-netcdf/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test-options-netcdf.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-petsc_laplace/makefile b/tests/integrated/test-petsc_laplace/makefile deleted file mode 100644 index 58633ec996..0000000000 --- a/tests/integrated/test-petsc_laplace/makefile +++ /dev/null @@ -1,9 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test_petsc_laplace.cxx -TARGET = test_petsc_laplace - -CXXFLAGS +=-g - -include $(BOUT_TOP)/make.config - diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/makefile b/tests/integrated/test-petsc_laplace_MAST-grid/makefile deleted file mode 100644 index 8a5ff1b27a..0000000000 --- a/tests/integrated/test-petsc_laplace_MAST-grid/makefile +++ /dev/null @@ -1,9 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test_petsc_laplace_MAST_grid.cxx -TARGET = test_petsc_laplace_MAST_grid - -CXXFLAGS +=-g - -include $(BOUT_TOP)/make.config - diff --git a/tests/integrated/test-region-iterator/makefile b/tests/integrated/test-region-iterator/makefile deleted file mode 100644 index fae70dbfa0..0000000000 --- a/tests/integrated/test-region-iterator/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_region_iterator.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-restart-io/makefile b/tests/integrated/test-restart-io/makefile deleted file mode 100644 index 4be85e426e..0000000000 --- a/tests/integrated/test-restart-io/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-restart-io.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-restarting/makefile b/tests/integrated/test-restarting/makefile deleted file mode 100644 index c1a416dcf9..0000000000 --- a/tests/integrated/test-restarting/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_restarting.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-slepc-solver/makefile b/tests/integrated/test-slepc-solver/makefile deleted file mode 100644 index 8fc1b74cf5..0000000000 --- a/tests/integrated/test-slepc-solver/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-slepc-solver.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-smooth/makefile b/tests/integrated/test-smooth/makefile deleted file mode 100644 index 141a214a50..0000000000 --- a/tests/integrated/test-smooth/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_smooth.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-snb/makefile b/tests/integrated/test-snb/makefile deleted file mode 100644 index 526313b1cf..0000000000 --- a/tests/integrated/test-snb/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_snb.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-solver/makefile b/tests/integrated/test-solver/makefile deleted file mode 100644 index 8d16dfc55c..0000000000 --- a/tests/integrated/test-solver/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test_solver.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-squash/makefile b/tests/integrated/test-squash/makefile deleted file mode 100644 index cecff798ec..0000000000 --- a/tests/integrated/test-squash/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = squash.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-stopCheck-file/makefile b/tests/integrated/test-stopCheck-file/makefile deleted file mode 100644 index 2d2e644a9e..0000000000 --- a/tests/integrated/test-stopCheck-file/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_stopCheck.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-stopCheck/makefile b/tests/integrated/test-stopCheck/makefile deleted file mode 100644 index 2d2e644a9e..0000000000 --- a/tests/integrated/test-stopCheck/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_stopCheck.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-subdir/bar/makefile b/tests/integrated/test-subdir/bar/makefile deleted file mode 100644 index ffa825d218..0000000000 --- a/tests/integrated/test-subdir/bar/makefile +++ /dev/null @@ -1,6 +0,0 @@ -BOUT_TOP = ../../../.. - -SOURCEC = bar.cxx -SOURCEH = $(SOURCEC:%.cxx=%.hxx) - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-subdir/fuu/makefile b/tests/integrated/test-subdir/fuu/makefile deleted file mode 100644 index 2c8332ee44..0000000000 --- a/tests/integrated/test-subdir/fuu/makefile +++ /dev/null @@ -1,6 +0,0 @@ -BOUT_TOP = ../../../.. - -SOURCEC = fuu.cxx -SOURCEH = $(SOURCEC:%.cxx=%.hxx) - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-subdir/makefile b/tests/integrated/test-subdir/makefile deleted file mode 100644 index ed52b47451..0000000000 --- a/tests/integrated/test-subdir/makefile +++ /dev/null @@ -1,10 +0,0 @@ -BOUT_TOP = ../../.. -SOURCEH = -SOURCEC = subdirs.cxx - -# make sure we extract the folder -# DIRS = fuu bar would work as well, but we want to make sure -# ../otherproject/fuu and /some/long/path/bar works as well ... -DIRS = fuu/ ././bar/ - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-twistshift-staggered/makefile b/tests/integrated/test-twistshift-staggered/makefile deleted file mode 100644 index 0018135bce..0000000000 --- a/tests/integrated/test-twistshift-staggered/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-twistshift.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-twistshift/makefile b/tests/integrated/test-twistshift/makefile deleted file mode 100644 index 0018135bce..0000000000 --- a/tests/integrated/test-twistshift/makefile +++ /dev/null @@ -1,5 +0,0 @@ -BOUT_TOP = ../../.. - -SOURCEC = test-twistshift.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-vec/makefile b/tests/integrated/test-vec/makefile deleted file mode 100644 index 75385e5460..0000000000 --- a/tests/integrated/test-vec/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = testVec.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-yupdown-weights/makefile b/tests/integrated/test-yupdown-weights/makefile deleted file mode 100644 index 4e3a173b0e..0000000000 --- a/tests/integrated/test-yupdown-weights/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_yupdown_weights.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-yupdown/makefile b/tests/integrated/test-yupdown/makefile deleted file mode 100644 index 26728c595f..0000000000 --- a/tests/integrated/test-yupdown/makefile +++ /dev/null @@ -1,6 +0,0 @@ - -BOUT_TOP = ../../.. - -SOURCEC = test_yupdown.cxx - -include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test_suite_make b/tests/integrated/test_suite_make deleted file mode 100755 index 36fe54225a..0000000000 --- a/tests/integrated/test_suite_make +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env sh - -./test_suite --make "$@" diff --git a/tests/unit/makefile b/tests/unit/makefile deleted file mode 100644 index 1264705559..0000000000 --- a/tests/unit/makefile +++ /dev/null @@ -1,114 +0,0 @@ -#################################################################### -# Tests -#################################################################### - -BOUT_TOP = ../.. - -BOUT_TEST_DIR = . - -GTEST_BASE = $(BOUT_TOP)/externalpackages/googletest -GTEST_DIR = $(GTEST_BASE)/googletest -GMOCK_DIR = $(GTEST_BASE)/googlemock - -GTEST_SOURCES = $(GTEST_DIR)/src/gtest-all.cc - -# Flags passed to the preprocessor. -# Set Google Test's header directory as a system directory, such that -# the compiler doesn't generate warnings in Google Test headers. -CXXFLAGS += -isystem ${GTEST_DIR}/include -I${GTEST_DIR} -I${BOUT_TEST_DIR} -CXXFLAGS += -isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} - -# Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra -pthread - - -# All Google Test headers. Usually you shouldn't change this -# definition. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -all: serial_tests -include $(BOUT_TOP)/make.config - -LDFLAGS += -pthread - -# Existence of this file indicates that GTEST has been downloaded -GTEST_SENTINEL = $(GTEST_BASE)/README.md - -# House-keeping build targets. - -clean :: - @$(RM) -f gtest.a bout_test_main.a *.o $(TEST_OBJECTS) - -# Builds gtest.a and bout_test_main.a. - -# Download Google Test -$(GTEST_SENTINEL) : - @echo "Downloading Google Test" - git submodule update --init --recursive - -# For simplicity and to avoid depending on Google Test's -# implementation details, the dependencies specified below are -# conservative and not optimized. This is fine as Google Test -# compiles fast and for ordinary users its source rarely changes. -# -# Note: If the GoogleTest submodule has not been checked out when -# this makefile is run, then the list of .cc and .h files is not -# correctly captured. Since we will probably not be modifying googletest -# this rule just depends on the sentinel file. -gtest-all.o : $(GTEST_SENTINEL) - @echo " Compiling" $@ - @$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(BOUT_FLAGS) -c \ - $(GTEST_DIR)/src/gtest-all.cc - -gmock-all.o : $(GTEST_SENTINEL) - @echo " Compiling" $@ - @$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(BOUT_FLAGS) -c \ - $(GMOCK_DIR)/src/gmock-all.cc - -bout_test_main.o : $(GTEST_SENTINEL) $(BOUT_TEST_DIR)/bout_test_main.cxx - @echo " Compiling" $@ - @$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(BOUT_INCLUDE) $(BOUT_FLAGS) -c $(@:.o=.cxx) - -gtest.a : gtest-all.o - @echo " Linking" $@ - @$(AR) $(ARFLAGS) $@ $^ - -gmock.a : gmock-all.o - @echo " Linking" $@ - @$(AR) $(ARFLAGS) $@ $^ - -bout_test_main.a : gtest-all.o gmock-all.o bout_test_main.o - @echo " Linking" $@ - @$(AR) $(ARFLAGS) $@ $^ - -$(TARGET): makefile $(BOUT_TOP)/make.config $(OBJ) $(SUB_LIBS) bout_test_main.a - @echo " Linking" $(TARGET) - @$(LD) $(LDFLAGS) -o $(TARGET) $(OBJ) $(BOUT_LIBS) $(SUB_LIBS) bout_test_main.a - -TEST_SOURCES = $(shell find $(BOUT_TEST_DIR) -type f -name "test_*.cxx" 2> /dev/null) -TEST_OBJECTS = $(TEST_SOURCES:%.cxx=%.o) - -$(TEST_OBJECTS): | $(GTEST_SENTINEL) - -serial_tests: makefile $(BOUT_TOP)/make.config $(OBJ) $(LIB) \ - $(SUB_LIBS) $(TEST_OBJECTS) bout_test_main.a - @echo " Linking tests" - @$(LD) -o $@ $(TEST_OBJECTS) bout_test_main.a $(LDFLAGS) $(BOUT_LIBS) $(SUB_LIBS) - -# Override this on the command line to print full output from the unit tests -QUIET ?= --gtest_brief=1 - -# Note: This depends on GTEST_SENTINEL, which checks out Google Test if not present -# The correct behaviour relies on the dependencies being checked in left-to-right order -# The GTEST_SENTINEL dependency cannot be added to the %.o target, since this results in the %.o -# target in make.config being used instead. -check: $(GTEST_SENTINEL) serial_tests - @echo "Running unit test" - @./serial_tests $(QUIET) $(GTEST_ARGS) - -# This is the same target as a make rule in make.config. Adding unmet dependencies here -# results in makefile reverting to the make.config version. -%.o: $(BOUT_TOP)/make.config %.cxx - @echo " Compiling " $(@:.o=.cxx) - @$(CXX) $(BOUT_INCLUDE) $(BOUT_FLAGS) -c $(@:.o=.cxx) -o $(@) diff --git a/tools/pdb2idl/make.config.in b/tools/pdb2idl/make.config.in deleted file mode 100644 index 36c97e7789..0000000000 --- a/tools/pdb2idl/make.config.in +++ /dev/null @@ -1,19 +0,0 @@ -# configuration file for PDB2IDL - -CFLAGS = @CFLAGS@ -LDFLAGS = @LDFLAGS@ - -CC = @CC@ -LD = @LD@ - -# Set the location of the PACT installation -PACT = @PACT@ - -# IDL external library -IDLPATH = @IDLPATH@ - -#################################### -# Do not need to alter this section - -INCLUDE = -I$(PACT)/include -I$(IDLPATH) -LIB = -L$(PACT)/lib -lpdb -lpml -lscore From 83cf45131efd234f6ffe080f53c4e0350f0ff39e Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 12:47:24 +0100 Subject: [PATCH 245/259] Remove vagrant config It was very outdated --- tools/vagrant/README.md | 12 ------------ tools/vagrant/Vagrantfile | 9 --------- tools/vagrant/bootstrap.sh | 31 ------------------------------- 3 files changed, 52 deletions(-) delete mode 100644 tools/vagrant/README.md delete mode 100644 tools/vagrant/Vagrantfile delete mode 100644 tools/vagrant/bootstrap.sh diff --git a/tools/vagrant/README.md b/tools/vagrant/README.md deleted file mode 100644 index 0adb67fa67..0000000000 --- a/tools/vagrant/README.md +++ /dev/null @@ -1,12 +0,0 @@ -This is a basic vagrant config which you can use to compile and run BOUT++ on your local machine. For more info on vagrant see https://www.vagrantup.com/. - -To use it, cd into this directory and run: - - vagrant up # this creates the VM, installs BOUT including dependencies and runs all the tests. - vagrant ssh # logs in to the VM. - -At this point you should be able to run one of the examples: - - cd BOUT/examples/conduction # find a simple example. - make # compile the example. - mpirun -np 2 ./conduction # run the example. diff --git a/tools/vagrant/Vagrantfile b/tools/vagrant/Vagrantfile deleted file mode 100644 index 0b0b3bc49c..0000000000 --- a/tools/vagrant/Vagrantfile +++ /dev/null @@ -1,9 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -VAGRANTFILE_API_VERSION = "2" - -Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.box = "ubuntu/trusty64" - config.vm.provision :shell, path: "bootstrap.sh" -end diff --git a/tools/vagrant/bootstrap.sh b/tools/vagrant/bootstrap.sh deleted file mode 100644 index 6737eac53c..0000000000 --- a/tools/vagrant/bootstrap.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# install dependencies -apt-get update -apt-get install -y mpich2 libmpich2-dev -apt-get install -y libfftw3-dev libnetcdf-dev -apt-get install -y g++ make -apt-get install -y python-scipy - -# get the bout++ code -apt-get install -y git -rm -rf BOUT -git clone https://github.com/bendudson/BOUT.git - -# environment variables for both this session and the vagrant user -echo "export IDL_PATH=$(pwd)/BOUT/tools/idllib" >> $(pwd)/.bashrc -echo "export PYTHONPATH=$(pwd)/BOUT/tools/pylib/:$PYTHONPATH" >> $(pwd)/.bashrc -source $(pwd)/.bashrc -export IDL_PATH=$(pwd)/BOUT/tools/idllib -export PYTHONPATH=$(pwd)/BOUT/tools/pylib/:$PYTHONPATH - -# configure bout++ -cd BOUT -./configure -make -cd examples -./test_suite - -# set owner to vagrant user so compilation works -cd ../.. -chown -R vagrant:vagrant BOUT From 10b0d4088e40bbc8855dabf230f05501297e7eaf Mon Sep 17 00:00:00 2001 From: ZedThree <1486942+ZedThree@users.noreply.github.com> Date: Tue, 4 Nov 2025 11:58:36 +0000 Subject: [PATCH 246/259] Apply clang-format changes --- src/mesh/parallel/fci.cxx | 4 ++-- tests/integrated/test-fci-boundary/get_par_bndry.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 96765c439e..7c7ade1c8d 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -180,8 +180,8 @@ FCIMap::FCIMap(Mesh& mesh, [[maybe_unused]] const Coordinates::FieldMetric& dy, const int ncz = map_mesh->LocalNz; BoutMask to_remove(map_mesh); - const int xend = - map_mesh->xstart + ((map_mesh->xend - map_mesh->xstart + 1) * map_mesh->getNXPE()) - 1; + const int xend = map_mesh->xstart + + ((map_mesh->xend - map_mesh->xstart + 1) * map_mesh->getNXPE()) - 1; // Serial loop because call to BoundaryRegionPar::addPoint // (probably?) can't be done in parallel BOUT_FOR_SERIAL(i, xt_prime.getRegion("RGN_NOBNDRY")) { diff --git a/tests/integrated/test-fci-boundary/get_par_bndry.cxx b/tests/integrated/test-fci-boundary/get_par_bndry.cxx index ba282d8988..8183d989d1 100644 --- a/tests/integrated/test-fci-boundary/get_par_bndry.cxx +++ b/tests/integrated/test-fci-boundary/get_par_bndry.cxx @@ -8,7 +8,7 @@ int main(int argc, char** argv) { using bout::globals::mesh; - std::vector fields (static_cast(BoundaryParType::SIZE), Field3D{0.0}); + std::vector fields(static_cast(BoundaryParType::SIZE), Field3D{0.0}); Options dump; for (int i = 0; i < fields.size(); i++) { From ec4148fb708c2d055576a351dc7427a6798baae1 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 15:20:49 +0100 Subject: [PATCH 247/259] Remove workaround --- tests/MMS/spatial/fci/runtest | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index e3d10d989b..4d5022d4b4 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -17,7 +17,6 @@ import zoidberg as zb from boutdata.collect import collect from boututils.run_wrapper import build_and_log, launch_safe from numpy import arange, array, linspace, log, polyfit -from scipy.interpolate import RectBivariateSpline as RBS # Global parameters DIRECTORY = "data" @@ -32,17 +31,6 @@ NLIST = [8, 16, 32, 64] dx = 1.0 / array(NLIST) -def myRBS(a, b, c): - """RectBivariateSpline, but automatically tune spline degree for small arrays""" - mx, _ = c.shape - kx = max(mx - 1, 1) - kx = min(kx, 3) - return RBS(a, b, c, kx=kx) - - -zb.poloidal_grid.RectBivariateSpline = myRBS - - def quiet_collect(name: str) -> float: # Index to return a plain (numpy) float rather than `BoutArray` return collect( From f25bb0f43fa85e9f7648bb6413a68430438c3007 Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Tue, 4 Nov 2025 14:27:00 +0000 Subject: [PATCH 248/259] Apply clang-format changes --- src/mesh/parallel/fci.cxx | 17 +++++++++-------- src/solver/impls/snes/snes.cxx | 5 ++--- tests/unit/sys/test_options.cxx | 3 ++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 7d5f436e6c..f533fae541 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -69,7 +69,7 @@ std::string parallel_slice_field_name(std::string field, int offset) { // We only have a suffix for parallel slices beyond the first // This is for backwards compatibility const auto slice_suffix = - (std::abs(offset) > 1) ? fmt::format("_{}", std::abs(offset)) : ""; + (std::abs(offset) > 1) ? fmt::format("_{}", std::abs(offset)) : ""; return fmt::format("{}_{}{}", direction, field, slice_suffix); }; @@ -228,7 +228,8 @@ FCIMap::FCIMap(Mesh& mesh, [[maybe_unused]] const Coordinates::FieldMetric& dy, // If we can't read in any of these fields, things will silently not // work, so best throw - if (map_mesh->get(xt_prime, parallel_slice_field_name("xt_prime", offset_), 0.0, false) != 0) { + if (map_mesh->get(xt_prime, parallel_slice_field_name("xt_prime", offset_), 0.0, false) + != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("xt_prime", offset_)); @@ -480,12 +481,12 @@ FCITransform::FCITransform(Mesh& mesh, const Coordinates::FieldMetric& dy, bool continue; } for (auto pnt : *bndry) { - for (auto pnt2 : *bndry2) { - if (pnt.ind() == pnt2.ind()) { - pnt.setValid( - static_cast(std::abs((pnt2.offset() - pnt.offset())) - 2)); - } - } + for (auto pnt2 : *bndry2) { + if (pnt.ind() == pnt2.ind()) { + pnt.setValid( + static_cast(std::abs((pnt2.offset() - pnt.offset())) - 2)); + } + } } } } diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index c10095af53..820f2cbebb 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -83,8 +83,7 @@ PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, - void* ctx) { +PetscErrorCode FormFunctionForColoring(void* UNUSED(snes), Vec x, Vec f, void* ctx) { return static_cast(ctx)->snes_function(x, f, true); } @@ -96,7 +95,7 @@ PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { PetscFunctionReturn(s->precon(x, y)); } -} +} // namespace SNESSolver::SNESSolver(Options* opts) : Solver(opts), diff --git a/tests/unit/sys/test_options.cxx b/tests/unit/sys/test_options.cxx index 67e405953d..725bbe1b04 100644 --- a/tests/unit/sys/test_options.cxx +++ b/tests/unit/sys/test_options.cxx @@ -1099,7 +1099,8 @@ value6 = 12 } TEST_F(OptionsTest, InvalidFormat) { - EXPECT_THROW([[maybe_unused]] auto none = fmt::format("{:nope}", Options{}), fmt::format_error); + EXPECT_THROW([[maybe_unused]] auto none = fmt::format("{:nope}", Options{}), + fmt::format_error); } TEST_F(OptionsTest, FormatValue) { From 99e28ca5f81081026df6eff1cf0670546c9a5e04 Mon Sep 17 00:00:00 2001 From: David Bold Date: Tue, 4 Nov 2025 15:42:19 +0100 Subject: [PATCH 249/259] Fix bad merge: Add Tensor::operator[](Ind3D) --- include/bout/utils.hxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/bout/utils.hxx b/include/bout/utils.hxx index 1ed3b34f9e..ed2f7a2737 100644 --- a/include/bout/utils.hxx +++ b/include/bout/utils.hxx @@ -354,7 +354,14 @@ public: return data[(i1 * n2 + i2) * n3 + i3]; } - const T& operator[](Ind3D i) const { + const T& operator[](const Ind3D i) const { + // ny and nz are private :-( + // ASSERT2(i.nz == n3); + // ASSERT2(i.ny == n2); + ASSERT2(0 <= i.ind && i.ind < n1 * n2 * n3); + return data[i.ind]; + } + T& operator[](const Ind3D i) { // ny and nz are private :-( // ASSERT2(i.nz == n3); // ASSERT2(i.ny == n2); From 8afbcbc968f88972d6311fa868e2725d98698d41 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 10:56:06 +0100 Subject: [PATCH 250/259] add yup and ydown property --- src/field/gen_fieldops.jinja | 12 ++++++------ src/field/gen_fieldops.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index 15f85c9ea4..d13c9ee758 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -16,8 +16,8 @@ if ({{lhs.name}}.isFci()) { {{out.name}}.splitParallelSlices(); for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { - {{out.name}}.yup(i) = {{lhs.name}}.yup(i) {{operator}} {{rhs.name}}.yup(i); - {{out.name}}.ydown(i) = {{lhs.name}}.ydown(i) {{operator}} {{rhs.name}}.ydown(i); + {{out.name}}.yup(i) = {{lhs.yup}} {{operator}} {{rhs.yup}}; + {{out.name}}.ydown(i) = {{lhs.ydown}} {{operator}} {{rhs.ydown}}; } } {% endif %} @@ -27,8 +27,8 @@ if ({{lhs.name}}.isFci()) { {{out.name}}.splitParallelSlices(); for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { - {{out.name}}.yup(i) = {{lhs.name}}.yup(i) {{operator}} {{rhs.name}}; - {{out.name}}.ydown(i) = {{lhs.name}}.ydown(i) {{operator}} {{rhs.name}}; + {{out.name}}.yup(i) = {{lhs.yup}} {{operator}} {{rhs.yup}}; + {{out.name}}.ydown(i) = {{lhs.ydown}} {{operator}} {{rhs.ydown}}; } } {% endif %} @@ -38,8 +38,8 @@ if ({{rhs.name}}.isFci()) { {{out.name}}.splitParallelSlices(); for (size_t i{0} ; i < {{rhs.name}}.numberParallelSlices() ; ++i) { - {{out.name}}.yup(i) = {{lhs.name}} {{operator}} {{rhs.name}}.yup(i); - {{out.name}}.ydown(i) = {{lhs.name}} {{operator}} {{rhs.name}}.ydown(i); + {{out.name}}.yup(i) = {{lhs.yup}} {{operator}} {{rhs.yup}}; + {{out.name}}.ydown(i) = {{lhs.ydown}} {{operator}} {{rhs.ydown}}; } } {% endif %} diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 16a5f4dd6e..28dd18e54d 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -157,6 +157,24 @@ def base_index(self): else: return "{self.name}[{self.mixed_base_ind_var}]".format(self=self) + @property + def yup(self): + """Returns {{name}}.yup(i) if it is a field with parallel slices. + If it is BoutReal just {{name}}""" + if self.field_type == "BoutReal": + return "{self.name}".format(self=self) + else: + return "{self.name}.yup(i)".format(self=self) + + @property + def ydown(self): + """Returns {{name}}.ydown(i) if it is a field with parallel slices. + If it is BoutReal just {{name}}""" + if self.field_type == "BoutReal": + return "{self.name}".format(self=self) + else: + return "{self.name}.ydown(i)".format(self=self) + def __eq__(self, other): try: return self.field_type == other.field_type From 28b2192595e7a5c9c9bbb5e4af9c9ee9494c1116 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 10:56:30 +0100 Subject: [PATCH 251/259] simplify template --- src/field/gen_fieldops.jinja | 30 +++++++----------------- src/field/generated_fieldops.cxx | 40 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index d13c9ee758..a836fa1633 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -12,37 +12,23 @@ {% if lhs.region_type == rhs.region_type == "3D" %} {{out.name}}.setRegion({{lhs.name}}.getMesh()->getCommonRegion({{lhs.name}}.getRegionID(), {{rhs.name}}.getRegionID())); - {% if out == "Field3DParallel" %} - if ({{lhs.name}}.isFci()) { - {{out.name}}.splitParallelSlices(); - for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { - {{out.name}}.yup(i) = {{lhs.yup}} {{operator}} {{rhs.yup}}; - {{out.name}}.ydown(i) = {{lhs.ydown}} {{operator}} {{rhs.ydown}}; - } - } - {% endif %} {% elif lhs.region_type == "3D" %} {{out.name}}.setRegion({{lhs.name}}.getRegionID()); - {% if rhs == "BoutReal" and out == "Field3DParallel" %} - if ({{lhs.name}}.isFci()) { - {{out.name}}.splitParallelSlices(); - for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { - {{out.name}}.yup(i) = {{lhs.yup}} {{operator}} {{rhs.yup}}; - {{out.name}}.ydown(i) = {{lhs.ydown}} {{operator}} {{rhs.ydown}}; - } - } - {% endif %} {% elif rhs.region_type == "3D" %} {{out.name}}.setRegion({{rhs.name}}.getRegionID()); - {% if lhs == "BoutReal" and rhs == "Field3DParallel" %} - if ({{rhs.name}}.isFci()) { + {% endif %} + {% if out == "Field3DParallel" %} + if ({{out.name}}.isFci()) { {{out.name}}.splitParallelSlices(); - for (size_t i{0} ; i < {{rhs.name}}.numberParallelSlices() ; ++i) { + {% if lhs.region_type == "3D" %} + for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { + {% else %} + for (size_t i{0} ; i < {{rhs.name}}.numberParallelSlices() ; ++i) { + {% endif %} {{out.name}}.yup(i) = {{lhs.yup}} {{operator}} {{rhs.yup}}; {{out.name}}.ydown(i) = {{lhs.ydown}} {{operator}} {{rhs.ydown}}; } } - {% endif %} {% endif %} {% endif %} diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index ec9b966467..d3355a8947 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -2271,7 +2271,7 @@ Field3DParallel operator*(const Field3D& lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs.yup(i); @@ -2299,7 +2299,7 @@ Field3DParallel operator/(const Field3D& lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs.yup(i); @@ -2327,7 +2327,7 @@ Field3DParallel operator+(const Field3D& lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs.yup(i); @@ -2355,7 +2355,7 @@ Field3DParallel operator-(const Field3D& lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs.yup(i); @@ -2383,7 +2383,7 @@ Field3DParallel operator*(const Field3DParallel& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs.yup(i); @@ -2447,7 +2447,7 @@ Field3DParallel operator/(const Field3DParallel& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs.yup(i); @@ -2511,7 +2511,7 @@ Field3DParallel operator+(const Field3DParallel& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs.yup(i); @@ -2575,7 +2575,7 @@ Field3DParallel operator-(const Field3DParallel& lhs, const Field3D& rhs) { checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs.yup(i); @@ -2639,7 +2639,7 @@ Field3DParallel operator*(const Field3DParallel& lhs, const Field3DParallel& rhs checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs.yup(i); @@ -2703,7 +2703,7 @@ Field3DParallel operator/(const Field3DParallel& lhs, const Field3DParallel& rhs checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs.yup(i); @@ -2767,7 +2767,7 @@ Field3DParallel operator+(const Field3DParallel& lhs, const Field3DParallel& rhs checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs.yup(i); @@ -2831,7 +2831,7 @@ Field3DParallel operator-(const Field3DParallel& lhs, const Field3DParallel& rhs checkData(rhs); result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs.yup(i); @@ -2894,7 +2894,7 @@ Field3DParallel operator*(const Field3DParallel& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs; @@ -2954,7 +2954,7 @@ Field3DParallel operator/(const Field3DParallel& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs; @@ -3015,7 +3015,7 @@ Field3DParallel operator+(const Field3DParallel& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs; @@ -3075,7 +3075,7 @@ Field3DParallel operator-(const Field3DParallel& lhs, const BoutReal rhs) { checkData(rhs); result.setRegion(lhs.getRegionID()); - if (lhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs; @@ -3135,7 +3135,7 @@ Field3DParallel operator*(const BoutReal lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); - if (rhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs * rhs.yup(i); @@ -3162,7 +3162,7 @@ Field3DParallel operator/(const BoutReal lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); - if (rhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs / rhs.yup(i); @@ -3189,7 +3189,7 @@ Field3DParallel operator+(const BoutReal lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); - if (rhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs + rhs.yup(i); @@ -3216,7 +3216,7 @@ Field3DParallel operator-(const BoutReal lhs, const Field3DParallel& rhs) { checkData(rhs); result.setRegion(rhs.getRegionID()); - if (rhs.isFci()) { + if (result.isFci()) { result.splitParallelSlices(); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs - rhs.yup(i); From 698b6cf11a05cdbb81655fe43d49551cede0005a Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 11:25:39 +0100 Subject: [PATCH 252/259] Add some asserts for Field3DParallel --- src/field/gen_fieldops.jinja | 2 ++ src/field/gen_fieldops.py | 12 ++++++---- src/field/generated_fieldops.cxx | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index a836fa1633..66b5103247 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -19,6 +19,8 @@ {% endif %} {% if out == "Field3DParallel" %} if ({{out.name}}.isFci()) { + {{ lhs.assertParallelSlices }} + {{ rhs.assertParallelSlices }} {{out.name}}.splitParallelSlices(); {% if lhs.region_type == "3D" %} for (size_t i{0} ; i < {{lhs.name}}.numberParallelSlices() ; ++i) { diff --git a/src/field/gen_fieldops.py b/src/field/gen_fieldops.py index 28dd18e54d..64d3771c55 100755 --- a/src/field/gen_fieldops.py +++ b/src/field/gen_fieldops.py @@ -163,8 +163,7 @@ def yup(self): If it is BoutReal just {{name}}""" if self.field_type == "BoutReal": return "{self.name}".format(self=self) - else: - return "{self.name}.yup(i)".format(self=self) + return "{self.name}.yup(i)".format(self=self) @property def ydown(self): @@ -172,8 +171,13 @@ def ydown(self): If it is BoutReal just {{name}}""" if self.field_type == "BoutReal": return "{self.name}".format(self=self) - else: - return "{self.name}.ydown(i)".format(self=self) + return "{self.name}.ydown(i)".format(self=self) + + @property + def assertParallelSlices(self): + if self.field_type == "BoutReal": + return "" + return f"ASSERT2({self.name}.hasParallelSlices());" def __eq__(self, other): try: diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index d3355a8947..5f66172302 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -2273,6 +2273,8 @@ Field3DParallel operator*(const Field3D& lhs, const Field3DParallel& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs.yup(i); result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); @@ -2301,6 +2303,8 @@ Field3DParallel operator/(const Field3D& lhs, const Field3DParallel& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs.yup(i); result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); @@ -2329,6 +2333,8 @@ Field3DParallel operator+(const Field3D& lhs, const Field3DParallel& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs.yup(i); result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); @@ -2357,6 +2363,8 @@ Field3DParallel operator-(const Field3D& lhs, const Field3DParallel& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs.yup(i); result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); @@ -2385,6 +2393,8 @@ Field3DParallel operator*(const Field3DParallel& lhs, const Field3D& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs.yup(i); result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); @@ -2449,6 +2459,8 @@ Field3DParallel operator/(const Field3DParallel& lhs, const Field3D& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs.yup(i); result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); @@ -2513,6 +2525,8 @@ Field3DParallel operator+(const Field3DParallel& lhs, const Field3D& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs.yup(i); result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); @@ -2577,6 +2591,8 @@ Field3DParallel operator-(const Field3DParallel& lhs, const Field3D& rhs) { result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs.yup(i); result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); @@ -2641,6 +2657,8 @@ Field3DParallel operator*(const Field3DParallel& lhs, const Field3DParallel& rhs result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs.yup(i); result.ydown(i) = lhs.ydown(i) * rhs.ydown(i); @@ -2705,6 +2723,8 @@ Field3DParallel operator/(const Field3DParallel& lhs, const Field3DParallel& rhs result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs.yup(i); result.ydown(i) = lhs.ydown(i) / rhs.ydown(i); @@ -2769,6 +2789,8 @@ Field3DParallel operator+(const Field3DParallel& lhs, const Field3DParallel& rhs result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs.yup(i); result.ydown(i) = lhs.ydown(i) + rhs.ydown(i); @@ -2833,6 +2855,8 @@ Field3DParallel operator-(const Field3DParallel& lhs, const Field3DParallel& rhs result.setRegion(lhs.getMesh()->getCommonRegion(lhs.getRegionID(), rhs.getRegionID())); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs.yup(i); result.ydown(i) = lhs.ydown(i) - rhs.ydown(i); @@ -2896,6 +2920,8 @@ Field3DParallel operator*(const Field3DParallel& lhs, const BoutReal rhs) { result.setRegion(lhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) * rhs; result.ydown(i) = lhs.ydown(i) * rhs; @@ -2956,6 +2982,8 @@ Field3DParallel operator/(const Field3DParallel& lhs, const BoutReal rhs) { result.setRegion(lhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) / rhs; result.ydown(i) = lhs.ydown(i) / rhs; @@ -3017,6 +3045,8 @@ Field3DParallel operator+(const Field3DParallel& lhs, const BoutReal rhs) { result.setRegion(lhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) + rhs; result.ydown(i) = lhs.ydown(i) + rhs; @@ -3077,6 +3107,8 @@ Field3DParallel operator-(const Field3DParallel& lhs, const BoutReal rhs) { result.setRegion(lhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + ASSERT2(lhs.hasParallelSlices()); + for (size_t i{0}; i < lhs.numberParallelSlices(); ++i) { result.yup(i) = lhs.yup(i) - rhs; result.ydown(i) = lhs.ydown(i) - rhs; @@ -3137,6 +3169,8 @@ Field3DParallel operator*(const BoutReal lhs, const Field3DParallel& rhs) { result.setRegion(rhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs * rhs.yup(i); result.ydown(i) = lhs * rhs.ydown(i); @@ -3164,6 +3198,8 @@ Field3DParallel operator/(const BoutReal lhs, const Field3DParallel& rhs) { result.setRegion(rhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs / rhs.yup(i); result.ydown(i) = lhs / rhs.ydown(i); @@ -3191,6 +3227,8 @@ Field3DParallel operator+(const BoutReal lhs, const Field3DParallel& rhs) { result.setRegion(rhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs + rhs.yup(i); result.ydown(i) = lhs + rhs.ydown(i); @@ -3218,6 +3256,8 @@ Field3DParallel operator-(const BoutReal lhs, const Field3DParallel& rhs) { result.setRegion(rhs.getRegionID()); if (result.isFci()) { result.splitParallelSlices(); + + ASSERT2(rhs.hasParallelSlices()); for (size_t i{0}; i < rhs.numberParallelSlices(); ++i) { result.yup(i) = lhs - rhs.yup(i); result.ydown(i) = lhs - rhs.ydown(i); From 6e428c14c2a0a7e63943569c3e7c1f1663f32e07 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 11:51:04 +0100 Subject: [PATCH 253/259] Ensure parallel slices are present --- src/mesh/coordinates.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index f2ae8c263b..4d596d99a4 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1814,7 +1814,7 @@ Coordinates::FieldMetric Coordinates::Laplace_par(const Field2D& f, CELL_LOC out Field3D Coordinates::Laplace_par(const Field3DParallel& f, CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); - return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * ::DDY(f, outloc) / J; + return D2DY2(f, outloc) / g_22 + DDY(J.asField3DParallel() / g_22, outloc) * ::DDY(f, outloc) / J; } // Full Laplacian operator on scalar field From 346ff3d66ff0333a83e45e8f1d422e1aa2ac4453 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 11:51:24 +0100 Subject: [PATCH 254/259] Simplify div_par --- src/mesh/coordinates.cxx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 4d596d99a4..918cdd1a09 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1619,13 +1619,8 @@ Field3D Coordinates::Div_par(const Field3DParallel& f, CELL_LOC outloc, auto coords = f.getCoordinates(); // Need to modify yup and ydown fields - Field3D f_B = f / coords->J * sqrt(coords->g_22); - f_B.splitParallelSlices(); - for (int i = 0; i < f.getMesh()->ystart; ++i) { - f_B.yup(i) = f.yup(i) / coords->J.yup(i) * sqrt(coords->g_22.yup(i)); - f_B.ydown(i) = f.ydown(i) / coords->J.ydown(i) * sqrt(coords->g_22.ydown(i)); - } - return setName(coords->J / sqrt(coords->g_22) * Grad_par(f_B, outloc, method), + Field3D Jg = coords->J / sqrt(coords->g_22.asField3DParallel()); + return setName(Jg * Grad_par(f / Jg, outloc, method), "Div_par({:s})", f.name); } From 96f792f1fbd7c0f1003a328243b951d445d518f6 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 11:51:47 +0100 Subject: [PATCH 255/259] Do not communicate the magnetic field --- tests/MMS/spatial/fci/fci_mms.cxx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/MMS/spatial/fci/fci_mms.cxx b/tests/MMS/spatial/fci/fci_mms.cxx index b9d335a3c4..265f14ea6e 100644 --- a/tests/MMS/spatial/fci/fci_mms.cxx +++ b/tests/MMS/spatial/fci/fci_mms.cxx @@ -39,12 +39,6 @@ int main(int argc, char** argv) { Field3D K{FieldFactory::get()->create3D("K", Options::getRoot(), mesh)}; // Communicate to calculate parallel transform. - if constexpr (bout::build::use_metric_3d) { - // Div_par operators require B parallel slices: - // Coordinates::geometry doesn't ensure this (yet) - auto& Bxy = mesh->getCoordinates()->Bxy; - mesh->communicate(Bxy); - } mesh->communicate(input, K); Options dump; From aad01826777a0ae125264bd588fb01802f1a3a06 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 11:52:52 +0100 Subject: [PATCH 256/259] Ensure parallel slices are set in FIELD_FUNC --- include/bout/field.hxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/bout/field.hxx b/include/bout/field.hxx index 27e7fb2b89..7786f78e37 100644 --- a/include/bout/field.hxx +++ b/include/bout/field.hxx @@ -528,6 +528,7 @@ T pow(BoutReal lhs, const T& rhs, const std::string& rgn = "RGN_ALL") { * result for non-finite numbers * */ +class Field3DParallel; #ifdef FIELD_FUNC #error This macro has already been defined #else @@ -540,6 +541,12 @@ T pow(BoutReal lhs, const T& rhs, const std::string& rgn = "RGN_ALL") { /* Define and allocate the output result */ \ T result{emptyFrom(f)}; \ BOUT_FOR(d, result.getRegion(rgn)) { result[d] = func(f[d]); } \ + if constexpr (std::is_base_of_v) { \ + for (int i = 0; i < f.numberParallelSlices(); ++i) { \ + result.yup(i) = func(f.yup(i)); \ + result.ydown(i) = func(f.ydown(i)); \ + } \ + } \ result.name = std::string(#_name "(") + f.name + std::string(")"); \ checkData(result); \ return result; \ From 87cc79a51b3c5817522efbdd70c9f787088d9755 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 11:53:49 +0100 Subject: [PATCH 257/259] fixup bad merge --- src/mesh/parallel/fci.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index f533fae541..3f3e7b0ebf 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -63,6 +63,7 @@ #include namespace { +using namespace std::literals; // Get a unique name for a field based on the sign/magnitude of the offset std::string parallel_slice_field_name(std::string field, int offset) { const auto direction = (offset > 0) ? "forward"sv : "backward"sv; @@ -234,18 +235,18 @@ FCIMap::FCIMap(Mesh& mesh, [[maybe_unused]] const Coordinates::FieldMetric& dy, " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("xt_prime", offset_)); } - if (map_mesh.get(zt_prime, parallel_slice_field_name("zt_prime", offset_), 0.0, false) + if (map_mesh->get(zt_prime, parallel_slice_field_name("zt_prime", offset_), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("zt_prime", offset_)); } - if (map_mesh.get(R_prime, parallel_slice_field_name("R", offset_), 0.0, false) != 0) { + if (map_mesh->get(R_prime, parallel_slice_field_name("R", offset_), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("R", offset_)); } - if (map_mesh.get(Z_prime, parallel_slice_field_name("Z", offset_), 0.0, false) != 0) { + if (map_mesh->get(Z_prime, parallel_slice_field_name("Z", offset_), 0.0, false) != 0) { throw BoutException("Could not read {:s} from grid file!\n" " Either add it to the grid file, or reduce MYG", parallel_slice_field_name("Z", offset_)); @@ -296,8 +297,8 @@ FCIMap::FCIMap(Mesh& mesh, [[maybe_unused]] const Coordinates::FieldMetric& dy, const int ncz = map_mesh->LocalNz; BoutMask to_remove(map_mesh); - const int xend = - map_mesh.xstart + (map_mesh.xend - map_mesh.xstart + 1) * map_mesh.getNXPE() - 1; + const int xend = map_mesh->xstart + + (map_mesh->xend - map_mesh->xstart + 1) * map_mesh->getNXPE() - 1; // Default to the maximum number of points const int defValid{map_mesh->ystart - 1 + std::abs(offset)}; // Serial loop because call to BoundaryRegionPar::addPoint @@ -368,7 +369,7 @@ FCIMap::FCIMap(Mesh& mesh, [[maybe_unused]] const Coordinates::FieldMetric& dy, // that also means inner. So to differentiate between inner and outer we // need at least 2 points in the domain. ASSERT2(map_mesh->xend - map_mesh->xstart >= 2); - auto boundary = (xt_prime[i] < map_mesh.xstart) ? inner_boundary : outer_boundary; + auto boundary = (xt_prime[i] < map_mesh->xstart) ? inner_boundary : outer_boundary; if (!boundary->contains(x, y, z)) { boundary->add_point(x, y, z, x + dx, y + offset - sgn(offset) * 0.5, z + dz, // Intersection point in local index space From ec8b6d48be6f7802fc562f9f4407a3c27331522d Mon Sep 17 00:00:00 2001 From: dschwoerer <5637662+dschwoerer@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:54:41 +0000 Subject: [PATCH 258/259] Apply clang-format changes --- src/mesh/coordinates.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 918cdd1a09..24bf2de0ba 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1620,8 +1620,7 @@ Field3D Coordinates::Div_par(const Field3DParallel& f, CELL_LOC outloc, auto coords = f.getCoordinates(); // Need to modify yup and ydown fields Field3D Jg = coords->J / sqrt(coords->g_22.asField3DParallel()); - return setName(Jg * Grad_par(f / Jg, outloc, method), - "Div_par({:s})", f.name); + return setName(Jg * Grad_par(f / Jg, outloc, method), "Div_par({:s})", f.name); } ///////////////////////////////////////////////////////// @@ -1809,7 +1808,8 @@ Coordinates::FieldMetric Coordinates::Laplace_par(const Field2D& f, CELL_LOC out Field3D Coordinates::Laplace_par(const Field3DParallel& f, CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); - return D2DY2(f, outloc) / g_22 + DDY(J.asField3DParallel() / g_22, outloc) * ::DDY(f, outloc) / J; + return D2DY2(f, outloc) / g_22 + + DDY(J.asField3DParallel() / g_22, outloc) * ::DDY(f, outloc) / J; } // Full Laplacian operator on scalar field From 9de0c341035ba05c37dd16f763e51ebfca1eb970 Mon Sep 17 00:00:00 2001 From: David Bold Date: Wed, 5 Nov 2025 12:50:23 +0100 Subject: [PATCH 259/259] Only run fci test for 3D metric --- tests/MMS/spatial/fci/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/MMS/spatial/fci/CMakeLists.txt b/tests/MMS/spatial/fci/CMakeLists.txt index 94b9682c9c..b01c765fa6 100644 --- a/tests/MMS/spatial/fci/CMakeLists.txt +++ b/tests/MMS/spatial/fci/CMakeLists.txt @@ -3,5 +3,6 @@ bout_add_mms_test(MMS-spatial-fci USE_RUNTEST USE_DATA_BOUT_INP REQUIRES zoidberg_FOUND + REQUIRES BOUT_USE_METRIC_3D PROCESSORS 2 )