diff --git a/.github/actions/install/install-struphy/action.yml b/.github/actions/install/install-struphy/action.yml index 319fff78a..ab2148a94 100644 --- a/.github/actions/install/install-struphy/action.yml +++ b/.github/actions/install/install-struphy/action.yml @@ -1,4 +1,4 @@ -name: "Clone and install struphy" +name: "Install struphy in env" inputs: optional-deps: @@ -12,6 +12,8 @@ runs: - name: Install struphy shell: bash run: | + python3 -m venv env + source env/bin/activate pip install --upgrade pip pip install ".[${{ inputs.optional-deps }}]" pip list diff --git a/.github/actions/tests/unit-mpi/action.yml b/.github/actions/tests/unit-mpi/action.yml new file mode 100644 index 000000000..fe7e2cc2e --- /dev/null +++ b/.github/actions/tests/unit-mpi/action.yml @@ -0,0 +1,9 @@ +name: "Run unit tests with MPI" + +runs: + using: composite + steps: + - name: Run unit tests with MPI + shell: bash + run: | + struphy test unit --mpi 2 diff --git a/.github/actions/tests/unit/action.yml b/.github/actions/tests/unit/action.yml index 7642c2040..d2e4ac787 100644 --- a/.github/actions/tests/unit/action.yml +++ b/.github/actions/tests/unit/action.yml @@ -5,6 +5,8 @@ runs: steps: - name: Run unit tests with MPI shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-${{ matrix.test-type }} run: | struphy compile --status # run: | diff --git a/.github/workflows/test-PR-models-clones.yml b/.github/workflows/test-PR-models-clones.yml new file mode 100644 index 000000000..6930bf6c0 --- /dev/null +++ b/.github/workflows/test-PR-models-clones.yml @@ -0,0 +1,79 @@ +name: PR - domain cloning in Container + +on: + pull_request: + branches: + - devel + push: + branches: + - devel + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + model-tests-in-container-with-struphy: + runs-on: ubuntu-latest + + container: + image: ghcr.io/struphy-hub/struphy/ubuntu-with-struphy:latest + credentials: + username: spossann + password: ${{ secrets.GHCR_TOKEN }} + + steps: + - name: Check for dockerenv file + run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv) + + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Check .testmondata 1 + run: | + ls .testmon* || echo "No .testmondata" + + - name: Setup cache for testmon + uses: actions/cache@v4 + with: + path: | + .testmondata-clones + key: testmon-clones-${{ github.ref_name }}-${{ github.event.number }}-${{ github.run_number }} + restore-keys: | + testmon-clones-${{ github.ref_name }}-${{ github.event.number }}- + testmon-clones-${{ github.ref_name }} + testmon-clones-devel + testmon-clones- + + - name: Check .testmondata 2 + run: | + ls .testmon* || echo "No .testmondata" + + # This step can be removed when the updated ghcr images are pushed + - name: Install sqlite + shell: bash + run: apt install -y sqlite3 + + - name: Install Struphy in Container + uses: ./.github/actions/install/struphy_in_container + + - name: Compile Struphy + run: | + source /struphy_c_/env_c_/bin/activate + struphy compile + + - name: Verification tests with clones + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-clones + run: | + source /struphy_c_/env_c_/bin/activate + struphy test verification --mpi 4 --nclones 2 \ No newline at end of file diff --git a/.github/workflows/test-PR-models.yml b/.github/workflows/test-PR-models.yml index 585f20929..292adcc2d 100644 --- a/.github/workflows/test-PR-models.yml +++ b/.github/workflows/test-PR-models.yml @@ -4,6 +4,9 @@ on: pull_request: branches: - devel + push: + branches: + - devel workflow_dispatch: concurrency: @@ -20,51 +23,98 @@ permissions: jobs: model-tests-in-container-with-struphy: runs-on: ubuntu-latest + container: image: ghcr.io/struphy-hub/struphy/ubuntu-with-struphy:latest credentials: username: spossann password: ${{ secrets.GHCR_TOKEN }} - steps: + steps: - name: Check for dockerenv file run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv) - name: Checkout repo uses: actions/checkout@v4 + - name: Check .testmondata 1 + run: | + ls .testmon* || echo "No .testmondata" + + - name: Setup cache for testmon + uses: actions/cache@v4 + with: + path: | + .testmondata-model + .testmondata-model-mpi + key: testmon-model-${{ github.ref_name }}-${{ github.event.number }}-${{ github.run_number }} + restore-keys: | + testmon-model-${{ github.ref_name }}-${{ github.event.number }}- + testmon-model-${{ github.ref_name }} + testmon-model-devel + testmon-model- + + - name: Check .testmondata 2 + run: | + ls .testmon* || echo "No .testmondata" + + # This step can be removed when the updated ghcr images are pushed + - name: Install sqlite + shell: bash + run: apt install -y sqlite3 + - name: Install Struphy in Container uses: ./.github/actions/install/struphy_in_container - name: Compile Struphy run: | - which python3 source /struphy_c_/env_c_/bin/activate - which python3 struphy compile - - name: Model tests + - name: LinearMHD test shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-model run: | - which python3 source /struphy_c_/env_c_/bin/activate - which python3 - struphy compile --status struphy test LinearMHD + + - name: Toy test + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-model + run: | + source /struphy_c_/env_c_/bin/activate struphy test toy + + - name: Model tests + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-model + run: | + source /struphy_c_/env_c_/bin/activate struphy test models - struphy test verification + + - name: Verification tests + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-model + run: | + source /struphy_c_/env_c_/bin/activate + struphy test verification - name: Model tests with MPI shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-model-mpi run: | - which python3 source /struphy_c_/env_c_/bin/activate - which python3 - struphy compile --status - struphy test models struphy test models --mpi 2 - struphy test verification --mpi 1 - struphy test verification --mpi 4 - struphy test verification --mpi 4 --nclones 2 - struphy test VlasovAmpereOneSpecies --mpi 2 --nclones 2 + + - name: Verification tests with 2 MPI + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-model-mpi + run: | + source /struphy_c_/env_c_/bin/activate + struphy test verification --mpi 2 \ No newline at end of file diff --git a/.github/workflows/test-PR-pure-python.yml b/.github/workflows/test-PR-pure-python.yml new file mode 100644 index 000000000..c49fce20d --- /dev/null +++ b/.github/workflows/test-PR-pure-python.yml @@ -0,0 +1,140 @@ +name: PR - pure Python tests in Container + +on: + pull_request: + branches: + - devel + push: + branches: + - devel + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + model-tests-in-container-with-reqs: + runs-on: ubuntu-latest + + container: + image: ghcr.io/struphy-hub/struphy/ubuntu-with-reqs:latest + credentials: + username: spossann + password: ${{ secrets.GHCR_TOKEN }} + + steps: + - name: Check for dockerenv file + run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv) + + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Check .testmondata 1 + run: | + ls .testmon* || echo "No .testmondata" + + - name: Setup cache for testmon + uses: actions/cache@v4 + with: + path: | + .testmondata-pure-python + .testmondata-pure-python-mpi + key: testmon-pure-python-${{ github.ref_name }}-${{ github.event.number }}-${{ github.run_number }} + restore-keys: | + testmon-pure-python-${{ github.ref_name }}-${{ github.event.number }}- + testmon-pure-python-${{ github.ref_name }} + testmon-pure-python-devel + testmon-pure-python- + + - name: Check .testmondata 2 + run: | + ls .testmon* || echo "No .testmondata" + + # This step can be removed when the updated ghcr images are pushed + - name: Install sqlite + shell: bash + run: apt install -y sqlite3 + + - name: Install Struphy + uses: ./.github/actions/install/install-struphy + + - name: LinearMHD test + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python + run: | + source env/bin/activate + struphy compile --status + struphy test LinearMHD + + - name: Vlasov test + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python + run: | + source env/bin/activate + struphy test Vlasov + + - name: GuidingCenter test + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python + run: | + source env/bin/activate + struphy test GuidingCenter + + - name: VlasovAmpere test + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python + run: | + source env/bin/activate + struphy test VlasovAmpereOneSpecies + + - name: EulerSPH test + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python + run: | + source env/bin/activate + struphy test EulerSPH + + - name: Vlasov test MPI + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python-mpi + run: | + source env/bin/activate + struphy test Vlasov --mpi 2 + + - name: GuidingCenter test MPI + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python-mpi + run: | + source env/bin/activate + struphy test GuidingCenter --mpi 2 + + - name: VlasovAmpere test MPI + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python-mpi + run: | + source env/bin/activate + struphy test VlasovAmpereOneSpecies --mpi 2 + + - name: EulerSPH test MPI + shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-pure-python-mpi + run: | + source env/bin/activate + struphy test EulerSPH --mpi 2 diff --git a/.github/workflows/test-PR-unit.yml b/.github/workflows/test-PR-unit.yml index acdaf0a8a..a0f60274a 100644 --- a/.github/workflows/test-PR-unit.yml +++ b/.github/workflows/test-PR-unit.yml @@ -4,6 +4,9 @@ on: pull_request: branches: - devel + push: + branches: + - devel workflow_dispatch: concurrency: @@ -20,50 +23,70 @@ permissions: jobs: unit-tests-in-container-with-struphy: runs-on: ubuntu-latest + container: image: ghcr.io/struphy-hub/struphy/ubuntu-with-struphy:latest credentials: username: spossann password: ${{ secrets.GHCR_TOKEN }} - steps: + steps: - name: Check for dockerenv file run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv) - name: Checkout repo uses: actions/checkout@v4 + - name: Check .testmondata 1 + run: | + ls .testmon* || echo "No .testmondata" + + - name: Setup cache for testmon + uses: actions/cache@v4 + with: + path: | + .testmondata-unit + .testmondata-unit-mpi + key: testmon-unit-${{ github.ref_name }}-${{ github.event.number }}-${{ github.run_number }} + restore-keys: | + testmon-unit-${{ github.ref_name }}-${{ github.event.number }}- + testmon-unit-${{ github.ref_name }} + testmon-unit-devel + testmon-unit- + + - name: Check .testmondata 2 + run: | + ls .testmon* || echo "No .testmondata" + + # This step can be removed when the updated ghcr images are pushed + - name: Install sqlite + shell: bash + run: apt install -y sqlite3 + - name: Install Struphy in Container uses: ./.github/actions/install/struphy_in_container - name: Compile Struphy run: | - which python3 source /struphy_c_/env_c_/bin/activate - which python3 struphy compile - name: Run unit tests shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-unit run: | - which python3 source /struphy_c_/env_c_/bin/activate - which python3 struphy compile --status - struphy --refresh-models pip show mpi4py pip uninstall -y mpi4py struphy test unit - name: Run unit tests with MPI shell: bash + env: + TESTMON_DATAFILE: ${{ github.workspace }}/.testmondata-unit-mpi run: | - which python3 source /struphy_c_/env_c_/bin/activate - which python3 - struphy compile --status - struphy --refresh-models pip install -U mpi4py - struphy test unit --mpi 2 - - + struphy test unit --mpi 2 \ No newline at end of file diff --git a/.github/workflows/ubuntu-latest.yml b/.github/workflows/ubuntu-latest.yml index 847adf982..91b46a929 100644 --- a/.github/workflows/ubuntu-latest.yml +++ b/.github/workflows/ubuntu-latest.yml @@ -1,9 +1,6 @@ name: Ubuntu on: - push: - branches: - - devel schedule: # run at 1 a.m. on Sunday - cron: "0 1 * * 0" diff --git a/docker/ubuntu-latest-with-struphy.dockerfile b/docker/ubuntu-latest-with-struphy.dockerfile index dcde6b07e..6170c594d 100644 --- a/docker/ubuntu-latest-with-struphy.dockerfile +++ b/docker/ubuntu-latest-with-struphy.dockerfile @@ -31,7 +31,7 @@ RUN apt install -y libopenmpi-dev openmpi-bin \ && apt install -y libomp-dev libomp5 RUN apt install -y git \ - && apt install -y pandoc graphviz \ + && apt install -y pandoc graphviz sqlite3 \ && bash -c "source ~/.bashrc" # for gvec diff --git a/docker/ubuntu-latest.dockerfile b/docker/ubuntu-latest.dockerfile index 386426c29..7c82e4e7c 100644 --- a/docker/ubuntu-latest.dockerfile +++ b/docker/ubuntu-latest.dockerfile @@ -31,7 +31,7 @@ RUN apt install -y libopenmpi-dev openmpi-bin \ && apt install -y libomp-dev libomp5 RUN apt install -y git \ - && apt install -y pandoc graphviz \ + && apt install -y pandoc graphviz sqlite3 \ && bash -c "source ~/.bashrc" # for gvec diff --git a/pyproject.toml b/pyproject.toml index 201452c06..76c1e0b0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ dependencies = [ 'argcomplete', 'pytest', 'pytest-mpi', + 'pytest-testmon', 'line_profiler', ] diff --git a/src/struphy/conftest.py b/src/struphy/conftest.py index 05e10b55e..9f7247be4 100644 --- a/src/struphy/conftest.py +++ b/src/struphy/conftest.py @@ -1,3 +1,11 @@ +import pytest + + +def pytest_unconfigure(config): + if hasattr(config, "testmon_data"): + config.testmon_data.db.con.close() + + def pytest_addoption(parser): parser.addoption("--with-desc", action="store_true") parser.addoption("--vrbose", action="store_true") diff --git a/src/struphy/console/test.py b/src/struphy/console/test.py index ab64707e3..be5f2a1a1 100644 --- a/src/struphy/console/test.py +++ b/src/struphy/console/test.py @@ -1,5 +1,10 @@ +import os + +import struphy from struphy.utils.utils import subp_run +LIBPATH = struphy.__path__[0] + def struphy_test( group: str, @@ -35,22 +40,36 @@ def struphy_test( """ if "unit" in group: + list_of_tests = [ + f"{LIBPATH}/bsplines/tests/", + f"{LIBPATH}/console/tests/", + f"{LIBPATH}/feec/tests/", + f"{LIBPATH}/fields_background/tests/", + f"{LIBPATH}/geometry/tests/", + f"{LIBPATH}/initial/tests/", + f"{LIBPATH}/kinetic_background/tests/", + f"{LIBPATH}/linear_algebra/tests/", + f"{LIBPATH}/ode/tests/", + f"{LIBPATH}/pic/tests/", + f"{LIBPATH}/polar/tests/", + f"{LIBPATH}/post_processing/tests/", + f"{LIBPATH}/propagators/tests/", + ] + if mpi > 1: cmd = [ "mpirun", "-n", str(mpi), "pytest", - "-k", - "not _models and not _tutorial and not pproc and not _verif_", + "--testmon", "--with-mpi", - ] + ] + list_of_tests else: cmd = [ "pytest", - "-k", - "not _models and not _tutorial and not pproc and not _verif_", - ] + "--testmon", + ] + list_of_tests if with_desc: cmd += ["--with-desc"] @@ -62,6 +81,10 @@ def struphy_test( subp_run(cmd) elif group in {"models", "fluid", "kinetic", "hybrid", "toy"}: + list_of_tests = [ + f"{LIBPATH}/models/tests/default_params/", + ] + if mpi > 1: cmd = [ "mpirun", @@ -69,22 +92,18 @@ def struphy_test( "-n", str(mpi), "pytest", - "-k", - "_models", "-m", group, - "-s", + "--testmon-forceselect", "--with-mpi", - ] + ] + list_of_tests else: cmd = [ "pytest", - "-k", - "_models", "-m", group, - "-s", - ] + "--testmon-forceselect", + ] + list_of_tests if vrbose: cmd += ["--vrbose"] @@ -92,9 +111,14 @@ def struphy_test( cmd += ["--nclones", f"{nclones}"] if show_plots: cmd += ["--show-plots"] + subp_run(cmd) elif "verification" in group: + list_of_tests = [ + f"{LIBPATH}/models/tests/verification/", + ] + if mpi > 1: cmd = [ "mpirun", @@ -102,18 +126,14 @@ def struphy_test( "-n", str(mpi), "pytest", - "-k", - "_verif_", - "-s", + "--testmon", "--with-mpi", - ] + ] + list_of_tests else: cmd = [ "pytest", - "-k", - "_verif_", - "-s", - ] + "--testmon", + ] + list_of_tests if vrbose: cmd += ["--vrbose"] @@ -121,6 +141,7 @@ def struphy_test( cmd += ["--nclones", f"{nclones}"] if show_plots: cmd += ["--show-plots"] + subp_run(cmd) else: @@ -130,10 +151,9 @@ def struphy_test( "-n", str(mpi), "pytest", - "-k", - "_models", "-m", "single", + "--testmon-forceselect", "-s", "--with-mpi", "--model-name", @@ -145,4 +165,5 @@ def struphy_test( cmd += ["--nclones", f"{nclones}"] if show_plots: cmd += ["--show-plots"] + subp_run(cmd) diff --git a/src/struphy/models/tests/default_params/__init__.py b/src/struphy/models/tests/default_params/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/struphy/models/tests/default_params/test_models.py b/src/struphy/models/tests/default_params/test_models.py new file mode 100644 index 000000000..e87f87ebf --- /dev/null +++ b/src/struphy/models/tests/default_params/test_models.py @@ -0,0 +1,67 @@ +import pytest + +from struphy.models.tests import utils_testing as ut + + +# specific tests +@pytest.mark.models +@pytest.mark.toy +@pytest.mark.parametrize("model", ut.toy_models) +def test_toy( + model: str, + vrbose: bool, + nclones: int, + show_plots: bool, +): + ut.call_test(model_name=model, module=ut.toy, verbose=vrbose) + + +@pytest.mark.models +@pytest.mark.fluid +@pytest.mark.parametrize("model", ut.fluid_models) +def test_fluid( + model: str, + vrbose: bool, + nclones: int, + show_plots: bool, +): + ut.call_test(model_name=model, module=ut.fluid, verbose=vrbose) + + +@pytest.mark.models +@pytest.mark.kinetic +@pytest.mark.parametrize("model", ut.kinetic_models) +def test_kinetic( + model: str, + vrbose: bool, + nclones: int, + show_plots: bool, +): + ut.call_test(model_name=model, module=ut.kinetic, verbose=vrbose) + + +@pytest.mark.models +@pytest.mark.hybrid +@pytest.mark.parametrize("model", ut.hybrid_models) +def test_hybrid( + model: str, + vrbose: bool, + nclones: int, + show_plots: bool, +): + ut.call_test(model_name=model, module=ut.hybrid, verbose=vrbose) + + +@pytest.mark.single +def test_single_model( + model_name: str, + vrbose: bool, + nclones: int, + show_plots: bool, +): + ut.call_test(model_name=model_name, module=None, verbose=vrbose) + + +if __name__ == "__main__": + test_toy("Maxwell") + test_fluid("LinearMHD") diff --git a/src/struphy/models/tests/test_xxpproc.py b/src/struphy/models/tests/test_xxpproc.py deleted file mode 100644 index 3d4fef2f0..000000000 --- a/src/struphy/models/tests/test_xxpproc.py +++ /dev/null @@ -1,69 +0,0 @@ -def test_pproc_codes(model: str = None, group: str = None): - """Tests the post processing of runs in test_codes.py""" - - import inspect - import os - - from psydac.ddm.mpi import mpi as MPI - - import struphy - from struphy.models import fluid, hybrid, kinetic, toy - from struphy.post_processing import pproc_struphy - - comm = MPI.COMM_WORLD - - libpath = struphy.__path__[0] - - list_fluid = [] - for name, obj in inspect.getmembers(fluid): - if inspect.isclass(obj) and obj.__module__ == fluid.__name__: - if name not in {"StruphyModel", "Propagator"}: - list_fluid += [name] - - list_kinetic = [] - for name, obj in inspect.getmembers(kinetic): - if inspect.isclass(obj) and obj.__module__ == kinetic.__name__: - if name not in {"StruphyModel", "KineticBackground", "Propagator"}: - list_kinetic += [name] - - list_hybrid = [] - for name, obj in inspect.getmembers(hybrid): - if inspect.isclass(obj) and obj.__module__ == hybrid.__name__: - if name not in {"StruphyModel", "Propagator"}: - list_hybrid += [name] - - list_toy = [] - for name, obj in inspect.getmembers(toy): - if inspect.isclass(obj) and obj.__module__ == toy.__name__: - if name not in {"StruphyModel", "Propagator"}: - list_toy += [name] - - if group is None: - list_models = list_fluid + list_kinetic + list_hybrid + list_toy - elif group == "fluid": - list_models = list_fluid - elif group == "kinetic": - list_models = list_kinetic - elif group == "hybrid": - list_models = list_hybrid - elif group == "toy": - list_models = list_toy - else: - raise ValueError(f"{group =} is not a valid group specification.") - - if comm.Get_rank() == 0: - if model is None: - for model in list_models: - if "Variational" in model or "Visco" in model: - print(f"Model {model} is currently excluded from tests.") - continue - - path_out = os.path.join(libpath, "io/out/test_" + model) - pproc_struphy.main(path_out) - else: - path_out = os.path.join(libpath, "io/out/test_" + model) - pproc_struphy.main(path_out) - - -if __name__ == "__main__": - test_pproc_codes() diff --git a/src/struphy/models/tests/util.py b/src/struphy/models/tests/util.py deleted file mode 100644 index 502390262..000000000 --- a/src/struphy/models/tests/util.py +++ /dev/null @@ -1,426 +0,0 @@ -import copy -import inspect -import os -import sys - -import yaml -from psydac.ddm.mpi import mpi as MPI - -import struphy -from struphy.console.main import recursive_get_files -from struphy.io.setup import descend_options_dict -from struphy.main import main -from struphy.models.base import StruphyModel - -libpath = struphy.__path__[0] - - -def wrapper_for_testing( - mtype: str = "fluid", - map_and_equil: tuple | list = ("Cuboid", "HomogenSlab"), - fast: bool = True, - vrbose: bool = False, - verification: bool = False, - nclones: int = 1, - show_plots: bool = False, - model: str = None, - Tend: float = None, -): - """Wrapper for testing Struphy models. - - If model is not None, tests the specified model. - The argument "fast" is a pytest option that can be specified at the command line (see conftest.py). - """ - - if mtype == "fluid": - from struphy.models import fluid as modmod - elif mtype == "kinetic": - from struphy.models import kinetic as modmod - elif mtype == "hybrid": - from struphy.models import hybrid as modmod - elif mtype == "toy": - from struphy.models import toy as modmod - else: - raise ValueError(f'{mtype} must be either "fluid", "kinetic", "hybrid" or "toy".') - - comm = MPI.COMM_WORLD - - if model is None: - for key, val in inspect.getmembers(modmod): - if inspect.isclass(val) and val.__module__ == modmod.__name__: - # TODO: remove if-clauses - if "LinearExtendedMHD" in key and "HomogenSlab" not in map_and_equil[1]: - print(f"Model {key} is currently excluded from tests with mhd_equil other than HomogenSlab.") - continue - - if fast and "Cuboid" not in map_and_equil[0]: - print(f"Fast is enabled, mapping {map_and_equil[0]} skipped ...") - continue - - call_test( - key, - val, - map_and_equil, - Tend=Tend, - verbose=vrbose, - comm=comm, - verification=verification, - nclones=nclones, - show_plots=show_plots, - ) - else: - assert model in modmod.__dir__(), f"{model} not in {modmod.__name__}, please specify correct model type." - val = getattr(modmod, model) - - # TODO: remove if-clause - if "LinearExtendedMHD" in model and "HomogenSlab" not in map_and_equil[1]: - print(f"Model {model} is currently excluded from tests with mhd_equil other than HomogenSlab.") - sys.exit(0) - - call_test( - model, - val, - map_and_equil, - Tend=Tend, - verbose=vrbose, - comm=comm, - verification=verification, - nclones=nclones, - show_plots=show_plots, - ) - - -def call_test( - model_name: str, - model: StruphyModel, - map_and_equil: tuple, - *, - Tend: float = None, - verbose: bool = True, - comm=None, - verification: bool = False, - nclones: int = 1, - show_plots: bool = False, -): - """Does testing of one model, either all options or verification. - - Parameters - ---------- - model_name : str - Model name. - - model : StruphyModel - Instance of model base class. - - map_and_equil : tuple[str] - Name of mapping and MHD equilibirum. - - nclones : int - Number of domain clones. - - Tend : float - End time of simulation other than default. - - verbose : bool - Show info on screen. - - verification : bool - Do verifiaction runs. - - show_plots: bool - Show plots of verification tests. - """ - if "SPH" in model_name: - nclones = 1 - rank = comm.Get_rank() - - if verification: - ver_path = os.path.join(libpath, "io", "inp", "verification") - yml_files = recursive_get_files(ver_path, contains=(model_name,)) - if len(yml_files) == 0: - if MPI.COMM_WORLD.Get_rank() == 0: - print(f"\nVerification run not started: no .yml files for model {model_name} in {ver_path}.") - return - params_list = [] - paths_out = [] - py_scripts = [] - if MPI.COMM_WORLD.Get_rank() == 0: - print("\nThe following verification tests will be run:") - for n, file in enumerate(yml_files): - ref = file.split("_")[0] - if ref != model_name: - continue - if MPI.COMM_WORLD.Get_rank() == 0: - print(file) - with open(os.path.join(ver_path, file)) as tmp: - params_list += [yaml.load(tmp, Loader=yaml.FullLoader)] - paths_out += [os.path.join(libpath, "io", "out", "verification", model_name, f"{n + 1}")] - - # python scripts for data verification after the run below - from struphy.models.tests import verification as verif - - tname = file.split(".")[0] - try: - py_scripts += [getattr(verif, tname)] - except: - if MPI.COMM_WORLD.Get_rank() == 0: - print(f"A Python script for {model_name} is missing in models/tests/verification.py, exiting ...") - sys.exit(1) - else: - params = model.generate_default_parameter_file(save=False) - params["geometry"]["type"] = map_and_equil[0] - params["geometry"][map_and_equil[0]] = {} - params["fluid_background"][map_and_equil[1]] = {} - params_list = [params] - paths_out = [os.path.join(libpath, "io/out/test_" + model_name)] - py_scripts = [None] - - # run model - for parameters, path_out, py_script in zip(params_list, paths_out, py_scripts): - if Tend is not None: - parameters["time"]["Tend"] = Tend - if MPI.COMM_WORLD.Get_rank() == 0: - print_test_params(parameters) - main( - model_name, - parameters, - path_out, - save_step=int( - Tend / parameters["time"]["dt"], - ), - num_clones=nclones, - verbose=verbose, - ) - return - else: - # run with default - if MPI.COMM_WORLD.Get_rank() == 0: - print_test_params(parameters) - main( - model_name, - parameters, - path_out, - num_clones=nclones, - verbose=verbose, - ) - - # run the verification script on the output data - if verification: - py_script( - path_out, - rank, - show_plots=show_plots, - ) - - # run available options (if present) - if not verification: - d_opts, test_list = find_model_options(model, parameters) - params_default = copy.deepcopy(parameters) - - if len(d_opts["em_fields"]) > 0: - for opts_dict in d_opts["em_fields"]: - parameters = copy.deepcopy(params_default) - for opt in opts_dict: - parameters["em_fields"]["options"] = opt - - # test only if not aready tested - if any([opt == i for i in test_list]): - continue - else: - test_list += [opt] - if MPI.COMM_WORLD.Get_rank() == 0: - print_test_params(parameters) - main( - model_name, - parameters, - path_out, - num_clones=nclones, - verbose=verbose, - ) - - if len(d_opts["fluid"]) > 0: - for species, opts_dicts in d_opts["fluid"].items(): - for opts_dict in opts_dicts: - parameters = copy.deepcopy(params_default) - for opt in opts_dict: - parameters["fluid"][species]["options"] = opt - - # test only if not aready tested - if any([opt == i for i in test_list]): - continue - else: - test_list += [opt] - if MPI.COMM_WORLD.Get_rank() == 0: - print_test_params(parameters) - main( - model_name, - parameters, - path_out, - num_clones=nclones, - verbose=verbose, - ) - - if len(d_opts["kinetic"]) > 0: - for species, opts_dicts in d_opts["kinetic"].items(): - for opts_dict in opts_dicts: - parameters = copy.deepcopy(params_default) - for opt in opts_dict: - parameters["kinetic"][species]["options"] = opt - - # test only if not aready tested - if any([opt == i for i in test_list]): - continue - else: - test_list += [opt] - if MPI.COMM_WORLD.Get_rank() == 0: - print_test_params(parameters) - main( - model_name, - parameters, - path_out, - num_clones=nclones, - verbose=verbose, - ) - - -def print_test_params(parameters): - print("\nOptions of this test run:") - for k, v in parameters.items(): - if k == "em_fields": - if "options" in v: - print("\nem_fields:") - for kk, vv in v["options"].items(): - print(" " * 4, kk) - print(" " * 8, vv) - elif k in ("fluid", "kinetic"): - print(f"\n{k}:") - for kk, vv in v.items(): - if "options" in vv: - for kkk, vvv in vv["options"].items(): - print(" " * 4, kkk) - print(" " * 8, vvv) - - -def find_model_options( - model: StruphyModel, - parameters: dict, -): - """Find all options of a model and store them in d_opts. - The default options are also stored in test_list.""" - - d_opts = {"em_fields": [], "fluid": {}, "kinetic": {}} - # find out the em_fields options of the model - if "em_fields" in parameters: - if "options" in parameters["em_fields"]: - # create the default options parameters - d_default = parameters["em_fields"]["options"] - - # create a list of parameter dicts for the different options - descend_options_dict( - model.options()["em_fields"]["options"], - d_opts["em_fields"], - d_default=d_default, - ) - - for name in model.species()["fluid"]: - # find out the fluid options of the model - if "options" in parameters["fluid"][name]: - # create the default options parameters - d_default = parameters["fluid"][name]["options"] - - d_opts["fluid"][name] = [] - - # create a list of parameter dicts for the different options - descend_options_dict( - model.options()["fluid"][name]["options"], - d_opts["fluid"][name], - d_default=d_default, - ) - - for name in model.species()["kinetic"]: - # find out the kinetic options of the model - if "options" in parameters["kinetic"][name]: - # create the default options parameters - d_default = parameters["kinetic"][name]["options"] - - d_opts["kinetic"][name] = [] - - # create a list of parameter dicts for the different options - descend_options_dict( - model.options()["kinetic"][name]["options"], - d_opts["kinetic"][name], - d_default=d_default, - ) - - # store default options - test_list = [] - if "options" in model.options()["em_fields"]: - test_list += [parameters["em_fields"]["options"]] - if "fluid" in parameters: - for species in parameters["fluid"]: - if "options" in model.options()["fluid"][species]: - test_list += [parameters["fluid"][species]["options"]] - if "kinetic" in parameters: - for species in parameters["kinetic"]: - if "options" in model.options()["kinetic"][species]: - test_list += [parameters["kinetic"][species]["options"]] - - return d_opts, test_list - - -if __name__ == "__main__": - # This is called in struphy_test in case "group" is a model name - mtype = sys.argv[1] - group = sys.argv[2] - if sys.argv[3] == "None": - Tend = None - else: - Tend = float(sys.argv[3]) - fast = sys.argv[4] == "True" - vrbose = sys.argv[5] == "True" - verification = sys.argv[6] == "True" - if sys.argv[7] == "None": - nclones = 1 - else: - nclones = int(sys.argv[7]) - show_plots = sys.argv[8] == "True" - - map_and_equil = ("Cuboid", "HomogenSlab") - wrapper_for_testing( - mtype, - map_and_equil, - fast, - vrbose, - verification, - nclones, - show_plots, - model=group, - Tend=Tend, - ) - - if not fast and not verification: - map_and_equil = ("HollowTorus", "AdhocTorus") - wrapper_for_testing( - mtype, - map_and_equil, - fast, - vrbose, - verification, - nclones, - show_plots, - model=group, - Tend=Tend, - ) - - map_and_equil = ("Tokamak", "EQDSKequilibrium") - wrapper_for_testing( - mtype, - map_and_equil, - fast, - vrbose, - verification, - nclones, - show_plots, - model=group, - Tend=Tend, - ) diff --git a/src/struphy/models/tests/test_models.py b/src/struphy/models/tests/utils_testing.py similarity index 69% rename from src/struphy/models/tests/test_models.py rename to src/struphy/models/tests/utils_testing.py index b9802abdc..ef5be133f 100644 --- a/src/struphy/models/tests/test_models.py +++ b/src/struphy/models/tests/utils_testing.py @@ -1,5 +1,6 @@ import inspect import os +import shutil from types import ModuleType import pytest @@ -43,10 +44,6 @@ print(f"\n{hybrid_models =}") -# folder for test simulations -test_folder = os.path.join(os.getcwd(), "struphy_model_tests") - - # generic function for calling model tests def call_test(model_name: str, module: ModuleType = None, verbose=True): if rank == 0: @@ -71,7 +68,9 @@ def call_test(model_name: str, module: ModuleType = None, verbose=True): assert isinstance(model, StruphyModel) # generate paramater file for testing + test_folder = os.path.join(os.getcwd(), "struphy_model_test") path = os.path.join(test_folder, f"params_{model_name}.py") + if rank == 0: model.generate_default_parameter_file(path=path, prompt=False) del model @@ -109,68 +108,5 @@ def call_test(model_name: str, module: ModuleType = None, verbose=True): path_out = os.path.join(test_folder, model_name) main.pproc(path=path_out) main.load_data(path=path_out) + shutil.rmtree(test_folder) MPI.COMM_WORLD.Barrier() - - -# specific tests -@pytest.mark.models -@pytest.mark.toy -@pytest.mark.parametrize("model", toy_models) -def test_toy( - model: str, - vrbose: bool, - nclones: int, - show_plots: bool, -): - call_test(model_name=model, module=toy, verbose=vrbose) - - -@pytest.mark.models -@pytest.mark.fluid -@pytest.mark.parametrize("model", fluid_models) -def test_fluid( - model: str, - vrbose: bool, - nclones: int, - show_plots: bool, -): - call_test(model_name=model, module=fluid, verbose=vrbose) - - -@pytest.mark.models -@pytest.mark.kinetic -@pytest.mark.parametrize("model", kinetic_models) -def test_kinetic( - model: str, - vrbose: bool, - nclones: int, - show_plots: bool, -): - call_test(model_name=model, module=kinetic, verbose=vrbose) - - -@pytest.mark.models -@pytest.mark.hybrid -@pytest.mark.parametrize("model", hybrid_models) -def test_hybrid( - model: str, - vrbose: bool, - nclones: int, - show_plots: bool, -): - call_test(model_name=model, module=hybrid, verbose=vrbose) - - -@pytest.mark.single -def test_single_model( - model_name: str, - vrbose: bool, - nclones: int, - show_plots: bool, -): - call_test(model_name=model_name, module=None, verbose=vrbose) - - -if __name__ == "__main__": - test_toy("Maxwell") - test_fluid("LinearMHD") diff --git a/src/struphy/models/tests/verification.py b/src/struphy/models/tests/verification.py deleted file mode 100644 index d28fc3d6e..000000000 --- a/src/struphy/models/tests/verification.py +++ /dev/null @@ -1,373 +0,0 @@ -import os -import pickle -from pathlib import Path - -import cunumpy as xp -import h5py -import yaml -from matplotlib import pyplot as plt -from matplotlib.ticker import FormatStrFormatter -from psydac.ddm.mpi import mpi as MPI -from scipy.special import jv, yn - -import struphy -from struphy.post_processing import pproc_struphy - - -def VlasovAmpereOneSpecies_weakLandau( - path_out: str, - rank: int, - show_plots: bool = False, -): - """Verification test for weak Landau damping. The computed damping rate is compared to the analytical rate. - - Parameters - ---------- - path_out : str - Simulation output folder (absolute path). - - rank : int - MPI rank. - - show_plots: bool - Whether to show plots.""" - - gamma = -0.1533 - - def E_exact(t): - eps = 0.001 - k = 0.5 - r = 0.3677 - omega = 1.4156 - phi = 0.5362 - return 2 * eps**2 * xp.pi / k**2 * r**2 * xp.exp(2 * gamma * t) * xp.cos(omega * t - phi) ** 2 - - # get parameters - with open(os.path.join(path_out, "parameters.yml")) as f: - params = yaml.load(f, Loader=yaml.FullLoader) - dt = params["time"]["dt"] - algo = params["time"]["split_algo"] - Nel = params["grid"]["Nel"][0] - p = params["grid"]["p"][0] - ppc = params["kinetic"]["species1"]["markers"]["ppc"] - - # get scalar data - pa_data = os.path.join(path_out, "data") - with h5py.File(os.path.join(pa_data, "data_proc0.hdf5"), "r") as f: - time = f["time"]["value"][()] - E = f["scalar"]["en_E"][()] - logE = xp.log10(E) - - # find where time derivative of E is zero - dEdt = (xp.roll(logE, -1) - xp.roll(logE, 1))[1:-1] / (2.0 * dt) - zeros = dEdt * xp.roll(dEdt, -1) < 0.0 - maxima_inds = xp.logical_and(zeros, dEdt > 0.0) - maxima = logE[1:-1][maxima_inds] - t_maxima = time[1:-1][maxima_inds] - - # linear fit - linfit = xp.polyfit(t_maxima[:5], maxima[:5], 1) - gamma_num = linfit[0] - - # plot - if show_plots and rank == 0: - plt.figure(figsize=(18, 12)) - plt.plot(time, logE, label="numerical") - plt.plot(time, xp.log10(E_exact(time)), label="exact") - plt.legend() - plt.title(f"{dt=}, {algo=}, {Nel=}, {p=}, {ppc=}") - plt.xlabel("time [m/c]") - plt.plot(t_maxima[:5], maxima[:5], "r") - plt.plot(t_maxima[:5], maxima[:5], "or", markersize=10) - plt.ylim([-10, -4]) - - plt.show() - - # assert - rel_error = xp.abs(gamma_num - gamma) / xp.abs(gamma) - assert rel_error < 0.25, f"{rank =}: Assertion for weak Landau damping failed: {gamma_num =} vs. {gamma =}." - print(f"{rank =}: Assertion for weak Landau damping passed ({rel_error =}).") - - -def LinearVlasovAmpereOneSpecies_weakLandau( - path_out: str, - rank: int, - show_plots: bool = False, -): - """Verification test for weak Landau damping. The computed damping rate is compared to the analytical rate. - - Parameters - ---------- - path_out : str - Simulation output folder (absolute path). - - rank : int - MPI rank. - - show_plots: bool - Whether to show plots.""" - - gamma = -0.1533 - - def E_exact(t): - eps = 0.001 - k = 0.5 - r = 0.3677 - omega = 1.4156 - phi = 0.5362 - return 2 * eps**2 * xp.pi / k**2 * r**2 * xp.exp(2 * gamma * t) * xp.cos(omega * t - phi) ** 2 - - # get parameters - with open(os.path.join(path_out, "parameters.yml")) as f: - params = yaml.load(f, Loader=yaml.FullLoader) - dt = params["time"]["dt"] - algo = params["time"]["split_algo"] - Nel = params["grid"]["Nel"][0] - p = params["grid"]["p"][0] - ppc = params["kinetic"]["species1"]["markers"]["ppc"] - - # get scalar data - pa_data = os.path.join(path_out, "data") - with h5py.File(os.path.join(pa_data, "data_proc0.hdf5"), "r") as f: - time = f["time"]["value"][()] - E = f["scalar"]["en_E"][()] - logE = xp.log10(E) - - # find where time derivative of E is zero - dEdt = (xp.roll(logE, -1) - xp.roll(logE, 1))[1:-1] / (2.0 * dt) - zeros = dEdt * xp.roll(dEdt, -1) < 0.0 - maxima_inds = xp.logical_and(zeros, dEdt > 0.0) - maxima = logE[1:-1][maxima_inds] - t_maxima = time[1:-1][maxima_inds] - - # linear fit - linfit = xp.polyfit(t_maxima[:5], maxima[:5], 1) - gamma_num = linfit[0] - - # plot - if show_plots and rank == 0: - plt.figure(figsize=(18, 12)) - plt.plot(time, logE, label="numerical") - plt.plot(time, xp.log10(E_exact(time)), label="exact") - plt.legend() - plt.title(f"{dt=}, {algo=}, {Nel=}, {p=}, {ppc=}") - plt.xlabel("time [m/c]") - plt.plot(t_maxima[:5], maxima[:5], "r") - plt.plot(t_maxima[:5], maxima[:5], "or", markersize=10) - plt.ylim([-10, -4]) - plt.show() - - # plt.show() - - # assert - rel_error = xp.abs(gamma_num - gamma) / xp.abs(gamma) - assert rel_error < 0.25, f"{rank =}: Assertion for weak Landau damping failed: {gamma_num =} vs. {gamma =}." - print(f"{rank =}: Assertion for weak Landau damping passed ({rel_error =}).") - - -def IsothermalEulerSPH_soundwave( - path_out: str, - rank: int, - show_plots: bool = False, -): - """Verification test for SPH discretization of isthermal Euler equations. - A standing sound wave with c_s=1 traveserses the domain once. - - Parameters - ---------- - path_out : str - Simulation output folder (absolute path). - - rank : int - MPI rank. - - show_plots: bool - Whether to show plots.""" - - path_pp = os.path.join(path_out, "post_processing/") - if rank == 0: - pproc_struphy.main(path_out) - MPI.COMM_WORLD.Barrier() - path_n_sph = os.path.join(path_pp, "kinetic_data/euler_fluid/n_sph/view_0/") - - ee1, ee2, ee3 = xp.load(os.path.join(path_n_sph, "grid_n_sph.npy")) - n_sph = xp.load(os.path.join(path_n_sph, "n_sph.npy")) - # print(f'{ee1.shape = }, {n_sph.shape = }') - - if show_plots and rank == 0: - ppb = 8 - nx = 16 - end_time = 2.5 - dt = 0.0625 - Nt = int(end_time // dt) - x = ee1 * 2.5 - - plt.figure(figsize=(10, 8)) - interval = Nt / 10 - plot_ct = 0 - for i in range(0, Nt + 1): - if i % interval == 0: - print(f"{i =}") - plot_ct += 1 - ax = plt.gca() - - if plot_ct <= 6: - style = "-" - else: - style = "." - plt.plot(x.squeeze(), n_sph[i, :, 0, 0], style, label=f"time={i * dt:4.2f}") - plt.xlim(0, 2.5) - plt.legend() - ax.set_xticks(xp.linspace(0, 2.5, nx + 1)) - ax.xaxis.set_major_formatter(FormatStrFormatter("%.2f")) - plt.grid(c="k") - plt.xlabel("x") - plt.ylabel(r"$\rho$") - - plt.title(f"standing sound wave ($c_s = 1$) for {nx =} and {ppb =}") - if plot_ct == 11: - break - - plt.show() - - # assert - error = xp.max(xp.abs(n_sph[0] - n_sph[-1])) - print(f"{rank =}: Assertion for SPH sound wave passed ({error =}).") - assert error < 1.3e-3 - - -def Maxwell_coaxial( - path_out: str, - show_plots: bool = False, -): - """Verification test for coaxial cable with Maxwell equations. Comparison w.r.t analytic solution. - - Solutions taken from TUM master thesis of Alicia Robles Pérez: - "Development of a Geometric Particle-in-Cell Method for Cylindrical Coordinate Systems", 2024 - - Parameters - ---------- - path_out : str - Simulation output folder (absolute path). - - show_plots: bool - Whether to show plots.""" - - rank = MPI.COMM_WORLD.Get_rank() - - if rank == 0: - pproc_struphy.main(path_out, physical=True) - MPI.COMM_WORLD.Barrier() - - def B_z(X, Y, Z, m, t): - """Magnetic field in z direction of coaxial cabel""" - r = (X**2 + Y**2) ** 0.5 - theta = xp.arctan2(Y, X) - return (jv(m, r) - 0.28 * yn(m, r)) * xp.cos(m * theta - t) - - def E_r(X, Y, Z, m, t): - """Electrical field in radial direction of coaxial cabel""" - r = (X**2 + Y**2) ** 0.5 - theta = xp.arctan2(Y, X) - return -m / r * (jv(m, r) - 0.28 * yn(m, r)) * xp.cos(m * theta - t) - - def E_theta(X, Y, Z, m, t): - """Electrical field in azimuthal direction of coaxial cabel""" - r = (X**2 + Y**2) ** 0.5 - theta = xp.arctan2(Y, X) - return ((m / r * jv(m, r) - jv(m + 1, r)) - 0.28 * (m / r * yn(m, r) - yn(m + 1, r))) * xp.sin(m * theta - t) - - def to_E_r(X, Y, E_x, E_y): - r = (X**2 + Y**2) ** 0.5 - theta = xp.arctan2(Y, X) - return xp.cos(theta) * E_x + xp.sin(theta) * E_y - - def to_E_theta(X, Y, E_x, E_y): - r = (X**2 + Y**2) ** 0.5 - theta = xp.arctan2(Y, X) - return -xp.sin(theta) * E_x + xp.cos(theta) * E_y - - # get parameters - with open(os.path.join(path_out, "parameters.yml")) as f: - params = yaml.load(f, Loader=yaml.FullLoader) - dt = params["time"]["dt"] - algo = params["time"]["split_algo"] - Nel = params["grid"]["Nel"][0] - modes = params["em_fields"]["perturbation"]["e_field"]["CoaxialWaveguideElectric_r"]["m"] - - pproc_path = os.path.join(path_out, "post_processing/") - em_fields_path = os.path.join(pproc_path, "fields_data/em_fields/") - t_grid = xp.load(os.path.join(pproc_path, "t_grid.npy")) - grids_phy = pickle.loads(Path(os.path.join(pproc_path, "fields_data/grids_phy.bin")).read_bytes()) - b_field_phy = pickle.loads(Path(os.path.join(em_fields_path, "b_field_phy.bin")).read_bytes()) - e_field_phy = pickle.loads(Path(os.path.join(em_fields_path, "e_field_phy.bin")).read_bytes()) - - X = grids_phy[0][:, :, 0] - Y = grids_phy[1][:, :, 0] - - # plot - if show_plots and rank == 0: - vmin = E_theta(X, Y, grids_phy[0], modes, 0).min() - vmax = E_theta(X, Y, grids_phy[0], modes, 0).max() - fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) - plot_exac = ax1.contourf( - X, - Y, - E_theta(X, Y, grids_phy[0], modes, t_grid[-1]), - cmap="plasma", - levels=100, - vmin=vmin, - vmax=vmax, - ) - ax2.contourf( - X, - Y, - to_E_theta(X, Y, e_field_phy[t_grid[-1]][0][:, :, 0], e_field_phy[t_grid[-1]][1][:, :, 0]), - cmap="plasma", - levels=100, - vmin=vmin, - vmax=vmax, - ) - fig.colorbar(plot_exac, ax=[ax1, ax2], orientation="vertical", shrink=0.9) - ax1.set_xlabel("Exact") - ax2.set_xlabel("Numerical") - fig.suptitle(f"Exact and Simulated $E_\\theta$ Field {dt=}, {algo=}, {Nel=}", fontsize=14) - plt.show() - - # assert - Ex_tend = e_field_phy[t_grid[-1]][0][:, :, 0] - Ey_tend = e_field_phy[t_grid[-1]][1][:, :, 0] - Er_exact = E_r(X, Y, grids_phy[0], modes, t_grid[-1]) - Etheta_exact = E_theta(X, Y, grids_phy[0], modes, t_grid[-1]) - Bz_tend = b_field_phy[t_grid[-1]][2][:, :, 0] - Bz_exact = B_z(X, Y, grids_phy[0], modes, t_grid[-1]) - - error_Er = xp.max(xp.abs((to_E_r(X, Y, Ex_tend, Ey_tend) - Er_exact))) - error_Etheta = xp.max(xp.abs((to_E_theta(X, Y, Ex_tend, Ey_tend) - Etheta_exact))) - error_Bz = xp.max(xp.abs((Bz_tend - Bz_exact))) - - rel_err_Er = error_Er / xp.max(xp.abs(Er_exact)) - rel_err_Etheta = error_Etheta / xp.max(xp.abs(Etheta_exact)) - rel_err_Bz = error_Bz / xp.max(xp.abs(Bz_exact)) - - print(f"{rel_err_Er =}") - print(f"{rel_err_Etheta =}") - print(f"{rel_err_Bz =}") - - assert rel_err_Bz < 0.0021, f"{rank =}: Assertion for magnetic field Maxwell failed: {rel_err_Bz =}" - print(f"{rank =}: Assertion for magnetic field Maxwell passed ({rel_err_Bz =}).") - assert rel_err_Etheta < 0.0021, ( - f"{rank =}: Assertion for electric (E_theta) field Maxwell failed: {rel_err_Etheta =}" - ) - print(f"{rank =}: Assertion for electric field Maxwell passed ({rel_err_Etheta =}).") - assert rel_err_Er < 0.0021, f"{rank =}: Assertion for electric (E_r) field Maxwell failed: {rel_err_Er =}" - print(f"{rank =}: Assertion for electric field Maxwell passed ({rel_err_Er =}).") - - -if __name__ == "__main__": - libpath = struphy.__path__[0] - # model_name = "LinearVlasovAmpereOneSpecies" - model_name = "Maxwell" - path_out = os.path.join(libpath, "io", "out", "verification", model_name, "1") - # LinearVlasovAmpereOneSpecies_weakLandau(path_out, 0, show_plots=True) - Maxwell_coaxial(path_out, 0, show_plots=True) diff --git a/src/struphy/models/tests/verification/__init__.py b/src/struphy/models/tests/verification/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/struphy/models/tests/test_verif_EulerSPH.py b/src/struphy/models/tests/verification/test_verif_EulerSPH.py similarity index 97% rename from src/struphy/models/tests/test_verif_EulerSPH.py rename to src/struphy/models/tests/verification/test_verif_EulerSPH.py index 48eb8a7a8..451a61e05 100644 --- a/src/struphy/models/tests/test_verif_EulerSPH.py +++ b/src/struphy/models/tests/verification/test_verif_EulerSPH.py @@ -1,4 +1,5 @@ import os +import shutil import cunumpy as xp import pytest @@ -21,8 +22,6 @@ ) from struphy.topology import grids -test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") - @pytest.mark.parametrize("nx", [12, 24]) @pytest.mark.parametrize("plot_pts", [11, 32]) @@ -34,6 +33,7 @@ def test_soundwave_1d(nx: int, plot_pts: int, do_plot: bool = False): from struphy.models.fluid import EulerSPH # environment options + test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") out_folders = os.path.join(test_folder, "EulerSPH") env = EnvironmentOptions(out_folders=out_folders, sim_folder="soundwave_1d") @@ -161,6 +161,8 @@ def test_soundwave_1d(nx: int, plot_pts: int, do_plot: bool = False): assert error < 6e-4 print("Assertion passed.") + shutil.rmtree(test_folder) + if __name__ == "__main__": test_soundwave_1d(nx=12, plot_pts=11, do_plot=True) diff --git a/src/struphy/models/tests/test_verif_LinearMHD.py b/src/struphy/models/tests/verification/test_verif_LinearMHD.py similarity index 97% rename from src/struphy/models/tests/test_verif_LinearMHD.py rename to src/struphy/models/tests/verification/test_verif_LinearMHD.py index 475b11aef..e6d6196b0 100644 --- a/src/struphy/models/tests/test_verif_LinearMHD.py +++ b/src/struphy/models/tests/verification/test_verif_LinearMHD.py @@ -1,4 +1,5 @@ import os +import shutil import cunumpy as xp import pytest @@ -13,10 +14,7 @@ from struphy.kinetic_background import maxwellians from struphy.topology import grids -test_folder = os.path.join(os.getcwd(), "verification_tests") - -@pytest.mark.mpi(min_size=3) @pytest.mark.parametrize("algo", ["implicit", "explicit"]) def test_slab_waves_1d(algo: str, do_plot: bool = False): # import model, set verbosity @@ -25,6 +23,7 @@ def test_slab_waves_1d(algo: str, do_plot: bool = False): verbose = True # environment options + test_folder = os.path.join(os.getcwd(), "verification_tests") out_folders = os.path.join(test_folder, "LinearMHD") env = EnvironmentOptions(out_folders=out_folders, sim_folder="slab_waves_1d") @@ -149,6 +148,8 @@ def test_slab_waves_1d(algo: str, do_plot: bool = False): assert xp.abs(coeffs[0][0] - v_slow) < 0.05 assert xp.abs(coeffs[1][0] - v_fast) < 0.19 + shutil.rmtree(test_folder) + if __name__ == "__main__": test_slab_waves_1d(algo="implicit", do_plot=True) diff --git a/src/struphy/models/tests/test_verif_Maxwell.py b/src/struphy/models/tests/verification/test_verif_Maxwell.py similarity index 97% rename from src/struphy/models/tests/test_verif_Maxwell.py rename to src/struphy/models/tests/verification/test_verif_Maxwell.py index ccea67c18..7480165d0 100644 --- a/src/struphy/models/tests/test_verif_Maxwell.py +++ b/src/struphy/models/tests/verification/test_verif_Maxwell.py @@ -1,4 +1,5 @@ import os +import shutil import cunumpy as xp import pytest @@ -16,13 +17,11 @@ from struphy.models.toy import Maxwell from struphy.topology import grids -test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") - -@pytest.mark.mpi(min_size=3) @pytest.mark.parametrize("algo", ["implicit", "explicit"]) def test_light_wave_1d(algo: str, do_plot: bool = False): # environment options + test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") out_folders = os.path.join(test_folder, "Maxwell") env = EnvironmentOptions(out_folders=out_folders, sim_folder="light_wave_1d") @@ -99,8 +98,9 @@ def test_light_wave_1d(algo: str, do_plot: bool = False): c_light_speed = 1.0 assert xp.abs(coeffs[0][0] - c_light_speed) < 0.02 + shutil.rmtree(test_folder) + -@pytest.mark.mpi(min_size=4) def test_coaxial(do_plot: bool = False): # import model, set verbosity from struphy.models.toy import Maxwell @@ -108,6 +108,7 @@ def test_coaxial(do_plot: bool = False): verbose = True # environment options + test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") out_folders = os.path.join(test_folder, "Maxwell") env = EnvironmentOptions(out_folders=out_folders, sim_folder="coaxial") @@ -269,6 +270,8 @@ def to_E_theta(X, Y, E_x, E_y): assert rel_err_Er < 0.0021, f"Assertion for electric (E_r) field Maxwell failed: {rel_err_Er =}" print(f"Assertion for electric field Maxwell passed ({rel_err_Er =}).") + shutil.rmtree(test_folder) + if __name__ == "__main__": # test_light_wave_1d(algo="explicit", do_plot=True) diff --git a/src/struphy/models/tests/test_verif_Poisson.py b/src/struphy/models/tests/verification/test_verif_Poisson.py similarity index 97% rename from src/struphy/models/tests/test_verif_Poisson.py rename to src/struphy/models/tests/verification/test_verif_Poisson.py index e82ea22c7..caddb205a 100644 --- a/src/struphy/models/tests/test_verif_Poisson.py +++ b/src/struphy/models/tests/verification/test_verif_Poisson.py @@ -1,4 +1,5 @@ import os +import shutil import cunumpy as xp from matplotlib import pyplot as plt @@ -20,11 +21,10 @@ ) from struphy.topology import grids -test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") - def test_poisson_1d(do_plot=False): # environment options + test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") out_folders = os.path.join(test_folder, "Poisson") env = EnvironmentOptions(out_folders=out_folders, sim_folder="time_source_1d") @@ -143,6 +143,8 @@ def test_poisson_1d(do_plot=False): print(f"{err =}") assert err < 0.0057 + shutil.rmtree(test_folder) + if __name__ == "__main__": # test_light_wave_1d(algo="explicit", do_plot=True) diff --git a/src/struphy/models/tests/test_verif_VlasovAmpereOneSpecies.py b/src/struphy/models/tests/verification/test_verif_VlasovAmpereOneSpecies.py similarity index 97% rename from src/struphy/models/tests/test_verif_VlasovAmpereOneSpecies.py rename to src/struphy/models/tests/verification/test_verif_VlasovAmpereOneSpecies.py index a2625ba17..504b673f4 100644 --- a/src/struphy/models/tests/test_verif_VlasovAmpereOneSpecies.py +++ b/src/struphy/models/tests/verification/test_verif_VlasovAmpereOneSpecies.py @@ -1,4 +1,5 @@ import os +import shutil import cunumpy as xp import h5py @@ -21,8 +22,6 @@ ) from struphy.topology import grids -test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") - def test_weak_Landau(do_plot: bool = False): """Verification test for weak Landau damping. @@ -32,6 +31,7 @@ def test_weak_Landau(do_plot: bool = False): from struphy.models.kinetic import VlasovAmpereOneSpecies # environment options + test_folder = os.path.join(os.getcwd(), "struphy_verification_tests") out_folders = os.path.join(test_folder, "VlasovAmpereOneSpecies") env = EnvironmentOptions(out_folders=out_folders, sim_folder="weak_Landau") @@ -162,6 +162,8 @@ def E_exact(t): assert rel_error < 0.22, f"Assertion for weak Landau damping failed: {gamma_num =} vs. {gamma =}." print(f"Assertion for weak Landau damping passed ({rel_error =}).") + shutil.rmtree(test_folder) + if __name__ == "__main__": test_weak_Landau(do_plot=True) diff --git a/src/struphy/pic/tests/test_accum_vec_H1.py b/src/struphy/pic/tests/test_accum_vec_H1.py index cb5cbb17e..4f234fbb8 100644 --- a/src/struphy/pic/tests/test_accum_vec_H1.py +++ b/src/struphy/pic/tests/test_accum_vec_H1.py @@ -89,7 +89,10 @@ def test_accum_poisson(Nel, p, spl_kind, mapping, num_clones, Np=1000): comm=None, ) else: - clone_config = CloneConfig(comm=mpi_comm, params=params, num_clones=num_clones) + if mpi_comm.Get_size() % num_clones == 0: + clone_config = CloneConfig(comm=mpi_comm, params=params, num_clones=num_clones) + else: + return derham = Derham( Nel, diff --git a/src/struphy/pic/tests/test_accumulation.py b/src/struphy/pic/tests/test_accumulation.py deleted file mode 100644 index ed3a41ff4..000000000 --- a/src/struphy/pic/tests/test_accumulation.py +++ /dev/null @@ -1,691 +0,0 @@ -import pytest - -from struphy.utils.pyccel import Pyccelkernel - - -@pytest.mark.parametrize("Nel", [[8, 9, 10]]) -@pytest.mark.parametrize("p", [[2, 3, 4]]) -@pytest.mark.parametrize( - "spl_kind", - [[False, False, True], [False, True, False], [True, False, True], [True, True, False]], -) -@pytest.mark.parametrize( - "mapping", - [ - [ - "Cuboid", - { - "l1": 1.0, - "r1": 2.0, - "l2": 10.0, - "r2": 20.0, - "l3": 100.0, - "r3": 200.0, - }, - ], - ], -) -def test_accumulation(Nel, p, spl_kind, mapping, Np=40, verbose=False): - """ - A test to compare the old accumulation routine of step1 and step3 of cc_lin_mhd_6d with the old way (files stored in - ../test_pic_legacy_files) and the new way using the Accumulator object (ghost_region_sender, particle_to_mat_kernels). - - The two accumulation matrices are computed with the same random magnetic field produced by - feec.utilities.create_equal_random_arrays and compared against each other at the bottom using - feec.utilities.compare_arrays(). - - The times for both legacy and the new way are printed if verbose == True. This comparison only makes sense if the - ..test_pic_legacy_files/ are also all compiled. - """ - from psydac.ddm.mpi import mpi as MPI - - rank = MPI.COMM_WORLD.Get_rank() - - pc_lin_mhd_6d_step_ph_full(Nel, p, spl_kind, mapping, Np, verbose) - if verbose and rank == 0: - print("\nTest for Step ph passed\n") - - -def pc_lin_mhd_6d_step_ph_full(Nel, p, spl_kind, mapping, Np, verbose=False): - from time import time - - import cunumpy as xp - from psydac.ddm.mpi import MockComm - from psydac.ddm.mpi import mpi as MPI - - from struphy.eigenvalue_solvers.spline_space import Spline_space_1d, Tensor_spline_space - from struphy.feec.mass import WeightedMassOperators - from struphy.feec.psydac_derham import Derham - from struphy.feec.utilities import compare_arrays - from struphy.geometry import domains - from struphy.pic.accumulation import accum_kernels - from struphy.pic.accumulation.particles_to_grid import Accumulator - from struphy.pic.particles import Particles6D - from struphy.pic.tests.test_pic_legacy_files.accumulation_kernels_3d import kernel_step_ph_full - from struphy.pic.utilities import BoundaryParameters, LoadingParameters, WeightsParameters - - if isinstance(MPI.COMM_WORLD, MockComm): - mpi_comm = None - rank = 0 - mpi_size = 1 - else: - mpi_comm = MPI.COMM_WORLD - # assert mpi_comm.size >= 2 - rank = mpi_comm.Get_rank() - mpi_size = mpi_comm.Get_size() - - # DOMAIN object - dom_type = mapping[0] - dom_params = mapping[1] - domain_class = getattr(domains, dom_type) - domain = domain_class(**dom_params) - - # DeRham object - derham = Derham(Nel, p, spl_kind, comm=mpi_comm) - - domain_array = derham.domain_array - nprocs = derham.domain_decomposition.nprocs - domain_decomp = (domain_array, nprocs) - - mass_ops = WeightedMassOperators(derham, domain) - - if rank == 0: - print(derham.domain_array) - - # load distributed markers first and use Send/Receive to make global marker copies for the legacy routines - loading_params = LoadingParameters(Np=Np, seed=1607, moments=(0.0, 0.0, 0.0, 1.0, 2.0, 3.0), spatial="uniform") - - particles = Particles6D( - comm_world=mpi_comm, - loading_params=loading_params, - domain=domain, - domain_decomp=domain_decomp, - ) - - particles.draw_markers() - - # set random weights on each process - particles.markers[ - ~particles.holes, - 6, - ] = xp.random.rand(particles.n_mks_loc) - - # gather all particles for legacy kernel - if mpi_comm is None: - marker_shapes = xp.array([particles.markers.shape[0]]) - else: - marker_shapes = xp.zeros(mpi_size, dtype=int) - mpi_comm.Allgather(xp.array([particles.markers.shape[0]]), marker_shapes) - print(rank, marker_shapes) - - particles_leg = xp.zeros( - (sum(marker_shapes), particles.markers.shape[1]), - dtype=float, - ) - - if rank == 0: - particles_leg[: marker_shapes[0], :] = particles.markers - - cumulative_lengths = marker_shapes[0] - - for i in range(1, mpi_size): - arr_recv = xp.zeros( - (marker_shapes[i], particles.markers.shape[1]), - dtype=float, - ) - mpi_comm.Recv(arr_recv, source=i) - particles_leg[cumulative_lengths : cumulative_lengths + marker_shapes[i]] = arr_recv - - cumulative_lengths += marker_shapes[i] - else: - mpi_comm.Send(particles.markers, dest=0) - - if mpi_comm is not None: - mpi_comm.Bcast(particles_leg, root=0) - - # sort new particles - if particles.mpi_comm: - particles.mpi_sort_markers() - - # ========================= - # ====== Legacy Part ====== - # ========================= - - spaces_FEM_1 = Spline_space_1d(Nel[0], p[0], spl_kind[0]) - spaces_FEM_2 = Spline_space_1d(Nel[1], p[1], spl_kind[1]) - spaces_FEM_3 = Spline_space_1d(Nel[2], p[2], spl_kind[2]) - - SPACES = Tensor_spline_space([spaces_FEM_1, spaces_FEM_2, spaces_FEM_3]) - - mat = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] - vec = [0, 0, 0] - - for a in range(3): - Ni = SPACES.Nbase_1form[a] - vec[a] = xp.zeros((Ni[0], Ni[1], Ni[2], 3), dtype=float) - - for b in range(3): - mat[a][b] = xp.zeros( - ( - Ni[0], - Ni[1], - Ni[2], - 2 * SPACES.p[0] + 1, - 2 * SPACES.p[1] + 1, - 2 * SPACES.p[2] + 1, - 3, - 3, - ), - dtype=float, - ) - - basis_u = 1 - - start_time = time() - kernel_step_ph_full( - particles_leg, - SPACES.T[0], - SPACES.T[1], - SPACES.T[2], - xp.array(SPACES.p), - xp.array(Nel), - xp.array(SPACES.NbaseN), - xp.array(SPACES.NbaseD), - particles_leg.shape[0], - domain.kind_map, - domain.params_numpy, - domain.T[0], - domain.T[1], - domain.T[2], - xp.array(domain.p), - xp.array( - domain.Nel, - ), - xp.array(domain.NbaseN), - domain.cx, - domain.cy, - domain.cz, - mat[0][0], - mat[0][1], - mat[0][2], - mat[1][1], - mat[1][2], - mat[2][2], - vec[0], - vec[1], - vec[2], - basis_u, - ) - - end_time = time() - tot_time = xp.round(end_time - start_time, 3) - - mat[0][0] /= Np - mat[0][1] /= Np - mat[0][2] /= Np - mat[1][1] /= Np - mat[1][2] /= Np - mat[2][2] /= Np - - vec[0] /= Np - vec[1] /= Np - vec[2] /= Np - - if rank == 0 and verbose: - print(f"Step ph Legacy took {tot_time} seconds.") - - # ========================= - # ======== New Part ======= - # ========================= - ACC = Accumulator( - particles, - "Hcurl", - Pyccelkernel(accum_kernels.pc_lin_mhd_6d_full), - mass_ops, - domain.args_domain, - add_vector=True, - symmetry="pressure", - ) - - start_time = time() - ACC( - 1.0, - ) - - end_time = time() - tot_time = xp.round(end_time - start_time, 3) - - if rank == 0 and verbose: - print(f"Step ph New took {tot_time} seconds.") - - # ========================= - # ======== Compare ======== - # ========================= - - atol = 1e-10 - - # mat_temp11 = [[mat[0][0][:,:,:,:,:,:,0,0], mat[0][1][:,:,:,:,:,:,0,0], mat[0][2][:,:,:,:,:,:,0,0]], - # [ mat[0][1][:,:,:,:,:,:,0,0].transpose(), mat[1][1][:,:,:,:,:,:,0,0], mat[1][2][:,:,:,:,:,:,0,0]], - # [ mat[0][2][:,:,:,:,:,:,0,0].transpose(), mat[1][2][:,:,:,:,:,:,0,0].transpose(), mat[2][2][:,:,:,:,:,:,0,0]]] - # mat_temp12 = [[mat[0][0][:,:,:,:,:,:,0,1], mat[0][1][:,:,:,:,:,:,0,1], mat[0][2][:,:,:,:,:,:,0,1]], - # [ mat[0][1][:,:,:,:,:,:,0,1].transpose(), mat[1][1][:,:,:,:,:,:,0,1], mat[1][2][:,:,:,:,:,:,0,1]], - # [ mat[0][2][:,:,:,:,:,:,0,1].transpose(), mat[1][2][:,:,:,:,:,:,0,1].transpose(), mat[2][2][:,:,:,:,:,:,0,1]]] - # mat_temp13 = [[mat[0][0][:,:,:,:,:,:,0,2], mat[0][1][:,:,:,:,:,:,0,2], mat[0][2][:,:,:,:,:,:,0,2]], - # [ mat[0][1][:,:,:,:,:,:,0,2].transpose(), mat[1][1][:,:,:,:,:,:,0,2], mat[1][2][:,:,:,:,:,:,0,2]], - # [ mat[0][2][:,:,:,:,:,:,0,2].transpose(), mat[1][2][:,:,:,:,:,:,0,2].transpose(), mat[2][2][:,:,:,:,:,:,0,2]]] - # mat_temp22 = [[mat[0][0][:,:,:,:,:,:,1,1], mat[0][1][:,:,:,:,:,:,1,1], mat[0][2][:,:,:,:,:,:,1,1]], - # [ mat[0][1][:,:,:,:,:,:,1,1].transpose(), mat[1][1][:,:,:,:,:,:,1,1], mat[1][2][:,:,:,:,:,:,1,1]], - # [ mat[0][2][:,:,:,:,:,:,1,1].transpose(), mat[1][2][:,:,:,:,:,:,1,1].transpose(), mat[2][2][:,:,:,:,:,:,1,1]]] - # mat_temp23 = [[mat[0][0][:,:,:,:,:,:,1,2], mat[0][1][:,:,:,:,:,:,1,2], mat[0][2][:,:,:,:,:,:,1,2]], - # [ mat[0][1][:,:,:,:,:,:,1,2].transpose(), mat[1][1][:,:,:,:,:,:,1,2], mat[1][2][:,:,:,:,:,:,1,2]], - # [ mat[0][2][:,:,:,:,:,:,1,2].transpose(), mat[1][2][:,:,:,:,:,:,1,2].transpose(), mat[2][2][:,:,:,:,:,:,1,2]]] - # mat_temp33 = [[mat[0][0][:,:,:,:,:,:,2,2], mat[0][1][:,:,:,:,:,:,2,2], mat[0][2][:,:,:,:,:,:,2,2]], - # [ mat[0][1][:,:,:,:,:,:,2,2].transpose(), mat[1][1][:,:,:,:,:,:,2,2], mat[1][2][:,:,:,:,:,:,2,2]], - # [ mat[0][2][:,:,:,:,:,:,2,2].transpose(), mat[1][2][:,:,:,:,:,:,2,2].transpose(), mat[2][2][:,:,:,:,:,:,2,2]]] - vec_temp1 = [vec[0][:, :, :, 0], vec[1][:, :, :, 0], vec[2][:, :, :, 0]] - vec_temp2 = [vec[0][:, :, :, 1], vec[1][:, :, :, 1], vec[2][:, :, :, 1]] - vec_temp3 = [vec[0][:, :, :, 2], vec[1][:, :, :, 2], vec[2][:, :, :, 2]] - - compare_arrays( - ACC.operators[0].matrix.blocks[0][0], - mat[0][0][:, :, :, :, :, :, 0, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat11_11 passed test") - compare_arrays( - ACC.operators[0].matrix.blocks[0][1], - mat[0][1][:, :, :, :, :, :, 0, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat12_11 passed test") - compare_arrays( - ACC.operators[0].matrix.blocks[0][2], - mat[0][2][:, :, :, :, :, :, 0, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat13_11 passed test") - compare_arrays( - ACC.operators[0].matrix.blocks[1][1], - mat[1][1][:, :, :, :, :, :, 0, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat22_11 passed test") - compare_arrays( - ACC.operators[0].matrix.blocks[1][2], - mat[1][2][:, :, :, :, :, :, 0, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat23_11 passed test") - compare_arrays( - ACC.operators[0].matrix.blocks[2][2], - mat[2][2][:, :, :, :, :, :, 0, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat33_11 passed test") - - compare_arrays( - ACC.operators[1].matrix.blocks[0][0], - mat[0][0][:, :, :, :, :, :, 0, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat11_12 passed test") - compare_arrays( - ACC.operators[1].matrix.blocks[0][1], - mat[0][1][:, :, :, :, :, :, 0, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat12_12 passed test") - compare_arrays( - ACC.operators[1].matrix.blocks[0][2], - mat[0][2][:, :, :, :, :, :, 0, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat13_12 passed test") - compare_arrays( - ACC.operators[1].matrix.blocks[1][1], - mat[1][1][:, :, :, :, :, :, 0, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat22_12 passed test") - compare_arrays( - ACC.operators[1].matrix.blocks[1][2], - mat[1][2][:, :, :, :, :, :, 0, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat23_12 passed test") - compare_arrays( - ACC.operators[1].matrix.blocks[2][2], - mat[2][2][:, :, :, :, :, :, 0, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat33_12 passed test") - - compare_arrays( - ACC.operators[2].matrix.blocks[0][0], - mat[0][0][:, :, :, :, :, :, 0, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat11_13 passed test") - compare_arrays( - ACC.operators[2].matrix.blocks[0][1], - mat[0][1][:, :, :, :, :, :, 0, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat12_13 passed test") - compare_arrays( - ACC.operators[2].matrix.blocks[0][2], - mat[0][2][:, :, :, :, :, :, 0, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat13_13 passed test") - compare_arrays( - ACC.operators[2].matrix.blocks[1][1], - mat[1][1][:, :, :, :, :, :, 0, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat22_13 passed test") - compare_arrays( - ACC.operators[2].matrix.blocks[1][2], - mat[1][2][:, :, :, :, :, :, 0, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat23_13 passed test") - compare_arrays( - ACC.operators[2].matrix.blocks[2][2], - mat[2][2][:, :, :, :, :, :, 0, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat33_13 passed test") - - compare_arrays( - ACC.operators[3].matrix.blocks[0][0], - mat[0][0][:, :, :, :, :, :, 1, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat11_22 passed test") - compare_arrays( - ACC.operators[3].matrix.blocks[0][1], - mat[0][1][:, :, :, :, :, :, 1, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat12_22 passed test") - compare_arrays( - ACC.operators[3].matrix.blocks[0][2], - mat[0][2][:, :, :, :, :, :, 1, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat13_22 passed test") - compare_arrays( - ACC.operators[3].matrix.blocks[1][1], - mat[1][1][:, :, :, :, :, :, 1, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat22_22 passed test") - compare_arrays( - ACC.operators[3].matrix.blocks[1][2], - mat[1][2][:, :, :, :, :, :, 1, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat23_22 passed test") - compare_arrays( - ACC.operators[3].matrix.blocks[2][2], - mat[2][2][:, :, :, :, :, :, 1, 1], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat33_22 passed test") - - compare_arrays( - ACC.operators[4].matrix.blocks[0][0], - mat[0][0][:, :, :, :, :, :, 1, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat11_23 passed test") - compare_arrays( - ACC.operators[4].matrix.blocks[0][1], - mat[0][1][:, :, :, :, :, :, 1, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat12_23 passed test") - compare_arrays( - ACC.operators[4].matrix.blocks[0][2], - mat[0][2][:, :, :, :, :, :, 1, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat13_23 passed test") - compare_arrays( - ACC.operators[4].matrix.blocks[1][1], - mat[1][1][:, :, :, :, :, :, 1, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat22_23 passed test") - compare_arrays( - ACC.operators[4].matrix.blocks[1][2], - mat[1][2][:, :, :, :, :, :, 1, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat23_23 passed test") - compare_arrays( - ACC.operators[4].matrix.blocks[2][2], - mat[2][2][:, :, :, :, :, :, 1, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat33_23 passed test") - - compare_arrays( - ACC.operators[5].matrix.blocks[0][0], - mat[0][0][:, :, :, :, :, :, 2, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat11_33 passed test") - compare_arrays( - ACC.operators[5].matrix.blocks[0][1], - mat[0][1][:, :, :, :, :, :, 2, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat12_33 passed test") - compare_arrays( - ACC.operators[5].matrix.blocks[0][2], - mat[0][2][:, :, :, :, :, :, 2, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat13_33 passed test") - compare_arrays( - ACC.operators[5].matrix.blocks[1][1], - mat[1][1][:, :, :, :, :, :, 2, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat22_33 passed test") - compare_arrays( - ACC.operators[5].matrix.blocks[1][2], - mat[1][2][:, :, :, :, :, :, 2, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat23_33 passed test") - compare_arrays( - ACC.operators[5].matrix.blocks[2][2], - mat[2][2][:, :, :, :, :, :, 2, 2], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("mat33_33 passed test") - - compare_arrays( - ACC.vectors[0].blocks[0], - vec[0][:, :, :, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("vec1_1 passed test") - compare_arrays( - ACC.vectors[0].blocks[1], - vec[1][:, :, :, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("vec2_1 passed test") - compare_arrays( - ACC.vectors[0].blocks[2], - vec[2][:, :, :, 0], - rank, - atol=atol, - verbose=verbose, - ) - if verbose: - print("vec3_1 passed test") - # compare_arrays(ACC.operators[0].matrix, mat_temp11, rank, atol=atol, verbose=verbose) - # if verbose: - # print('full block matrix_11 passed test') - # compare_arrays(ACC.operators[1].matrix, mat_temp12, rank, atol=atol, verbose=verbose) - # if verbose: - # print('full block matrix_12 passed test') - # compare_arrays(ACC.operators[2].matrix, mat_temp13, rank, atol=atol, verbose=verbose) - # if verbose: - # print('full block matrix_13 passed test') - # compare_arrays(ACC.operators[3].matrix, mat_temp22, rank, atol=atol, verbose=verbose) - # if verbose: - # print('full block matrix_22 passed test') - # compare_arrays(ACC.operators[4].matrix, mat_temp23, rank, atol=atol, verbose=verbose) - # if verbose: - # print('full block matrix_23 passed test') - # compare_arrays(ACC.operators[5].matrix, mat_temp33, rank, atol=atol, verbose=verbose) - # if verbose: - # print('full block matrix_33 passed test') - compare_arrays(ACC.vectors[0], vec_temp1, rank, atol=atol, verbose=verbose) - if verbose: - print("full block vector_1 passed test") - compare_arrays(ACC.vectors[1], vec_temp2, rank, atol=atol, verbose=verbose) - if verbose: - print("full block vector_2 passed test") - compare_arrays(ACC.vectors[2], vec_temp3, rank, atol=atol, verbose=verbose) - if verbose: - print("full block vector_3 passed test") - - -if __name__ == "__main__": - test_accumulation( - [8, 9, 10], - [2, 3, 4], - [False, False, True], - [ - "Cuboid", - { - "l1": 1.0, - "r1": 2.0, - "l2": 10.0, - "r2": 20.0, - "l3": 100.0, - "r3": 200.0, - }, - ], - )