├── .editorconfig ├── .github ├── codeql │ └── pyamrex-codeql.yml ├── update_stub.sh └── workflows │ ├── ci.yml │ ├── cleanup-cache-postpr.yml │ ├── cleanup-cache.yml │ ├── codeql.yml │ ├── dependencies │ ├── dependencies_ccache.sh │ ├── dependencies_clang14_libcpp.sh │ ├── dependencies_clang18.sh │ ├── dependencies_gcc10.sh │ ├── dependencies_gcc14.sh │ ├── dependencies_mac.sh │ ├── dependencies_nofortran.sh │ ├── dependencies_nvcc12.sh │ ├── documentation.sh │ ├── dpcpp.sh │ ├── hip.sh │ └── ubuntu_free_disk_space.sh │ ├── hip.yml │ ├── intel.yml │ ├── macos.yml │ ├── post-pr.yml │ ├── stubs.yml │ ├── ubuntu.yml │ └── windows.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── .zenodo.json ├── CMakeLists.txt ├── CODE_OF_CONDUCT.rst ├── LICENSE ├── MANIFEST.in ├── NOTICE ├── README.md ├── cmake ├── dependencies │ ├── AMReX.cmake │ └── pybind11.cmake └── pyAMReXFunctions.cmake ├── docs ├── Doxyfile ├── Makefile ├── README.md ├── requirements.txt ├── source │ ├── acknowledge_us.rst │ ├── acknowledgements.rst │ ├── coc.rst │ ├── conf.py │ ├── developers │ │ ├── debugging.rst │ │ ├── documentation.rst │ │ ├── doxygen.rst │ │ ├── implementation.rst │ │ ├── repo_organization.rst │ │ └── testing.rst │ ├── glossary.rst │ ├── index.rst │ ├── install │ │ ├── brew.svg │ │ ├── cmake.rst │ │ ├── cmake.svg │ │ ├── conda.svg │ │ ├── dependencies.rst │ │ ├── pypi.svg │ │ ├── spack.svg │ │ └── users.rst │ ├── maintenance │ │ └── release.rst │ └── usage │ │ ├── api.rst │ │ ├── compute.rst │ │ ├── examples.rst │ │ ├── workflows.rst │ │ └── zerocopy.rst └── spack.yaml ├── pyAMReXConfig.cmake.in ├── pyproject.toml ├── requirements.txt ├── requirements_mpi.txt ├── setup.py ├── spack.yaml ├── src ├── AmrCore │ ├── AmrMesh.cpp │ └── CMakeLists.txt ├── Base │ ├── AMReX.cpp │ ├── Algorithm.cpp │ ├── Arena.cpp │ ├── Array4.H │ ├── Array4.cpp │ ├── Array4_complex.cpp │ ├── Array4_complex_const.cpp │ ├── Array4_float.cpp │ ├── Array4_float_const.cpp │ ├── Array4_int.cpp │ ├── Array4_int_const.cpp │ ├── Array4_uint.cpp │ ├── Array4_uint_const.cpp │ ├── BaseFab.cpp │ ├── Box.cpp │ ├── BoxArray.cpp │ ├── CMakeLists.txt │ ├── CoordSys.cpp │ ├── Dim3.cpp │ ├── DistributionMapping.cpp │ ├── FArrayBox.cpp │ ├── FabArray.cpp │ ├── Geometry.cpp │ ├── IndexType.cpp │ ├── IntVect.cpp │ ├── MFInfo.cpp │ ├── MPMD.cpp │ ├── MultiFab.H │ ├── MultiFab.cpp │ ├── PODVector.cpp │ ├── ParallelDescriptor.cpp │ ├── ParmParse.cpp │ ├── Periodicity.cpp │ ├── PlotFileUtil.cpp │ ├── RealBox.cpp │ ├── RealVect.cpp │ ├── SmallMatrix.H │ ├── SmallMatrix.cpp │ ├── Utility.cpp │ ├── Vector.H │ ├── Vector.cpp │ ├── Version.cpp │ ├── VisMF.cpp │ └── iMultiFab.cpp ├── CMakeLists.txt ├── Particle │ ├── ArrayOfStructs.H │ ├── CMakeLists.txt │ ├── Particle.H │ ├── ParticleContainer.H │ ├── ParticleContainer.cpp │ ├── ParticleContainer_FHDeX.cpp │ ├── ParticleContainer_ImpactX.cpp │ ├── ParticleContainer_WarpX.cpp │ ├── ParticleTile.H │ └── StructOfArrays.H ├── amrex │ ├── __init__.py │ ├── extensions │ │ ├── Array4.py │ │ ├── ArrayOfStructs.py │ │ ├── Iterator.py │ │ ├── MultiFab.py │ │ ├── PODVector.py │ │ ├── ParticleContainer.py │ │ ├── SmallMatrix.py │ │ ├── StructOfArrays.py │ │ └── __init__.py │ ├── space1d │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ └── amrex_1d_pybind │ │ │ ├── ParallelDescriptor.pyi │ │ │ └── __init__.pyi │ ├── space2d │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ └── amrex_2d_pybind │ │ │ ├── ParallelDescriptor.pyi │ │ │ └── __init__.pyi │ └── space3d │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ └── amrex_3d_pybind │ │ ├── ParallelDescriptor.pyi │ │ └── __init__.pyi ├── pyAMReX.H └── pyAMReX.cpp ├── tests ├── conftest.py ├── parmparse_inputs ├── test_MPMD │ └── test_1 │ │ ├── GNUmakefile │ │ ├── Make.package │ │ ├── README.rst │ │ ├── main.cpp │ │ └── main.py ├── test_aos.py ├── test_array4.py ├── test_basefab.py ├── test_box.py ├── test_boxarray.py ├── test_coordsys.py ├── test_dim3.py ├── test_farraybox.py ├── test_geometry.py ├── test_imultifab.py ├── test_indextype.py ├── test_intvect.py ├── test_multifab.py ├── test_parmparse.py ├── test_particle.py ├── test_particleContainer.py ├── test_particleTile.py ├── test_periodicity.py ├── test_plotfiledata.py ├── test_plotfileparticledata.py ├── test_podvector.py ├── test_realbox.py ├── test_realvect.py ├── test_smallmatrix.py ├── test_soa.py └── test_utility.py └── tools └── plot_plotfile_2d.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://EditorConfig.org 2 | # 3 | # precedence of rules is bottom to top 4 | 5 | # this is the top-most EditorConfig file 6 | root = true 7 | 8 | 9 | [*] 10 | # 4 space indentation 11 | indent_style = space 12 | indent_size = 4 13 | 14 | # no end of line whitespaces 15 | trim_trailing_whitespace = true 16 | 17 | # unix-style newlines 18 | end_of_line = lf 19 | 20 | # newline ending in files 21 | insert_final_newline = true 22 | 23 | 24 | [*.md] 25 | # two end of line whitespaces are newlines without a paragraph 26 | trim_trailing_whitespace = false 27 | 28 | 29 | [Makefile] 30 | # TABs are part of its syntax 31 | indent_style = tab 32 | indent_size = unset 33 | 34 | 35 | [*.py] 36 | # isort config 37 | force_sort_within_sections = true 38 | known_first_party = amrex,impactx,picmistandard,pywarpx,warpx 39 | # same as the "black" multi-line import style 40 | multi_line_output = 3 41 | include_trailing_comma = True 42 | -------------------------------------------------------------------------------- /.github/codeql/pyamrex-codeql.yml: -------------------------------------------------------------------------------- 1 | name: "pyAMReX CodeQL config" 2 | 3 | # ignore AMReX from superbuild 4 | # note: not yet suppored, thus doing post-analysis SARIF filtering 5 | paths-ignore: 6 | - build/_deps 7 | -------------------------------------------------------------------------------- /.github/update_stub.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2021-2023 The AMReX Community 4 | # 5 | # This script updates the .pyi stub files for documentation and interactive use. 6 | # To run this script, pyAMReX needs to be installed (all dimensions) and importable. 7 | # 8 | # Authors: Axel Huebl 9 | # License: BSD-3-Clause-LBNL 10 | # 11 | set -eu -o pipefail 12 | 13 | # we are in the source directory, .github/ 14 | this_dir=$(cd $(dirname $0) && pwd) 15 | 16 | pybind11-stubgen --exit-code -o ${this_dir}/../src/ amrex.space1d 17 | pybind11-stubgen --exit-code -o ${this_dir}/../src/ amrex.space2d 18 | pybind11-stubgen --exit-code -o ${this_dir}/../src/ amrex.space3d 19 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: 👑 CI 2 | 3 | on: [push, pull_request] 4 | 5 | concurrency: 6 | group: ${{ github.ref }}-${{ github.head_ref }}-ci 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | stubs: 11 | # Pushes should only run on mainline branch "development" 12 | name: 🔄 Update Stub Files 13 | secrets: 14 | PYAMREX_PUSH_TOKEN: ${{ secrets.PYAMREX_PUSH_TOKEN }} 15 | uses: ./.github/workflows/stubs.yml 16 | 17 | ubuntu: 18 | name: 🐧 Ubuntu 19 | needs: [stubs] 20 | uses: ./.github/workflows/ubuntu.yml 21 | 22 | intel: 23 | name: 🐧 Intel 24 | needs: [ubuntu] 25 | uses: ./.github/workflows/intel.yml 26 | 27 | hip: 28 | name: 🐧 HIP 29 | needs: [ubuntu] 30 | uses: ./.github/workflows/hip.yml 31 | 32 | macos: 33 | name: 🍏 macOS 34 | needs: [ubuntu] 35 | uses: ./.github/workflows/macos.yml 36 | 37 | windows: 38 | name: 🪟 Windows 39 | needs: [ubuntu] 40 | uses: ./.github/workflows/windows.yml 41 | 42 | codeql: 43 | name: 🔎 CodeQL 44 | needs: [ubuntu] 45 | permissions: 46 | actions: read 47 | contents: read 48 | security-events: write 49 | uses: ./.github/workflows/codeql.yml 50 | -------------------------------------------------------------------------------- /.github/workflows/cleanup-cache-postpr.yml: -------------------------------------------------------------------------------- 1 | name: CleanUpCachePostPR 2 | 3 | on: 4 | workflow_run: 5 | workflows: [PostPR] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | CleanUpCcacheCachePostPR: 11 | name: Clean Up Ccache Cache Post PR 12 | runs-on: ubuntu-latest 13 | permissions: 14 | actions: write 15 | contents: read 16 | env: 17 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Clean up ccache 21 | run: | 22 | gh extension install actions/gh-actions-cache 23 | 24 | REPO=${{ github.repository }} 25 | 26 | # For debugging cat ${GITHUB_EVENT_PATH} to see the payload. 27 | 28 | pr_head_sha=${{ github.event.workflow_run.head_sha }} 29 | pr_number=$(gh pr list --state all --search $pr_head_sha --json number --jq '.[0].number') 30 | echo "Post-PR cache cleanup for PR ${pr_number}" 31 | BRANCH=refs/pull/${pr_number}/merge 32 | 33 | # Setting this to not fail the workflow while deleting cache keys. 34 | set +e 35 | 36 | keys=$(gh actions-cache list -L 100 -R $REPO -B $BRANCH | cut -f 1) 37 | # $keys might contain spaces. Thus we set IFS to \n. 38 | IFS=$'\n' 39 | for k in $keys 40 | do 41 | gh actions-cache delete "$k" -R $REPO -B $BRANCH --confirm 42 | done 43 | unset IFS 44 | -------------------------------------------------------------------------------- /.github/workflows/cleanup-cache.yml: -------------------------------------------------------------------------------- 1 | name: CleanUpCache 2 | 3 | on: 4 | workflow_run: 5 | workflows: [👑 CI] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | CleanUpCcacheCache: 11 | name: Clean Up Ccache Cache for ${{ github.event.workflow_run.name }} 12 | runs-on: ubuntu-latest 13 | permissions: 14 | actions: write 15 | contents: read 16 | env: 17 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Clean up ccache 21 | run: | 22 | gh extension install actions/gh-actions-cache 23 | 24 | REPO=${{ github.repository }} 25 | 26 | # push or pull_request or schedule or ... 27 | EVENT=${{ github.event.workflow_run.event }} 28 | 29 | # Triggering workflow run name (e.g., LinuxClang) 30 | WORKFLOW_NAME="${{ github.event.workflow_run.name }}" 31 | 32 | # For debugging, cat ${GITHUB_EVENT_PATH} to see the payload. 33 | 34 | if [[ $EVENT == "pull_request" ]]; then 35 | pr_head_sha=${{ github.event.workflow_run.head_sha }} 36 | pr_number=$(gh pr list --search $pr_head_sha --json number --jq '.[0].number') 37 | echo "Clean up cache for PR ${pr_number}" 38 | BRANCH=refs/pull/${pr_number}/merge 39 | else 40 | BRANCH=refs/heads/${{ github.event.workflow_run.head_branch }} 41 | fi 42 | 43 | # Setting this to not fail the workflow while deleting cache keys. 44 | set +e 45 | 46 | # In our cache keys, substring after `-git-` is git hash, substring 47 | # before that is a unique id for jobs (e.g., `ccache-LinuxClang-configure-2d`). 48 | # The goal is to keep the last used key of each job and delete all others. 49 | 50 | # something like ccache-LinuxClang- 51 | keyprefix="ccache-${WORKFLOW_NAME}-" 52 | 53 | cached_jobs=$(gh actions-cache list -L 100 -R $REPO -B $BRANCH --key "$keyprefix" | awk -F '-git-' '{print $1}' | sort | uniq) 54 | 55 | # cached_jobs is something like "ccache-LinuxClang-configure-1d ccache-LinuxClang-configure-2d". 56 | # It might also contain spaces. Thus we set IFS to \n. 57 | IFS=$'\n' 58 | for j in $cached_jobs 59 | do 60 | # Delete all entries except the last used one 61 | old_keys=$(gh actions-cache list -L 100 -R $REPO -B $BRANCH --key "${j}-git-" --sort last-used | cut -f 1 | tail -n +2) 62 | for k in $old_keys 63 | do 64 | gh actions-cache delete "$k" -R $REPO -B $BRANCH --confirm 65 | done 66 | done 67 | unset IFS 68 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: 🔎 CodeQL 2 | 3 | on: 4 | workflow_call: 5 | schedule: 6 | - cron: "27 3 * * 0" 7 | 8 | concurrency: 9 | group: ${{ github.ref }}-${{ github.head_ref }}-codeql 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: ubuntu-latest 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | language: [ python, cpp ] 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | 30 | - name: Clean Out 31 | run: | 32 | .github/workflows/dependencies/ubuntu_free_disk_space.sh 33 | 34 | - name: Install Packages (C++) 35 | if: ${{ matrix.language == 'cpp' }} 36 | run: | 37 | sudo apt-get update 38 | sudo apt-get install --yes cmake openmpi-bin libopenmpi-dev libhdf5-openmpi-dev 39 | 40 | python -m pip install --upgrade pip 41 | python -m pip install --upgrade wheel 42 | python -m pip install --upgrade cmake 43 | export CMAKE="$HOME/.local/bin/cmake" && echo "CMAKE=$CMAKE" >> $GITHUB_ENV 44 | python -m pip install --upgrade numpy 45 | python -m pip install --upgrade mpi4py 46 | python -m pip install --upgrade pytest 47 | python -m pip cache purge 48 | 49 | .github/workflows/dependencies/dependencies_ccache.sh 50 | sudo ln -s /usr/local/bin/ccache /usr/local/bin/g++ 51 | 52 | - name: Set Up Cache 53 | if: ${{ matrix.language == 'cpp' }} 54 | uses: actions/cache@v4 55 | with: 56 | path: ~/.cache/ccache 57 | key: ccache-${{ github.workflow }}-${{ github.job }}-git-${{ github.sha }} 58 | restore-keys: | 59 | ccache-${{ github.workflow }}-${{ github.job }}-git- 60 | 61 | - name: Configure (C++) 62 | if: ${{ matrix.language == 'cpp' }} 63 | run: | 64 | $CMAKE -S . -B build -DAMReX_SPACEDIM="1;2;3" \ 65 | -DCMAKE_CXX_COMPILER="/usr/local/bin/g++" 66 | 67 | - name: Initialize CodeQL 68 | uses: github/codeql-action/init@v3 69 | with: 70 | languages: ${{ matrix.language }} 71 | queries: +security-and-quality 72 | 73 | - name: Build (py) 74 | uses: github/codeql-action/autobuild@v3 75 | if: ${{ matrix.language == 'python' }} 76 | 77 | - name: Build (C++) 78 | if: ${{ matrix.language == 'cpp' }} 79 | run: | 80 | export CCACHE_COMPRESS=1 81 | export CCACHE_COMPRESSLEVEL=10 82 | export CCACHE_MAXSIZE=400M 83 | ccache -z 84 | 85 | $CMAKE --build build -j 4 86 | 87 | ccache -s 88 | du -hs ~/.cache/ccache 89 | 90 | # Make sure CodeQL has something to do 91 | touch src/pyAMReX.cpp 92 | export CCACHE_DISABLE=1 93 | $CMAKE --build build -j 4 94 | 95 | # claim back disk space 96 | rm -rf build 97 | 98 | - name: Perform CodeQL Analysis 99 | uses: github/codeql-action/analyze@v3 100 | with: 101 | category: "/language:${{ matrix.language }}" 102 | upload: False 103 | output: sarif-results 104 | 105 | - name: filter-sarif 106 | uses: advanced-security/filter-sarif@v1 107 | with: 108 | patterns: | 109 | -build/_deps/*/* 110 | -build/_deps/*/*/* 111 | -build/_deps/*/*/*/* 112 | -build/_deps/*/*/*/*/* 113 | -build/_deps/*/*/*/*/*/* 114 | -build/_deps/*/*/*/*/*/*/* 115 | -build/_deps/*/*/*/*/*/*/*/* 116 | input: sarif-results/${{ matrix.language }}.sarif 117 | output: sarif-results/${{ matrix.language }}.sarif 118 | 119 | - name: Upload SARIF 120 | uses: github/codeql-action/upload-sarif@v3 121 | with: 122 | sarif_file: sarif-results/${{ matrix.language }}.sarif 123 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_ccache.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ $# -eq 2 ]]; then 4 | CVER=$1 5 | else 6 | CVER=4.8 7 | fi 8 | 9 | wget https://github.com/ccache/ccache/releases/download/v${CVER}/ccache-${CVER}-linux-x86_64.tar.xz 10 | tar xvf ccache-${CVER}-linux-x86_64.tar.xz 11 | sudo mv -f ccache-${CVER}-linux-x86_64/ccache /usr/local/bin/ 12 | sudo rm -rf ccache-${CVER}-linux-x86_64 13 | sudo rm -f ccache-${CVER}-linux-x86_64.tar.xz 14 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_clang14_libcpp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | set -eu -o pipefail 9 | 10 | sudo apt-get update 11 | 12 | sudo apt-get install -y \ 13 | build-essential \ 14 | clang \ 15 | lld \ 16 | libopenmpi-dev \ 17 | openmpi-bin 18 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_clang18.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | set -eu -o pipefail 9 | 10 | sudo apt-get update 11 | 12 | sudo apt-get install -y \ 13 | build-essential \ 14 | clang-18 \ 15 | lld \ 16 | libc++-18-dev \ 17 | libopenmpi-dev \ 18 | openmpi-bin 19 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_gcc10.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020-2022 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | set -eu -o pipefail 9 | 10 | sudo apt-get update 11 | 12 | sudo apt-get install -y --no-install-recommends \ 13 | build-essential \ 14 | g++-10 \ 15 | libopenmpi-dev \ 16 | openmpi-bin 17 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_gcc14.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | set -eu -o pipefail 9 | 10 | sudo apt-get update 11 | 12 | sudo apt-get install -y --no-install-recommends\ 13 | build-essential \ 14 | g++-14 \ 15 | libopenmpi-dev \ 16 | openmpi-bin 17 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_mac.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | set -eu -o pipefail 9 | 10 | brew update 11 | brew install gfortran || true 12 | brew install libomp || true 13 | brew install open-mpi || true 14 | brew install ccache || true 15 | 16 | python3 -m venv venv 17 | source venv/bin/activate 18 | python3 -m pip install -U pip setuptools[core] wheel pytest 19 | python3 -m pip install -U cmake 20 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_nofortran.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 Axel Huebl 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | 7 | # search recursive inside a folder if a file contains tabs 8 | # 9 | # @result 0 if no files are found, else 1 10 | # 11 | 12 | set -eu -o pipefail 13 | 14 | sudo apt-get update 15 | 16 | sudo apt-get install -y --no-install-recommends\ 17 | build-essential \ 18 | g++ \ 19 | libopenmpi-dev \ 20 | openmpi-bin 21 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dependencies_nvcc12.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 Axel Huebl 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | 7 | # search recursive inside a folder if a file contains tabs 8 | # 9 | # @result 0 if no files are found, else 1 10 | # 11 | 12 | set -eu -o pipefail 13 | 14 | sudo apt-get -qqq update 15 | sudo apt-get install -y \ 16 | build-essential \ 17 | ca-certificates \ 18 | cmake \ 19 | g++-10 \ 20 | gfortran-10 \ 21 | gnupg \ 22 | libopenmpi-dev \ 23 | openmpi-bin \ 24 | pkg-config \ 25 | wget 26 | 27 | sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub 28 | echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64 /" \ 29 | | sudo tee /etc/apt/sources.list.d/cuda.list 30 | sudo apt-get update 31 | sudo apt-get install -y \ 32 | cuda-command-line-tools-12-2 \ 33 | cuda-compiler-12-2 \ 34 | cuda-cupti-dev-12-2 \ 35 | cuda-minimal-build-12-2 \ 36 | cuda-nvml-dev-12-2 \ 37 | cuda-nvtx-12-2 \ 38 | libcurand-dev-12-2 \ 39 | libcusparse-dev-12-2 40 | sudo ln -s cuda-12.2 /usr/local/cuda 41 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/documentation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Andrew Myers 7 | 8 | set -eu -o pipefail 9 | 10 | sudo apt-get update 11 | 12 | sudo apt-get install -y --no-install-recommends\ 13 | build-essential \ 14 | pandoc \ 15 | doxygen \ 16 | texlive \ 17 | texlive-latex-extra \ 18 | texlive-lang-cjk \ 19 | latexmk 20 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/dpcpp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020-2021 The WarpX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | set -eu -o pipefail 9 | 10 | # `man apt.conf`: 11 | # Number of retries to perform. If this is non-zero APT will retry 12 | # failed files the given number of times. 13 | echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries 14 | 15 | # Ref.: https://github.com/rscohn2/oneapi-ci 16 | # intel-basekit intel-hpckit are too large in size 17 | 18 | # download the key to system keyring 19 | wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \ 20 | | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null 21 | 22 | # add signed entry to apt sources and configure the APT client to use Intel repository: 23 | echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list 24 | 25 | sudo apt-get update 26 | 27 | df -h 28 | # Install and reduce disk space 29 | # https://github.com/ECP-WarpX/WarpX/pull/1566#issuecomment-790934878 30 | 31 | # try apt install up to five times, to avoid connection splits 32 | status=1 33 | for itry in {1..5} 34 | do 35 | sudo apt-get install -y --no-install-recommends \ 36 | build-essential \ 37 | ccache \ 38 | cmake \ 39 | intel-oneapi-compiler-dpcpp-cpp intel-oneapi-mkl-devel \ 40 | g++ gfortran \ 41 | libopenmpi-dev \ 42 | openmpi-bin \ 43 | && { sudo apt-get clean; status=0; break; } \ 44 | || { sleep 10; } 45 | done 46 | if [[ ${status} -ne 0 ]]; then exit 1; fi 47 | 48 | du -sh /opt/intel/oneapi/ 49 | du -sh /opt/intel/oneapi/*/* 50 | echo "+++ REDUCING oneAPI install size +++" 51 | sudo rm -rf /opt/intel/oneapi/mkl/latest/lib/intel64/*.a \ 52 | /opt/intel/oneapi/compiler/latest/linux/lib/oclfpga \ 53 | /opt/intel/oneapi/compiler/latest/linux/lib/emu \ 54 | /opt/intel/oneapi/compiler/latest/linux/bin/intel64 \ 55 | /opt/intel/oneapi/compiler/latest/linux/bin/lld \ 56 | /opt/intel/oneapi/compiler/latest/linux/bin/lld-link \ 57 | /opt/intel/oneapi/compiler/latest/linux/bin/wasm-ld 58 | du -sh /opt/intel/oneapi/ 59 | du -sh /opt/intel/oneapi/*/* 60 | df -h 61 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/hip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2020 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | # Authors: Axel Huebl 7 | 8 | # search recursive inside a folder if a file contains tabs 9 | # 10 | # @result 0 if no files are found, else 1 11 | # 12 | 13 | set -eu -o pipefail 14 | 15 | # `man apt.conf`: 16 | # Number of retries to perform. If this is non-zero APT will retry 17 | # failed files the given number of times. 18 | echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries 19 | 20 | # Ref.: https://rocm.docs.amd.com/projects/install-on-linux/en/latest/how-to/native-install/ubuntu.html 21 | 22 | # Make the directory if it doesn't exist yet. 23 | # This location is recommended by the distribution maintainers. 24 | sudo mkdir --parents --mode=0755 /etc/apt/keyrings 25 | 26 | # Download the key, convert the signing-key to a full 27 | # keyring required by apt and store in the keyring directory 28 | wget https://repo.radeon.com/rocm/rocm.gpg.key -O - | \ 29 | gpg --dearmor | sudo tee /etc/apt/keyrings/rocm.gpg > /dev/null 30 | 31 | curl -O https://repo.radeon.com/rocm/rocm.gpg.key 32 | sudo apt-key add rocm.gpg.key 33 | 34 | source /etc/os-release # set UBUNTU_CODENAME: focal or jammy or ... 35 | 36 | VERSION=${1-6.3.2} 37 | 38 | echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/${VERSION} ${UBUNTU_CODENAME} main" \ 39 | | sudo tee /etc/apt/sources.list.d/rocm.list 40 | echo 'export PATH=/opt/rocm/llvm/bin:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin:$PATH' \ 41 | | sudo tee -a /etc/profile.d/rocm.sh 42 | 43 | # we should not need to export HIP_PATH=/opt/rocm/hip with those installs 44 | 45 | sudo apt-get clean 46 | sudo apt-get update 47 | 48 | # Ref.: https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html#installing-development-packages-for-cross-compilation 49 | # meta-package: rocm-dkms 50 | # OpenCL: rocm-opencl 51 | # other: rocm-dev rocm-utils 52 | sudo apt-get install -y --no-install-recommends \ 53 | build-essential \ 54 | gfortran \ 55 | libnuma-dev \ 56 | libopenmpi-dev \ 57 | openmpi-bin \ 58 | rocm-dev${VERSION} \ 59 | roctracer-dev${VERSION} \ 60 | rocprofiler-dev${VERSION} \ 61 | rocrand-dev${VERSION} \ 62 | rocfft-dev${VERSION} \ 63 | rocprim-dev${VERSION} \ 64 | rocsparse-dev${VERSION} 65 | 66 | # hiprand-dev is a new package that does not exist in old versions 67 | sudo apt-get install -y --no-install-recommends hiprand-dev${VERSION} || true 68 | 69 | # activate 70 | # 71 | source /etc/profile.d/rocm.sh 72 | hipcc --version 73 | hipconfig --full 74 | which clang 75 | which clang++ 76 | which flang 77 | -------------------------------------------------------------------------------- /.github/workflows/dependencies/ubuntu_free_disk_space.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2023 The AMReX Community 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | 7 | # Don't want to use the following line because apt-get remove may fail if 8 | # the package specfied does not exist. 9 | # set -eu -o pipefail 10 | 11 | # Large packages 12 | dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 100 13 | 14 | echo 'Removing some packages we do not need' 15 | 16 | df -h 17 | 18 | apt list --installed 19 | 20 | sudo apt-get remove -y '^apache.*' 21 | sudo apt-get remove -y '^aspnetcore.*' 22 | sudo apt-get remove -y '^azure.*' 23 | sudo apt-get remove -y '^dotnet.*' 24 | sudo apt-get remove -y '^firebird.*' 25 | sudo apt-get remove -y '^firefox.*' 26 | sudo apt-get remove -y '^google.*' 27 | sudo apt-get remove -y '^hhvm.*' 28 | sudo apt-get remove -y '^microsoft.*' 29 | sudo apt-get remove -y '^mongodb.*' 30 | sudo apt-get remove -y '^mono-.*' 31 | sudo apt-get remove -y '^monodoc-.*' 32 | sudo apt-get remove -y '^mysql.*' 33 | sudo apt-get remove -y '^php.*' 34 | sudo apt-get remove -y '^powershell.*' 35 | sudo apt-get remove -y '^snapd.*' 36 | sudo apt-get remove -y '^temurin.*' 37 | 38 | sudo apt-get autoremove -y 39 | 40 | df -h 41 | -------------------------------------------------------------------------------- /.github/workflows/hip.yml: -------------------------------------------------------------------------------- 1 | name: 🐧 HIP 2 | 3 | on: [workflow_call] 4 | 5 | concurrency: 6 | group: ${{ github.ref }}-${{ github.head_ref }}-hip 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | build_hip: 11 | name: ROCm HIP 6.3.2 12 | runs-on: ubuntu-24.04 13 | env: 14 | CXXFLAGS: "-Werror -Wno-deprecated-declarations -Wno-error=pass-failed" 15 | CMAKE_GENERATOR: Ninja 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: install dependencies 19 | shell: bash 20 | run: | 21 | .github/workflows/dependencies/hip.sh 6.3.2 22 | .github/workflows/dependencies/dependencies_ccache.sh 23 | - name: Set Up Cache 24 | uses: actions/cache@v4 25 | with: 26 | path: ~/.cache/ccache 27 | key: ccache-${{ github.workflow }}-${{ github.job }}-git-${{ github.sha }} 28 | restore-keys: | 29 | ccache-${{ github.workflow }}-${{ github.job }}-git- 30 | - name: build pyAMReX 31 | shell: bash 32 | run: | 33 | export CCACHE_COMPRESS=1 34 | export CCACHE_COMPRESSLEVEL=10 35 | export CCACHE_MAXSIZE=300M 36 | ccache -z 37 | 38 | source /etc/profile.d/rocm.sh 39 | hipcc --version 40 | which clang 41 | which clang++ 42 | export CXX=$(which clang++) 43 | export CC=$(which clang) 44 | 45 | python3 -m pip install -U pip 46 | python3 -m pip install -U build packaging setuptools[core] wheel 47 | python3 -m pip install -U cmake 48 | 49 | cmake -S . -B build \ 50 | -DCMAKE_VERBOSE_MAKEFILE=ON \ 51 | -DpyAMReX_IPO=OFF \ 52 | -DAMReX_GPU_BACKEND=HIP \ 53 | -DAMReX_AMD_ARCH=gfx90a \ 54 | -DAMReX_SPACEDIM="1;2;3" 55 | cmake --build build --target pip_install -j 4 56 | 57 | ccache -s 58 | du -hs ~/.cache/ccache 59 | -------------------------------------------------------------------------------- /.github/workflows/intel.yml: -------------------------------------------------------------------------------- 1 | name: 🐧 Intel 2 | 3 | on: [workflow_call] 4 | 5 | concurrency: 6 | group: ${{ github.ref }}-${{ github.head_ref }}-intel 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | tests-oneapi-sycl: 11 | name: oneAPI SYCL 3D 12 | runs-on: ubuntu-22.04 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Dependencies 16 | run: | 17 | .github/workflows/dependencies/dpcpp.sh 18 | .github/workflows/dependencies/dependencies_ccache.sh 19 | - name: Set Up Cache 20 | uses: actions/cache@v4 21 | with: 22 | path: ~/.cache/ccache 23 | key: ccache-${{ github.workflow }}-${{ github.job }}-git-${{ github.sha }} 24 | restore-keys: | 25 | ccache-${{ github.workflow }}-${{ github.job }}-git- 26 | - name: Build & Install 27 | # mkl/rng/device/detail/mrg32k3a_impl.hpp has a number of sign-compare error 28 | # mkl/rng/device/detail/mrg32k3a_impl.hpp has missing braces in array-array initalization 29 | env: {CXXFLAGS: "-fno-operator-names -Werror -Wall -Wextra -Wpedantic -Wnull-dereference -Wfloat-conversion -Wshadow -Woverloaded-virtual -Wextra-semi -Wunreachable-code -Wnon-virtual-dtor -Wno-unused-variable -Wno-shadow"} 30 | run: | 31 | set +e 32 | source /opt/intel/oneapi/setvars.sh 33 | set -e 34 | 35 | export CCACHE_COMPRESS=1 36 | export CCACHE_COMPRESSLEVEL=10 37 | export CCACHE_MAXSIZE=200M 38 | export CCACHE_DEPEND=1 39 | ccache -z 40 | 41 | export CC=$(which icx) 42 | export CXX=$(which icpx) 43 | python3 -m pip install -U pip setuptools[core] wheel 44 | python3 -m pip install -U cmake 45 | python3 -m pip install -U pytest mpi4py 46 | 47 | cmake -S . -B build \ 48 | -DCMAKE_BUILD_TYPE=Release \ 49 | -DCMAKE_VERBOSE_MAKEFILE=ON \ 50 | -DBUILD_SHARED_LIBS=ON \ 51 | -DAMReX_GPU_BACKEND=SYCL \ 52 | -DAMReX_MPI=ON \ 53 | -DAMReX_SPACEDIM="3" 54 | cmake --build build --target pip_install -j 4 55 | 56 | ccache -s 57 | du -hs ~/.cache/ccache 58 | 59 | tests-icpx: 60 | name: ICPX 61 | runs-on: ubuntu-22.04 62 | steps: 63 | - uses: actions/checkout@v4 64 | - name: Dependencies 65 | run: | 66 | .github/workflows/dependencies/dpcpp.sh 67 | .github/workflows/dependencies/dependencies_ccache.sh 68 | - name: Set Up Cache 69 | uses: actions/cache@v4 70 | with: 71 | path: ~/.cache/ccache 72 | key: ccache-${{ github.workflow }}-${{ github.job }}-git-${{ github.sha }} 73 | restore-keys: | 74 | ccache-${{ github.workflow }}-${{ github.job }}-git- 75 | - name: Build & Install 76 | # /usr/include/c++/12/bits/stl_tempbuf.h has deprecated-declarations in 'get_temporary_buffer>' 77 | env: {CXXFLAGS: "-fno-operator-names -Werror -Wall -Wextra -Wpedantic -Wnull-dereference -Wfloat-conversion -Wshadow -Woverloaded-virtual -Wextra-semi -Wunreachable-code -Wnon-virtual-dtor -Wno-deprecated-declarations"} 78 | run: | 79 | set +e 80 | source /opt/intel/oneapi/setvars.sh 81 | set -e 82 | 83 | export CCACHE_COMPRESS=1 84 | export CCACHE_COMPRESSLEVEL=10 85 | export CCACHE_MAXSIZE=200M 86 | ccache -z 87 | 88 | export CC=$(which icx) 89 | export CXX=$(which icpx) 90 | python3 -m pip install -U pip setuptools[core] wheel 91 | python3 -m pip install -U cmake 92 | python3 -m pip install -U pytest mpi4py 93 | 94 | cmake -S . -B build \ 95 | -DCMAKE_BUILD_TYPE=Release \ 96 | -DCMAKE_VERBOSE_MAKEFILE=ON \ 97 | -DAMReX_MPI=ON \ 98 | -DAMReX_SPACEDIM="1;2;3" 99 | cmake --build build --target pip_install -j 4 100 | 101 | ccache -s 102 | du -hs ~/.cache/ccache 103 | 104 | - name: Run tests 105 | run: | 106 | set +e 107 | source /opt/intel/oneapi/setvars.sh 108 | set -e 109 | cd build 110 | ctest --output-on-failure 111 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: 🍏 macOS 2 | 3 | on: [workflow_call] 4 | 5 | concurrency: 6 | group: ${{ github.ref }}-${{ github.head_ref }}-macos 7 | cancel-in-progress: true 8 | 9 | env: 10 | CXXFLAGS: "-Werror -Wshadow -Woverloaded-virtual -Wextra-semi -Wunreachable-code -fno-operator-names -Wno-pass-failed" 11 | 12 | jobs: 13 | appleclang: 14 | name: AppleClang@14.0 w/o MPI 15 | runs-on: macos-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Dependencies 19 | run: .github/workflows/dependencies/dependencies_mac.sh 20 | - name: Set Up Cache 21 | uses: actions/cache@v4 22 | with: 23 | path: ~/Library/Caches/ccache 24 | key: ccache-${{ github.workflow }}-${{ github.job }}-git-${{ github.sha }} 25 | restore-keys: | 26 | ccache-${{ github.workflow }}-${{ github.job }}-git- 27 | - name: Build & Install 28 | run: | 29 | source venv/bin/activate 30 | 31 | export CCACHE_COMPRESS=1 32 | export CCACHE_COMPRESSLEVEL=10 33 | export CCACHE_MAXSIZE=600M 34 | export CCACHE_SLOPPINESS=time_macros 35 | ccache -z 36 | 37 | export CMAKE_BUILD_PARALLEL_LEVEL=3 38 | 39 | python3 -m pip install -v . 40 | python3 -c "import amrex.space1d as amr; print(amr.__version__)" 41 | python3 -c "import amrex.space2d as amr; print(amr.__version__)" 42 | python3 -c "import amrex.space3d as amr; print(amr.__version__)" 43 | 44 | ccache -s 45 | du -hs ~/Library/Caches/ccache 46 | 47 | - name: Unit tests 48 | run: | 49 | source venv/bin/activate 50 | 51 | python3 -m pytest tests/ 52 | 53 | 54 | # TODO: AppleClang w/ MPI 55 | -------------------------------------------------------------------------------- /.github/workflows/post-pr.yml: -------------------------------------------------------------------------------- 1 | name: PostPR 2 | on: 3 | pull_request: 4 | types: 5 | - closed 6 | 7 | # This workflow does not have the permission to clean up cache for PRs 8 | # originated from a fork. The purpose here is to trigger a workflow_run 9 | # cleanup-cache-postpr.yml that has the right permission. 10 | 11 | jobs: 12 | noop: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: No OP 16 | run: echo "This workflow is going to trigger CleanUpCachePostPR." 17 | -------------------------------------------------------------------------------- /.github/workflows/stubs.yml: -------------------------------------------------------------------------------- 1 | name: 🔄 Update Stub Files 2 | 3 | # This workflow updates the .pyi stub files for documentation and interactive use. 4 | 5 | on: 6 | workflow_call: 7 | secrets: 8 | PYAMREX_PUSH_TOKEN: 9 | required: true 10 | 11 | concurrency: 12 | group: ${{ github.ref }}-${{ github.head_ref }}-stubs 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | # Build and install libamrex as AMReX CMake project 17 | stubs: 18 | name: Stubs 19 | runs-on: ubuntu-22.04 20 | env: 21 | CC: gcc 22 | CXX: g++ 23 | CXXFLAGS: "-O1" 24 | OMP_NUM_THREAD: 4 25 | 26 | steps: 27 | - uses: actions/checkout@v4 28 | if: github.event_name != 'push' || github.repository != 'AMReX-Codes/pyamrex' || github.ref != 'refs/heads/development' 29 | 30 | - uses: actions/checkout@v4 31 | if: github.event_name == 'push' && github.repository == 'AMReX-Codes/pyamrex' && github.ref == 'refs/heads/development' 32 | with: 33 | token: ${{ secrets.PYAMREX_PUSH_TOKEN }} 34 | 35 | - name: Pull Remote Changes 36 | if: github.event_name == 'push' && github.repository == 'AMReX-Codes/pyamrex' && github.ref == 'refs/heads/development' 37 | run: git pull 38 | 39 | - uses: actions/setup-python@v4 40 | name: Install Python 41 | with: 42 | python-version: '3.9' 43 | 44 | - name: Dependencies 45 | run: | 46 | .github/workflows/dependencies/dependencies_gcc10.sh 47 | .github/workflows/dependencies/dependencies_ccache.sh 48 | 49 | - name: Set Up Cache 50 | uses: actions/cache@v4 51 | with: 52 | path: ~/.cache/ccache 53 | key: ccache-${{ github.workflow }}-${{ github.job }}-git-${{ github.sha }} 54 | restore-keys: | 55 | ccache-${{ github.workflow }}-${{ github.job }}-git- 56 | 57 | - name: Build & Install 58 | run: | 59 | export CCACHE_COMPRESS=1 60 | export CCACHE_COMPRESSLEVEL=10 61 | export CCACHE_MAXSIZE=200M 62 | ccache -z 63 | 64 | python3 -m pip install -U pip setuptools[core] wheel 65 | python3 -m pip install -U pip mpi4py pytest pybind11-stubgen pre-commit 66 | cmake -S . -B build -DAMReX_SPACEDIM="1;2;3" -DpyAMReX_IPO=OFF 67 | cmake --build build -j 4 --target pip_install 68 | 69 | ccache -s 70 | du -hs ~/.cache/ccache 71 | 72 | - name: Update Stubs 73 | run: | 74 | .github/update_stub.sh 75 | 76 | - name: Run pre-commit cleanup 77 | run: | 78 | git add . 79 | pre-commit run -a || true 80 | git add . 81 | 82 | - name: Update Install 83 | run: | 84 | cmake --build build -j 4 --target pip_install 85 | 86 | - name: Unit tests 87 | run: | 88 | mpiexec -np 1 python3 -m pytest tests/ 89 | 90 | - uses: stefanzweifel/git-auto-commit-action@v5 91 | name: Commit Updated Stub Files 92 | if: github.event_name == 'push' && github.repository == 'AMReX-Codes/pyamrex' && github.ref == 'refs/heads/development' 93 | with: 94 | commit_message: Update Stub Files 95 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: 🪟 Windows 2 | 3 | on: [workflow_call] 4 | 5 | concurrency: 6 | group: ${{ github.ref }}-${{ github.head_ref }}-windows 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | msvc: 11 | name: MSVC w/o MPI Static Release 12 | runs-on: windows-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-python@v4 16 | with: 17 | python-version: '3.x' 18 | - name: Build & Install 19 | env: 20 | # Work-around for windows-latest GH runner issue, see 21 | # https://github.com/actions/runner-images/issues/10004 22 | CXXFLAGS: "/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR" 23 | run: | 24 | set "CMAKE_BUILD_PARALLEL_LEVEL=4" 25 | 26 | python3 -m pip install -U pip 27 | python3 -m pip install -U pandas pytest 28 | python3 -m pip install -v . 29 | if(!$?) { Exit $LASTEXITCODE } 30 | 31 | python3 -c "import amrex.space1d as amr; print(amr.__version__)" 32 | python3 -c "import amrex.space2d as amr; print(amr.__version__)" 33 | python3 -c "import amrex.space3d as amr; print(amr.__version__)" 34 | - name: Unit tests 35 | shell: cmd 36 | run: python3 -m pytest tests 37 | 38 | clang: 39 | name: Clang w/o MPI Shared Debug 40 | runs-on: windows-latest 41 | steps: 42 | - uses: actions/checkout@v4 43 | - uses: actions/setup-python@v4 44 | with: 45 | python-version: '3.x' 46 | - uses: seanmiddleditch/gha-setup-ninja@master 47 | - name: Build 48 | run: | 49 | python3 -m pip install -U pip setuptools[core] wheel pytest 50 | python3 -m pip install -U cmake 51 | python3 -m pip install -r requirements.txt 52 | 53 | cmake -S . -B build ` 54 | -T "ClangCl" ` 55 | -DCMAKE_VERBOSE_MAKEFILE=ON ` 56 | -DBUILD_SHARED_LIBS=ON ` 57 | -DAMReX_MPI=OFF ` 58 | -DAMReX_SPACEDIM="1;2;3" 59 | if(!$?) { Exit $LASTEXITCODE } 60 | 61 | cmake --build build --config Debug -j 4 62 | if(!$?) { Exit $LASTEXITCODE } 63 | - name: Unit tests 64 | run: | 65 | ctest --test-dir build -C Debug --output-on-failure 66 | - name: Install 67 | run: | 68 | cmake --build build --config Debug --target install 69 | if(!$?) { Exit $LASTEXITCODE } 70 | cmake --build build --config Debug --target pip_install 71 | if(!$?) { Exit $LASTEXITCODE } 72 | - name: Unit tests as Installed 73 | run: | 74 | $env:PATH += ';C:/Program Files (x86)/pyAMReX/bin/' 75 | rm -r -fo build 76 | python3 -m pytest tests 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ####### 2 | # C++ # 3 | ####### 4 | # Prerequisites 5 | *.d 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | *.smod 25 | 26 | # Compiled Static libraries 27 | *.lai 28 | *.la 29 | *.a 30 | *.lib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | 37 | ## Compiler debris 38 | **/tmp_build_dir 39 | 40 | ## Crash debris 41 | **/Backtrace.* 42 | 43 | ## All compiled programs 44 | **/*.gnu.*.ex 45 | **/*.o 46 | **/*.ex 47 | 48 | ## MacOS creates dynamic linker symbol files 49 | *.dSym 50 | 51 | ## MacOS custom folder attributes 52 | .DS_Store 53 | 54 | 55 | ########## 56 | # Python # 57 | ########## 58 | *.pyc 59 | __pycache__ 60 | _tmppythonbuild/ 61 | amrex.egg-info/ 62 | 63 | ####### 64 | # IDE # 65 | ####### 66 | /*.cbp 67 | /*.layout 68 | .idea/ 69 | .kdev?/ 70 | *.kdev? 71 | /nbproject/ 72 | .vimrc 73 | cmake-build-*/ 74 | spack-build* 75 | build/ 76 | 77 | # File-based project format: 78 | *.iws 79 | 80 | ###### 81 | # OS # 82 | ###### 83 | .DS_Store 84 | .AppleDouble 85 | .LSOverride 86 | 87 | # Icon must end with two \r 88 | Icon 89 | 90 | # Thumbnails 91 | ._* 92 | 93 | # temporary files / backup 94 | *~ 95 | 96 | # Files that might appear in the root of a volume 97 | .DocumentRevisions-V100 98 | .fseventsd 99 | .Spotlight-V100 100 | .TemporaryItems 101 | .Trashes 102 | .VolumeIcon.icns 103 | 104 | # Directories potentially created on remote AFP share 105 | .AppleDB 106 | .AppleDesktop 107 | Network Trash Folder 108 | Temporary Items 109 | .apdisk 110 | 111 | ######### 112 | # CMake # 113 | ######### 114 | CMakeCache.txt 115 | CMakeFiles 116 | CMakeScripts 117 | cmake_install.cmake 118 | install_manifest.txt 119 | compile_commands.json 120 | CTestTestfile.cmake 121 | 122 | #################### 123 | # Package Managers # 124 | #################### 125 | # anonymous Spack environments 126 | # https://spack.readthedocs.io/en/latest/environments.html#anonymous-environments 127 | .spack-env/ 128 | spack.lock 129 | 130 | ######### 131 | # Tools # 132 | ######### 133 | .stfolder 134 | 135 | ########### 136 | # Doxygen # 137 | ########### 138 | docs/doxyhtml/ 139 | docs/doxyxml/ 140 | docs/html/ 141 | docs/xml/ 142 | docs/doxygen_sqlite3.db 143 | docs/amrex-doxygen-web.tag.xml 144 | docs/pyamrex-doxygen-web.tag.xml 145 | 146 | #################### 147 | # Sphinx & Breathe # 148 | #################### 149 | docs/build/ 150 | docs/source/_static/doxyhtml/ 151 | docs/source/_static/ 152 | docs/doxyhtml/ 153 | docs/doxyxml/ 154 | 155 | ### Output #### 156 | ## Plot files 157 | **/plt* 158 | ## Checkpoints 159 | **/chk* 160 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # To use: 2 | # 3 | # pre-commit run -a 4 | # 5 | # Or: 6 | # 7 | # pre-commit install # (runs every time you commit in git) 8 | # 9 | # To update this file: 10 | # 11 | # pre-commit autoupdate 12 | # 13 | # See https://pre-commit.com for more information 14 | 15 | # Do not check/format anything from third parties 16 | #exclude: '^share/pyAMReX/thirdParty' 17 | 18 | # See https://pre-commit.com/hooks.html for more hooks 19 | repos: 20 | - repo: https://github.com/pre-commit/pre-commit-hooks 21 | rev: v5.0.0 22 | hooks: 23 | - id: trailing-whitespace 24 | args: [--markdown-linebreak-ext=md] 25 | - id: end-of-file-fixer 26 | - id: mixed-line-ending 27 | - id: check-json 28 | - id: check-toml 29 | - id: check-yaml 30 | args: [--allow-multiple-documents] 31 | - id: check-added-large-files 32 | args: ['--maxkb=40'] 33 | exclude: ^.*\.pyi$ 34 | - id: requirements-txt-fixer 35 | # - id: fix-encoding-pragma 36 | # exclude: ^noxfile.py$ 37 | 38 | # documentation files: .rst 39 | - repo: https://github.com/pre-commit/pygrep-hooks 40 | rev: v1.10.0 41 | hooks: 42 | - id: rst-backticks 43 | - id: rst-directive-colons 44 | - id: rst-inline-touching-normal 45 | 46 | #- repo: https://github.com/asottile/pyupgrade 47 | # rev: v2.29.0 48 | # hooks: 49 | # - id: pyupgrade 50 | 51 | # Changes tabs to spaces 52 | - repo: https://github.com/Lucas-C/pre-commit-hooks 53 | rev: v1.5.5 54 | hooks: 55 | - id: remove-tabs 56 | # exclude: 'Make.WarpX|Make.package|Makefile|GNUmake' 57 | 58 | # CMake formatting 59 | #- repo: https://github.com/cheshirekow/cmake-format-precommit 60 | # rev: v0.6.13 61 | # hooks: 62 | # - id: cmake-format 63 | # additional_dependencies: [pyyaml] 64 | # types: [file] 65 | # files: (\.cmake|CMakeLists.txt)(.in)?$ 66 | 67 | # C++ formatting 68 | # clang-format v13 69 | #- repo: https://github.com/pre-commit/mirrors-clang-format 70 | # rev: v14.0.5 71 | # hooks: 72 | # - id: clang-format 73 | 74 | # Python: Ruff linter & formatter 75 | # https://docs.astral.sh/ruff/ 76 | - repo: https://github.com/astral-sh/ruff-pre-commit 77 | rev: v0.11.8 78 | hooks: 79 | # Run the linter 80 | - id: ruff 81 | args: [--fix, --exit-non-zero-on-fix] 82 | # Run the formatter 83 | - id: ruff-format 84 | 85 | # Jupyter Notebooks: clean up all cell outputs 86 | - repo: https://github.com/roy-ht/pre-commit-jupyter 87 | rev: v1.2.1 88 | hooks: 89 | - id: jupyter-notebook-cleanup 90 | args: 91 | - --pin-patterns 92 | - "[pin];[donotremove]" 93 | # - --remove-kernel-metadata 94 | 95 | # Checks the manifest for missing files (native support) 96 | - repo: https://github.com/mgedmin/check-manifest 97 | rev: "0.50" 98 | hooks: 99 | - id: check-manifest 100 | # This is a slow hook, so only run this if --hook-stage manual is passed 101 | stages: [manual] 102 | additional_dependencies: [cmake, ninja] 103 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | version: 2 5 | 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: "3.11" 10 | 11 | sphinx: 12 | configuration: docs/source/conf.py 13 | 14 | python: 15 | install: 16 | - requirements: docs/requirements.txt 17 | 18 | formats: 19 | - htmlzip 20 | # - pdf 21 | # - epub 22 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "creators": [ 3 | { 4 | "affiliation": "Lawrence Berkeley National Laboratory", 5 | "name": "Huebl, Axel", 6 | "orcid": "0000-0003-1943-7141" 7 | }, 8 | { 9 | "affiliation": "National Renewable Energy Laboratory", 10 | "name": "Ananthan, Shreyas", 11 | "orcid": "0000-0003-3966-4595" 12 | }, 13 | { 14 | "affiliation": "Lawrence Livermore National Laboratory", 15 | "name": "Grote, David", 16 | "orcid": "0000-0002-4057-8582" 17 | }, 18 | { 19 | "affiliation": "Lawrence Berkeley National Laboratory", 20 | "name": "Sandberg, Ryan T.", 21 | "orcid": "0000-0001-7680-8733" 22 | }, 23 | { 24 | "affiliation": "Lawrence Berkeley National Laboratory", 25 | "name": "Zoni, Edoardo", 26 | "orcid": "0000-0001-5662-4646" 27 | }, 28 | { 29 | "affiliation": "Lawrence Berkeley National Laboratory", 30 | "name": "Jambunathan, Revathi", 31 | "orcid": "0000-0001-9432-2091" 32 | }, 33 | { 34 | "affiliation": "Lawrence Berkeley National Laboratory", 35 | "name": "Lehe, Remi", 36 | "orcid": "0000-0002-3656-9659" 37 | }, 38 | { 39 | "affiliation": "Lawrence Berkeley National Laboratory", 40 | "name": "Myers, Andrew", 41 | "orcid": "0000-0001-8427-8330" 42 | }, 43 | { 44 | "affiliation": "Lawrence Berkeley National Laboratory", 45 | "name": "Zhang, Weiqun", 46 | "orcid": "0000-0001-8092-1974" 47 | }, 48 | { 49 | "affiliation": "Lawrence Berkeley National Laboratory", 50 | "name": "Siddani, Bhargav Sriram", 51 | "orcid": "0000-0002-3535-4429" 52 | }, 53 | { 54 | "affiliation": "Michigan State University", 55 | "name": "Wibking, Benjamin", 56 | "orcid": "0000-0003-3175-2291" 57 | } 58 | ], 59 | "license": { 60 | "id": "BSD-3-Clause-LBNL" 61 | }, 62 | "notes": "This work was supported by the Laboratory Directed Research and Development Program of Lawrence Berkeley National Laboratory under U.S. Department of Energy Contract No. DE-AC02-05CH11231.", 63 | "language": "eng", 64 | "keywords": [ 65 | "research", 66 | "simulation", 67 | "modeling", 68 | "data science", 69 | "amr", 70 | "ml" 71 | ], 72 | "access_right": "open" 73 | } 74 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.rst: -------------------------------------------------------------------------------- 1 | .. _coc: 2 | 3 | Code of Conduct 4 | =============== 5 | 6 | Our Pledge 7 | ---------- 8 | 9 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 10 | 11 | Our Standards 12 | ------------- 13 | 14 | Examples of behavior that contributes to creating a positive environment include: 15 | 16 | - Using welcoming and inclusive language 17 | - Being respectful of differing viewpoints and experiences 18 | - Gracefully accepting constructive criticism 19 | - Focusing on what is best for the community 20 | - Showing empathy towards other community members 21 | 22 | Examples of unacceptable behavior by participants include: 23 | 24 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 25 | - Trolling, insulting/derogatory comments, and personal or political attacks 26 | - Public or private harassment 27 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 28 | - Other conduct which could reasonably be considered inappropriate in a professional setting 29 | 30 | Our Responsibilities 31 | -------------------- 32 | 33 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 34 | 35 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 36 | 37 | Scope 38 | ----- 39 | 40 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. 41 | Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. 42 | Representation of a project may be further defined and clarified by project maintainers. 43 | 44 | Enforcement 45 | ----------- 46 | 47 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 48 | reported by contacting the project team at amrex@lbl.gov. 49 | All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. 50 | The project team is obligated to maintain confidentiality with regard to the reporter of an incident. 51 | Further details of specific enforcement policies may be posted separately. 52 | 53 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 54 | 55 | Attribution 56 | ----------- 57 | 58 | This Code of Conduct is adapted from the `Contributor Covenant `_, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 59 | 60 | For answers to common questions about this code of conduct, see 61 | https://www.contributor-covenant.org/faq 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | pyAMReX Copyright (c) 2023, The Regents of the University of California, 2 | through Lawrence Berkeley National Laboratory, National Renewable Energy 3 | Laboratory Alliance for Sustainable Energy, LLC and Lawrence Livermore 4 | National Security, LLC (subject to receipt of any required approvals from the U.S. 5 | Dept. of Energy). All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | (1) Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | (3) Neither the name of the University of California, Lawrence Berkeley 18 | National Laboratory, U.S. Dept. of Energy, National Renewable Energy 19 | Laboratory Alliance for Sustainable Energy, LLC, Lawrence Livermore 20 | National Security, LLC, nor the names of its contributors may be used to 21 | endorse or promote products derived from this software without specific prior 22 | written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 25 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 26 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 29 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 35 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 36 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | You are under no obligation whatsoever to provide any bug fixes, patches, 39 | or upgrades to the features, functionality or performance of the source 40 | code ("Enhancements") to anyone; however, if you choose to make your 41 | Enhancements available either publicly, or directly to Lawrence Berkeley 42 | National Laboratory, without imposing a separate written license agreement 43 | for such Enhancements, then you hereby grant the following license: a 44 | non-exclusive, royalty-free perpetual license to install, use, modify, 45 | prepare derivative works, incorporate into other computer software, 46 | distribute, and sublicense such enhancements or derivative works thereof, 47 | in binary and source code form. 48 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE 2 | include pyproject.toml 3 | include requirements.txt requirements_mpi.txt 4 | global-include CMakeLists.txt *.cmake *.in 5 | recursive-include cmake * 6 | recursive-include src * 7 | recursive-include tests * 8 | 9 | # avoid accidentially copying compiled Python files 10 | global-exclude */__pycache__/* 11 | global-exclude *.pyc 12 | 13 | # see .gitignore 14 | prune cmake-build* 15 | prune .spack-env* 16 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This Software was developed under funding from the U.S. Department 2 | of Energy and the U.S. Government consequently retains certain rights. As 3 | such, the U.S. Government has been granted for itself and others acting on 4 | its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the 5 | Software to reproduce, distribute copies to the public, prepare derivative 6 | works, and perform publicly and display publicly, and to permit other to do 7 | so. 8 | 9 | Reference herein to any specific commercial product, process, or service 10 | by trade name, trademark, manufacturer, or otherwise does not necessarily 11 | constitute or imply its endorsement, recommendation, or favoring by the 12 | United States Government, The Regents of the University of California, or 13 | Lawrence Berkeley National Laboratory. 14 | 15 | The views and opinions of authors expressed herein do not necessarily 16 | state or reflect those of the United States Government, 17 | The Regents of the University of California, or 18 | Lawrence Berkeley National Laboratory, and shall not be used for advertising 19 | or product endorsement purposes. 20 | -------------------------------------------------------------------------------- /cmake/dependencies/AMReX.cmake: -------------------------------------------------------------------------------- 1 | macro(find_amrex) 2 | if(TARGET AMReX::amrex) 3 | message(STATUS "AMReX::amrex target already imported") 4 | elseif(pyAMReX_amrex_src) 5 | message(STATUS "Compiling local AMReX ...") 6 | message(STATUS "AMReX source path: ${pyAMReX_amrex_src}") 7 | if(NOT IS_DIRECTORY ${pyAMReX_amrex_src}) 8 | message(FATAL_ERROR "Specified directory pyAMReX_amrex_src='${pyAMReX_amrex_src}' does not exist!") 9 | endif() 10 | elseif(pyAMReX_amrex_internal) 11 | message(STATUS "Downloading AMReX ...") 12 | message(STATUS "AMReX repository: ${pyAMReX_amrex_repo} (${pyAMReX_amrex_branch})") 13 | include(FetchContent) 14 | endif() 15 | if(TARGET AMReX::amrex) 16 | # nothing to do, target already exists in the superbuild 17 | elseif(pyAMReX_amrex_internal OR pyAMReX_amrex_src) 18 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 19 | 20 | # see https://amrex-codes.github.io/amrex/docs_html/BuildingAMReX.html#customization-options 21 | if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") 22 | set(AMReX_ASSERTIONS ON CACHE BOOL "") 23 | # note: floating-point exceptions can slow down debug runs a lot 24 | set(AMReX_FPE ON CACHE BOOL "") 25 | else() 26 | set(AMReX_ASSERTIONS OFF CACHE BOOL "") 27 | set(AMReX_FPE OFF CACHE BOOL "") 28 | endif() 29 | 30 | set(AMReX_EB ON CACHE INTERNAL "") 31 | set(AMReX_PIC ON CACHE INTERNAL "") 32 | set(AMReX_ENABLE_TESTS OFF CACHE INTERNAL "") 33 | set(AMReX_FORTRAN OFF CACHE INTERNAL "") 34 | set(AMReX_FORTRAN_INTERFACES OFF CACHE INTERNAL "") 35 | set(AMReX_BUILD_TUTORIALS OFF CACHE INTERNAL "") 36 | set(AMReX_PARTICLES ON CACHE INTERNAL "") # default: OFF 37 | 38 | if(pyAMReX_amrex_src) 39 | list(APPEND CMAKE_MODULE_PATH "${pyAMReX_amrex_src}/Tools/CMake") 40 | if(AMReX_GPU_BACKEND STREQUAL CUDA) 41 | enable_language(CUDA) 42 | endif() 43 | add_subdirectory(${pyAMReX_amrex_src} _deps/localamrex-build/) 44 | else() 45 | if(AMReX_GPU_BACKEND STREQUAL CUDA) 46 | enable_language(CUDA) 47 | endif() 48 | FetchContent_Declare(fetchedamrex 49 | GIT_REPOSITORY ${pyAMReX_amrex_repo} 50 | GIT_TAG ${pyAMReX_amrex_branch} 51 | BUILD_IN_SOURCE 0 52 | ) 53 | FetchContent_MakeAvailable(fetchedamrex) 54 | list(APPEND CMAKE_MODULE_PATH "${fetchedamrex_SOURCE_DIR}/Tools/CMake") 55 | 56 | # advanced fetch options 57 | mark_as_advanced(FETCHCONTENT_BASE_DIR) 58 | mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) 59 | mark_as_advanced(FETCHCONTENT_QUIET) 60 | mark_as_advanced(FETCHCONTENT_SOURCE_DIR_FETCHEDAMREX) 61 | mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) 62 | mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_FETCHEDAMREX) 63 | endif() 64 | 65 | message(STATUS "AMReX: Using version '${AMREX_PKG_VERSION}' (${AMREX_GIT_VERSION})") 66 | elseif(NOT pyAMReX_amrex_internal) 67 | message(STATUS "Searching for pre-installed AMReX ...") 68 | # https://amrex-codes.github.io/amrex/docs_html/BuildingAMReX.html#importing-amrex-into-your-cmake-project 69 | # not strictly required yet to compile pyAMReX: EB 70 | find_package(AMReX 25.06 CONFIG REQUIRED COMPONENTS PARTICLES PIC) 71 | message(STATUS "AMReX: Found version '${AMReX_VERSION}'") 72 | 73 | if(AMReX_GPU_BACKEND STREQUAL CUDA) 74 | enable_language(CUDA) 75 | endif() 76 | endif() 77 | endmacro() 78 | 79 | # local source-tree 80 | set(pyAMReX_amrex_src "" 81 | CACHE PATH 82 | "Local path to AMReX source directory (preferred if set)") 83 | 84 | # Git fetcher 85 | option(pyAMReX_amrex_internal "Download & build AMReX" ON) 86 | set(pyAMReX_amrex_repo "https://github.com/AMReX-Codes/amrex.git" 87 | CACHE STRING 88 | "Repository URI to pull and build AMReX from if(pyAMReX_amrex_internal)") 89 | set(pyAMReX_amrex_branch "25.06" 90 | CACHE STRING 91 | "Repository branch for pyAMReX_amrex_repo if(pyAMReX_amrex_internal)") 92 | 93 | find_amrex() 94 | -------------------------------------------------------------------------------- /cmake/dependencies/pybind11.cmake: -------------------------------------------------------------------------------- 1 | function(find_pybind11) 2 | if(TARGET pybind11::module) 3 | message(STATUS "pybind11::module target already imported") 4 | elseif(pyAMReX_pybind11_src) 5 | message(STATUS "Compiling local pybind11 ...") 6 | message(STATUS "pybind11 source path: ${pyAMReX_pybind11_src}") 7 | if(NOT IS_DIRECTORY ${pyAMReX_pybind11_src}) 8 | message(FATAL_ERROR "Specified directory pyAMReX_pybind11_src='${pyAMReX_pybind11_src}' does not exist!") 9 | endif() 10 | elseif(pyAMReX_pybind11_internal) 11 | message(STATUS "Downloading pybind11 ...") 12 | message(STATUS "pybind11 repository: ${pyAMReX_pybind11_repo} (${pyAMReX_pybind11_branch})") 13 | include(FetchContent) 14 | endif() 15 | 16 | # rely on our find_package(Python ...) call 17 | # https://pybind11.readthedocs.io/en/stable/compiling.html#modules-with-cmake 18 | set(PYBIND11_FINDPYTHON ON) 19 | 20 | if(TARGET pybind11::module) 21 | # nothing to do, target already exists in the superbuild 22 | elseif(pyAMReX_pybind11_internal OR pyAMReX_pybind11_src) 23 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 24 | 25 | if(pyAMReX_pybind11_src) 26 | add_subdirectory(${pyAMReX_pybind11_src} _deps/localpybind11-build/) 27 | else() 28 | FetchContent_Declare(fetchedpybind11 29 | GIT_REPOSITORY ${pyAMReX_pybind11_repo} 30 | GIT_TAG ${pyAMReX_pybind11_branch} 31 | BUILD_IN_SOURCE 0 32 | ) 33 | FetchContent_MakeAvailable(fetchedpybind11) 34 | 35 | # advanced fetch options 36 | mark_as_advanced(FETCHCONTENT_BASE_DIR) 37 | mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) 38 | mark_as_advanced(FETCHCONTENT_QUIET) 39 | mark_as_advanced(FETCHCONTENT_SOURCE_DIR_FETCHEDpybind11) 40 | mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) 41 | mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_FETCHEDpybind11) 42 | endif() 43 | elseif(NOT pyAMReX_pybind11_internal) 44 | find_package(pybind11 2.13.0 CONFIG REQUIRED) 45 | message(STATUS "pybind11: Found version '${pybind11_VERSION}'") 46 | endif() 47 | endfunction() 48 | 49 | # local source-tree 50 | set(pyAMReX_pybind11_src "" 51 | CACHE PATH 52 | "Local path to pybind11 source directory (preferred if set)") 53 | 54 | # Git fetcher 55 | option(pyAMReX_pybind11_internal "Download & build pybind11" ON) 56 | set(pyAMReX_pybind11_repo "https://github.com/pybind/pybind11.git" 57 | CACHE STRING 58 | "Repository URI to pull and build pybind11 from if(pyAMReX_pybind11_internal)") 59 | set(pyAMReX_pybind11_branch "v2.13.6" 60 | CACHE STRING 61 | "Repository branch for pyAMReX_pybind11_repo if(pyAMReX_pybind11_internal)") 62 | 63 | find_pybind11() 64 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = pyAMReX 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | clean: 16 | rm -rf 17 | @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" amrex-doxygen-web.tag.xml pyamrex-doxygen-web.tag.xml 18 | 19 | .PHONY: help Makefile 20 | 21 | # Catch-all target: route all unknown targets to Sphinx using the new 22 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 23 | %: Makefile 24 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 25 | 26 | Doxygen-build: 27 | doxygen Doxyfile 28 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This explains how to generate the documentation for pyAMReX, and contribute to it. 4 | 5 | ## Generating the documentation 6 | 7 | ### Installing the requirements 8 | 9 | Install the Python requirements for compiling the documentation: 10 | ``` 11 | cd docs 12 | python3 -m pip install -r requirements.txt 13 | ``` 14 | 15 | ### Compiling the documentation 16 | 17 | `cd` into this directory and type 18 | ``` 19 | make html 20 | ``` 21 | You can then open the file `build/html/index.html` with a standard web browser (e.g. Firefox), in order to visualize the results on your local computer. 22 | 23 | ### Cleaning the documentation 24 | 25 | In order to remove all of the generated files, use: 26 | ``` 27 | make clean 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2023 Axel Huebl, Maxence Thevenet 2 | # 3 | # This file is part of WarpX. 4 | # 5 | # License: BSD-3-Clause-LBNL 6 | 7 | breathe 8 | docutils>=0.17.1 9 | numpy # in public APIs 10 | pybind11-stubgen # type hints in pyi files 11 | pygments 12 | recommonmark 13 | # Attention: we need to track the resolution of 14 | # https://github.com/breathe-doc/breathe/issues/943 15 | sphinx>=5.3 16 | sphinx-copybutton 17 | sphinx-design 18 | sphinx_rtd_theme>=1.1.1 19 | # reference system 20 | #sphinxcontrib-bibtex 21 | #sphinxcontrib-napoleon 22 | sphinxcontrib-googleanalytics 23 | -------------------------------------------------------------------------------- /docs/source/acknowledge_us.rst: -------------------------------------------------------------------------------- 1 | Acknowledge pyAMReX 2 | =================== 3 | 4 | Please acknowledge the role that pyAMReX played in your research. 5 | 6 | 7 | In Publications 8 | *************** 9 | 10 | If a project using pyAMReX leads to a scientific publication, please consider citing it. 11 | This helps to keep in touch with the community, shows its use and supports the project. 12 | 13 | Huebl A, Ananthan S, Grote D P, Sandberg R T, Zoni E, Jambunathan R, Lehe R, Myers A, Zhang W. 14 | **pyAMReX: GPU-Enabled, Zero-Copy AMReX Python Bindings including AI/ML**. 15 | *software*, 2023. `DOI:10.5281/zenodo.8408733 `__ 16 | `github.com/AMReX-Codes/pyamrex `__ 17 | 18 | .. code-block:: bibtex 19 | 20 | @misc{pyAMReX, 21 | author = {Huebl, Axel and 22 | Ananthan, Shreyas and 23 | Grote, David P. and 24 | Sandberg, Ryan T. and 25 | Zoni, Edoardo and 26 | Jambunathan, Revathi and 27 | Lehe, Remi and 28 | Myers, Andrew and 29 | Zhang, Weiqun}, 30 | title = {{pyAMReX: GPU-Enabled, Zero-Copy AMReX Python Bindings including AI/ML}}, 31 | year = 2023, 32 | publisher = {Zenodo}, 33 | doi = {10.5281/zenodo.8408733}, 34 | url = {https://github.com/AMReX-Codes/pyamrex}, 35 | howpublished = {https://github.com/AMReX-Codes/pyamrex} 36 | } 37 | 38 | You can also add an acknowledgement, e.g., 39 | 40 | .. code-block:: latex 41 | 42 | This research used the open-source code pyAMReX~\cite{pyAMReX}. 43 | We acknowledge all AMReX contributors. 44 | 45 | 46 | Further pyAMReX References 47 | ************************** 48 | 49 | - Myers A, Zhang W, Almgren A, Antoun T, Bell J, Huebl A, Sinn A. 50 | **AMReX and pyAMReX: Looking Beyond ECP**. 51 | *submitted for review*, 2024. 52 | `arXiv:2403.12179 `__ 53 | 54 | Works using pyAMReX: 55 | 56 | - Sandberg R T, Lehe R, Mitchell C E, Garten M, Myers A, Qiang J, Vay J-L and Huebl A. 57 | **Synthesizing Particle-in-Cell Simulations Through Learning and GPU Computing for Hybrid Particle Accelerator Beamlines**. 58 | Proc. of Platform for Advanced Scientific Computing (PASC'24), *in print*, 2024. 59 | `arXiv:2402.17248 `__ 60 | 61 | - Huebl A et al., 62 | **Exascale and ML Models for Accelerator Simulations**. 63 | presentation at the 6th European Advanced Accelerator Concepts workshop (EAAC23), Isola d'Elba, Italy, Sep 17 – 23, 2023. 64 | `DOI:10.5281/zenodo.8362549 `__ 65 | 66 | - Sandberg R T, Lehe R, Mitchell C E, Garten M, Qiang J, Vay J-L and Huebl A. 67 | **Hybrid Beamline Element ML-Training for Surrogates in the ImpactX Beam-Dynamics Code**. 68 | 14th International Particle Accelerator Conference (IPAC'23), WEPA101, *in print*, 2023. 69 | `preprint `__, 70 | `DOI:10.18429/JACoW-IPAC-23-WEPA101 `__ 71 | 72 | - Huebl A, Lehe R, Mitchell C E, Qiang J, Ryne R D, Sandberg R T, Vay JL. 73 | **Next Generation Computational Tools for the Modeling and Design of Particle Accelerators at Exascale**. 74 | 2022 North American Particle Accelerator Conference (NAPAC'22), TUYE2, pp. 302-306, 2022. 75 | `arXiv:2208.02382 `__, 76 | `DOI:10.18429/JACoW-NAPAC2022-TUYE2 `__ 77 | -------------------------------------------------------------------------------- /docs/source/acknowledgements.rst: -------------------------------------------------------------------------------- 1 | Funding and Acknowledgements 2 | ============================ 3 | 4 | This work was supported by the Laboratory Directed Research and Development Program of Lawrence Berkeley National Laboratory under U.S. Department of Energy Contract No. DE-AC02-05CH11231. 5 | -------------------------------------------------------------------------------- /docs/source/coc.rst: -------------------------------------------------------------------------------- 1 | ../../CODE_OF_CONDUCT.rst -------------------------------------------------------------------------------- /docs/source/developers/debugging.rst: -------------------------------------------------------------------------------- 1 | .. _debugging-pyamrex: 2 | 3 | Debugging the code 4 | ================== 5 | 6 | Sometimes, the code does not give you the result that you are expecting. 7 | This can be due to a variety of reasons, from misunderstandings or changes, system specific quirks, or bugs. 8 | You might also want to debug your code that uses pyAMReX or pyAMReX itself, as you implement new features during development. 9 | 10 | This section gives a step-by-step guidance on how to systematically check what might be going wrong. 11 | 12 | Debugging Workflow 13 | ------------------ 14 | 15 | Debugging Python processes works the same way as debugging regular applications. 16 | For investigating bugs on the Python extension side (e.g., in AMReX/pyAMReX/your application), the Python intepreter itself does *not* need to be compiled in debug mode. 17 | 18 | Try the following steps to debug a simulation: 19 | 20 | #. Check the output text file, often called ``output.txt``: are there warnings or errors present? 21 | #. On an HPC system, look for the job output and error files, usually called ``.e...`` and ``.o...``. 22 | Read long messages from the top and follow potential guidance. 23 | #. If your simulation already created output data files: 24 | Check if they look reasonable before the problem occurred; are the initial conditions of the simulation as you expected? 25 | Do you spot numerical artifacts or instabilities that could point to missing resolution or unexpected/incompatible numerical parameters? 26 | #. Did the job output files indicate a crash? Check the ``Backtrace.`` files for the location of the code that triggered the crash. 27 | Backtraces are read from bottom (high-level) to top (most specific line that crashed). 28 | #. In case of a crash, Backtraces can be more detailed if you :ref:`re-compile ` with debug flags: for example, try compiling with ``-DCMAKE_BUILD_TYPE=RelWithDebInfo`` (some slowdown) or even ``-DCMAKE_BUILD_TYPE=Debug`` (this will make the simulation way slower) and rerun. 29 | #. If debug builds are too costly, try instead compiling with ``-DAMReX_ASSERTIONS=ON`` to activate more checks and rerun. 30 | #. If the problem looks like a memory violation, this could be from an invalid field or particle index access. 31 | Try compiling with ``-DAMReX_BOUND_CHECK=ON`` (this will make the simulation very slow), and rerun. 32 | #. If the problem looks like a random memory might be used, try initializing memory with signaling Not-a-Number (NaN) values through the runtime option ``fab.init_snan = 1``. 33 | Further useful runtime options are ``amrex.fpe_trap_invalid``, ``amrex.fpe_trap_zero`` and ``amrex.fpe_trap_overflow`` (see details in the AMReX link below). 34 | #. On Nvidia GPUs, if you suspect the problem might be a race condition due to a missing host / device synchronization, set the environment variable ``export CUDA_LAUNCH_BLOCKING=1`` and rerun. 35 | #. Consider simplifying your input options and re-adding more options after having found a working baseline. 36 | 37 | Fore more information, see also the `AMReX Debugging Manual `__. 38 | 39 | Last but not least: the community of AMReX developers and users can help if you get stuck. 40 | Collect your above findings, describe where and what you are running and how you installed the code, describe the issue you are seeing with details and input files used and what you already tried. 41 | Can you reproduce the problem with a smaller setup (less parallelism and/or less resolution)? 42 | Report these details in a :ref:`pyAMReX or AMReX GitHub issue `. 43 | 44 | Debuggers 45 | --------- 46 | 47 | See the `AMReX debugger section `__ on additional runtime parameters to 48 | 49 | * disable backtraces 50 | * rethrow exceptions 51 | * avoid AMReX-level signal handling 52 | 53 | You will need to set those runtime options to work directly with debuggers. 54 | -------------------------------------------------------------------------------- /docs/source/developers/documentation.rst: -------------------------------------------------------------------------------- 1 | .. _developers-docs: 2 | 3 | Documentation 4 | ============= 5 | 6 | Python API documentation 7 | ------------------------ 8 | 9 | .. note:: 10 | 11 | TODO: document the Python doc style we use. 12 | 13 | We add `docstrings for pybind11-created types and functions `__. 14 | In order to retrieve those, one usually would need to build pyAMReX and have it available (installed) as a working Python import. 15 | This build step can be complicated for building documentation and it does not work well with autocompletion in IPython. 16 | 17 | Thus, on every merge to the mainline ``development`` branch, we build pyAMReX and create "stub" (interface/facade) files that carry all type information and doc strings. 18 | We do this by building pyAMReX and running the script ``.github/update_stub.sh``, which uses `pybind11-stubgen `__ to extract these information. 19 | A GitHub action then commits the updated stub files (``.pyi``) to the repository. 20 | 21 | When we build our Sphinx documentation, we copy the ``.pyi`` files and generate documentation of classes and functions via `autodoc `__. 22 | The logic for this resides in ``docs/source/conf.py``. 23 | We also provide a zip archive online under https://pyamrex.readthedocs.io/en/latest/_static/pyapi/amrex.zip that can be downloaded by dependent projects that build their Sphinx docs. 24 | 25 | 26 | Doxygen documentation (C++) 27 | --------------------------- 28 | 29 | pyAMReX uses a `Doxygen documentation `__ for its C++ part. 30 | Whenever you create a new class, please document it where it is declared (typically in the header file): 31 | 32 | .. code-block:: cpp 33 | 34 | /** A brief title 35 | * 36 | * few-line description explaining the purpose of my_class. 37 | * 38 | * If you are kind enough, also quickly explain how things in my_class work. 39 | * (typically a few more lines) 40 | */ 41 | class my_class 42 | { ... } 43 | 44 | Doxygen reads this docstring, so please be accurate with the syntax! See `Doxygen manual `__ for more information. Similarly, please document functions when you declare them (typically in a header file) like: 45 | 46 | .. code-block:: cpp 47 | 48 | /** A brief title 49 | * 50 | * few-line description explaining the purpose of my_function. 51 | * 52 | * \param[in,out] my_int a pointer to an integer variable on which 53 | * my_function will operate. 54 | * \return what is the meaning and value range of the returned value 55 | */ 56 | int my_class::my_function(int* my_int); 57 | 58 | An online version of this documentation is :ref:`linked here `. 59 | 60 | 61 | Breathe documentation 62 | --------------------- 63 | 64 | Your Doxygen documentation is not only useful for people looking into the C++ side of the pyAMReX code, it is also part of the `pyAMReX online documentation `_ based on `Sphinx `_! 65 | This is done using the Python module `Breathe `_, that allows you to read Doxygen C++ documentation dorectly in the source and include it in your Sphinx documentation, by calling Breathe functions. 66 | For instance, the following line will get the Doxygen documentation for ``make_Vector`` in ``src/Base/Vector.H`` and include it to the html page generated by Sphinx: 67 | 68 | .. doxygenfunction:: make_Vector 69 | 70 | .. .. doxygenfunction:: make_ParticleContainer_and_Iterators 71 | 72 | 73 | Building the documentation 74 | -------------------------- 75 | 76 | To build the documentation on your local computer, you will need to install Doxygen as well as the Python module ``breathe``. 77 | First, change into ``docs/`` and install the Python requirements: 78 | 79 | .. code-block:: sh 80 | 81 | cd docs/ 82 | pip install -r requirements.txt 83 | 84 | You will also need Doxygen (macOS: ``brew install doxygen``; Ubuntu: ``sudo apt install doxygen``). 85 | 86 | Then, to compile the documentation, use 87 | 88 | .. code-block:: sh 89 | 90 | make html 91 | # This will first compile the Doxygen documentation (execute doxygen) 92 | # and then build html pages from rst files using sphinx and breathe. 93 | 94 | Open the created ``build/html/index.html`` file with your favorite browser. 95 | Rebuild and refresh as needed. 96 | -------------------------------------------------------------------------------- /docs/source/developers/doxygen.rst: -------------------------------------------------------------------------------- 1 | .. _development-doxygen: 2 | 3 | C++ Objects & Functions 4 | ======================= 5 | 6 | We generate the documentation of C++ objects and functions *from our C++ source code* by adding :ref:`Doxygen strings `. 7 | 8 | Our Doxygen C++ API documentation in classic formatting `is located here <../_static/doxyhtml/index.html>`_. 9 | -------------------------------------------------------------------------------- /docs/source/developers/implementation.rst: -------------------------------------------------------------------------------- 1 | .. _developers-implementation: 2 | 3 | Implementation Details 4 | ====================== 5 | 6 | For now, please see these presentations: 7 | 8 | - `A. Huebl et al., NREL virtual seminar, December 2022 `__ 9 | - `A. Huebl et al., "Exascale and ML Models for Accelerator Simulations", 6th European Advanced Accelerator Concepts workshop (EAAC23), Isola d'Elba, Italy, Sep 17 – 23, 2023 DOI:10.5281/zenodo.8362549 `__ 10 | 11 | 12 | Zero-Copy Data APIs 13 | ------------------- 14 | 15 | pyAMReX implements the following `standardized data APIs `__: 16 | 17 | - ``__array_interface__`` (CPU) 18 | - ``__cuda_array_interface__`` (CUDA GPU) 19 | - ``DLPack`` (`coming soon `__) 20 | 21 | These APIs are automatically used when creating "views" (non-copy) numpy arrays, cupy arrays, PyTorch tensors, etc. from AMReX objects such as ``Array4`` and particle arrays. 22 | -------------------------------------------------------------------------------- /docs/source/developers/testing.rst: -------------------------------------------------------------------------------- 1 | .. _developers-testing: 2 | 3 | Testing 4 | ======= 5 | 6 | Preparation 7 | ----------- 8 | 9 | Prepare for running tests of pyAMReX by :ref:`building pyAMReX from source `. 10 | 11 | In order to run our tests, you need to have a few :ref:`Python packages installed `: 12 | 13 | .. code-block:: sh 14 | 15 | python3 -m pip install -U pip 16 | python3 -m pip install -U build packaging setuptools[core] wheel pytest 17 | python3 -m pip install -r requirements.txt 18 | 19 | 20 | Run 21 | --- 22 | 23 | You can run all our tests with: 24 | 25 | .. code-block:: sh 26 | 27 | ctest --test-dir build --output-on-failure 28 | 29 | 30 | Further Options 31 | --------------- 32 | 33 | For faster compile-and-test iterations, build with ``-DpyAMReX_IPO=OFF``: 34 | 35 | .. code-block:: sh 36 | 37 | ctest -S . -B build -DpyAMReX_IPO=OFF 38 | 39 | After successful installation, with 40 | 41 | .. code-block:: sh 42 | 43 | ctest --test-dir build --target pip_install 44 | 45 | you can also run the unit tests individually. 46 | For ``AMReX_MPI=ON``, please prepend the following commands with ``mpiexec -np `` 47 | 48 | .. code-block:: sh 49 | 50 | # Run all tests 51 | python3 -m pytest tests/ 52 | 53 | # Run tests from a single file 54 | python3 -m pytest tests/test_intvect.py 55 | 56 | # Run a single test (useful during debugging) 57 | python3 -m pytest tests/test_intvect.py::test_iv_conversions 58 | 59 | # Run all tests, do not capture "print" output and be verbose 60 | python3 -m pytest -s -vvvv tests/ 61 | -------------------------------------------------------------------------------- /docs/source/glossary.rst: -------------------------------------------------------------------------------- 1 | .. _glossary: 2 | 3 | Glossary 4 | ======== 5 | 6 | In daily communication, we tend to abbreviate a lot of terms. 7 | It is important to us to make it easy to interact with the pyAMReX community and thus, this list shall help to clarify often used terms. 8 | 9 | Please see: https://warpx.readthedocs.io/en/latest/glossary.html 10 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | pyAMReX 4 | ------- 5 | 6 | The Python binding pyAMReX bridges the compute in AMReX block-structured codes and data science: 7 | it provides zero-copy application GPU data access for AI/ML, in situ analysis, application coupling and enables rapid, massively parallel prototyping. 8 | 9 | pyAMReX is part of the `AMReX software ecosystem `__ and builds directly on the AMReX C++ library. 10 | 11 | 12 | .. _contact: 13 | 14 | Contact us 15 | ^^^^^^^^^^ 16 | 17 | If you are starting using pyAMReX, or if you have a user question, please pop in our `GitHub discussions page `__ and get in touch with the community. 18 | 19 | The `pyAMReX GitHub repo `__ is the main communication platform. 20 | Have a look at the action icons on the top right of the web page: feel free to watch the repo if you want to receive updates, or to star the repo to support the project. 21 | For bug reports or to request new features, you can also open a new `issue `__. 22 | 23 | On our `discussion page `__, you can find already answered questions, add new questions, get help with installation procedures, discuss ideas or share comments. 24 | 25 | .. raw:: html 26 | 27 | 39 | 40 | .. toctree:: 41 | :hidden: 42 | 43 | coc 44 | acknowledge_us 45 | 46 | Installation 47 | ------------ 48 | .. toctree:: 49 | :caption: INSTALLATION 50 | :maxdepth: 1 51 | :hidden: 52 | 53 | install/users 54 | install/cmake 55 | .. install/hpc 56 | .. install/changelog 57 | .. install/upgrade 58 | 59 | Usage 60 | ----- 61 | .. toctree:: 62 | :caption: USAGE 63 | :maxdepth: 1 64 | :hidden: 65 | 66 | usage/examples 67 | usage/api 68 | usage/zerocopy 69 | usage/compute 70 | usage/workflows 71 | .. usage/tests 72 | 73 | Development 74 | ----------- 75 | .. toctree:: 76 | :caption: DEVELOPMENT 77 | :maxdepth: 1 78 | :hidden: 79 | 80 | developers/testing 81 | developers/documentation 82 | developers/repo_organization 83 | developers/implementation 84 | developers/doxygen 85 | developers/debugging 86 | .. developers/contributing 87 | 88 | Maintenance 89 | ----------- 90 | .. toctree:: 91 | :caption: MAINTENANCE 92 | :maxdepth: 1 93 | :hidden: 94 | 95 | maintenance/release 96 | .. maintenance/performance_tests 97 | 98 | Epilogue 99 | -------- 100 | .. toctree:: 101 | :caption: EPILOGUE 102 | :maxdepth: 1 103 | :hidden: 104 | 105 | glossary 106 | acknowledgements 107 | -------------------------------------------------------------------------------- /docs/source/install/conda.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/source/install/spack.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 37 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 49 | 51 | 52 | 54 | 56 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/source/install/users.rst: -------------------------------------------------------------------------------- 1 | .. _install-users: 2 | 3 | Users 4 | ===== 5 | 6 | .. raw:: html 7 | 8 | 18 | 19 | Our community is here to help. 20 | Please `report installation problems `_ in case you should get stuck. 21 | 22 | Choose **one** of the installation methods below to get started: 23 | 24 | 25 | .. _install-conda: 26 | 27 | .. only:: html 28 | 29 | .. image:: conda.svg 30 | 31 | Using the Conda Package 32 | ----------------------- 33 | 34 | A package for pyAMReX is available via the `Conda `_ package manager. 35 | 36 | .. tip:: 37 | 38 | We recommend to configure your conda to use the faster ``libmamba`` `dependency solver `__. 39 | 40 | .. code-block:: bash 41 | 42 | conda update -n base conda 43 | conda install -n base conda-libmamba-solver 44 | conda config --set solver libmamba 45 | 46 | We recommend to deactivate that conda self-activates its ``base`` environment. 47 | This `avoids interference with the system and other package managers `__. 48 | 49 | .. code-block:: bash 50 | 51 | conda config --set auto_activate_base false 52 | 53 | .. code-block:: bash 54 | 55 | conda create -n pyamrex -c conda-forge pyamrex 56 | conda activate pyamrex 57 | 58 | .. note:: 59 | 60 | The ``pyamrex`` `conda package `__ does not yet provide GPU support. 61 | 62 | 63 | .. _install-spack: 64 | 65 | .. only:: html 66 | 67 | .. image:: spack.svg 68 | 69 | Using the Spack Package 70 | ----------------------- 71 | 72 | .. note:: 73 | 74 | Coming soon. 75 | 76 | 77 | .. _install-pypi: 78 | 79 | .. only:: html 80 | 81 | .. image:: pypi.svg 82 | 83 | Using the PyPI Package 84 | ---------------------- 85 | 86 | .. note:: 87 | 88 | Coming soon. 89 | 90 | 91 | .. _install-brew: 92 | 93 | .. only:: html 94 | 95 | .. image:: brew.svg 96 | 97 | Using the Brew Package 98 | ---------------------- 99 | 100 | .. note:: 101 | 102 | Coming soon. 103 | 104 | 105 | .. _install-cmake: 106 | 107 | .. only:: html 108 | 109 | .. image:: cmake.svg 110 | 111 | From Source with CMake 112 | ---------------------- 113 | 114 | After installing the :ref:`pyAMReX dependencies `, you can also install pyAMReX from source with `CMake `_: 115 | 116 | .. code-block:: bash 117 | 118 | # get the source code 119 | git clone https://github.com/AMReX-Codes/pyamrex.git $HOME/src/pyamrex 120 | cd $HOME/src/pyamrex 121 | 122 | # configure 123 | cmake -S . -B build 124 | 125 | # optional: change configuration 126 | ccmake build 127 | 128 | # compile & install 129 | # on Windows: --config Release 130 | cmake --build build -j 4 --target pip_install 131 | 132 | We document the details in the :ref:`developer installation `. 133 | 134 | Tips for macOS Users 135 | -------------------- 136 | 137 | .. tip:: 138 | 139 | Before getting started with package managers, please check what you manually installed in ``/usr/local``. 140 | If you find entries in ``bin/``, ``lib/`` et al. that look like you manually installed MPI, HDF5 or other software in the past, then remove those files first. 141 | 142 | If you find software such as MPI in the same directories that are shown as symbolic links then it is likely you `brew installed `__ software before. 143 | If you are trying annother package manager than ``brew``, run `brew unlink ... `__ on such packages first to avoid software incompatibilities. 144 | 145 | See also: A. Huebl, `Working With Multiple Package Managers `__, `Collegeville Workshop (CW20) `_, 2020 146 | -------------------------------------------------------------------------------- /docs/source/maintenance/release.rst: -------------------------------------------------------------------------------- 1 | .. _developers-release: 2 | 3 | Dependencies & Releases 4 | ======================= 5 | 6 | Update pyAMReX' Core Dependencies 7 | --------------------------------- 8 | 9 | pyAMReX has a direct dependency on AMReX, which we periodically update. 10 | 11 | It further depends on pybind11 and a Python interpreter. 12 | 13 | 14 | Create a new pyAMReX release 15 | ---------------------------- 16 | 17 | pyAMReX has one release per month. 18 | The version number is set at the beginning of the month and follows the format ``YY.MM``. 19 | 20 | In order to create a GitHub release, you need to: 21 | 22 | 1. Create a new branch from ``development`` and update the version number in all source files. 23 | We usually wait for the AMReX release to be tagged first, then we also point to its tag. 24 | 25 | For a pyAMReX release, ideally a *git tag* of AMReX shall be used instead of an unnamed commit. 26 | 27 | Then open a PR, wait for tests to pass and then merge. 28 | 29 | 2. **Local Commit** (Optional): at the moment, ``@ax3l`` is managing releases and signs tags (naming: ``YY.MM``) locally with his GPG key before uploading them to GitHub. 30 | 31 | **Publish**: On the `GitHub Release page `__, create a new release via ``Draft a new release``. 32 | Either select the locally created tag or create one online (naming: ``YY.MM``) on the merged commit of the PR from step 1. 33 | 34 | In the *release description*, please specify the compatible versions of dependencies (see previous releases), and provide info on the content of the release. 35 | In order to get a list of PRs merged since last release, you may run 36 | 37 | .. code-block:: sh 38 | 39 | git log .. --format='- %s' 40 | 41 | 3. Optional/future: create a ``release-`` branch, write a changelog, and backport bug-fixes for a few days. 42 | -------------------------------------------------------------------------------- /docs/source/usage/examples.rst: -------------------------------------------------------------------------------- 1 | .. _usage_examples: 2 | 3 | Examples 4 | ======== 5 | 6 | .. _usage_run: 7 | 8 | When to Use pyAMReX? 9 | -------------------- 10 | 11 | pyAMReX is usually used for these kinds of workflows: 12 | 13 | 1. To enhance an existing AMReX application with Python, Data-Science and AI/ML capabilities, 14 | 2. To write a standalone application or test on AMReX, rapidly prototyped in Python. 15 | 16 | 17 | Enhance an Application 18 | ---------------------- 19 | 20 | pyAMReX is used in large, production-quality high-performance applications. 21 | See the following examples: 22 | 23 | ImpactX 24 | """"""" 25 | 26 | `ImpactX `__ is an s-based beam dynamics code including space charge effects. 27 | 28 | * `Python examples `__ 29 | * `Python implementation `__ 30 | * Highlight example: `Fully GPU-accelerated PyTorch+ImpactX simulation `__ 31 | 32 | 33 | WarpX 34 | """"" 35 | `WarpX `__ is an advanced, time-based electromagnetic & electrostatic Particle-In-Cell code. 36 | 37 | * `Python (PICMI) examples `__ 38 | * `Python implementation `__ 39 | * Detailed workflow: `Extend a WarpX Simulation with Python `__ 40 | 41 | 42 | Standalone 43 | ---------- 44 | 45 | Please see the `AMReX Tutorials `__ for Python-written, GPU-accelerated AMReX examples: 46 | 47 | * `MultiFab example `__ 48 | * `Heat Equation example `__ 49 | 50 | 51 | Unit Tests 52 | ---------- 53 | 54 | We ensure the correctness of pyAMReX with `unit tests `__. 55 | Our tests are small, plentiful and can be found in the source code, see: 56 | 57 | * `tests/ `__ 58 | 59 | The following sections on :ref:`compute workflows ` go in detail through selected unit tests, too. 60 | -------------------------------------------------------------------------------- /docs/source/usage/workflows.rst: -------------------------------------------------------------------------------- 1 | .. _usage-workflows: 2 | 3 | Workflows 4 | ========= 5 | 6 | This section collects typical user workflows and best practices for pyAMReX. 7 | 8 | .. note:: 9 | 10 | TODO: Add more workflows as in https://warpx.readthedocs.io/en/latest/usage/workflows.html 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | 15 | .. workflows/parallelization 16 | .. workflows/profiling 17 | workflows/debugging 18 | .. workflows/libensemble 19 | .. workflows/plot_distribution_mapping 20 | -------------------------------------------------------------------------------- /docs/source/usage/zerocopy.rst: -------------------------------------------------------------------------------- 1 | .. _usage-zerocopy: 2 | 3 | Zero-Copy 4 | ========= 5 | 6 | The Python binding pyAMReX bridges the compute in AMReX block-structured codes and data science. 7 | As such, it includes zero-copy GPU data access for AI/ML, in situ analysis, application coupling by implementing :ref:`standardized data interfaces `. 8 | 9 | 10 | CPU: NumPy 11 | ---------- 12 | 13 | zero-copy read and write access. 14 | CPU as well as managed memory CPU/GPU. 15 | 16 | Call ``.to_numpy()`` on data objects of pyAMReX. 17 | See the optional arguments of this API. 18 | 19 | Writing to the created NumPy array will also modify the underlying AMReX memory. 20 | 21 | 22 | GPU: CuPy 23 | --------- 24 | 25 | GPU zero-copy read and write access. 26 | 27 | Call ``.to_cupy()`` on data objects of pyAMReX. 28 | See the optional arguments of this API. 29 | 30 | Writing to the created CuPy array will also modify the underlying AMReX memory. 31 | 32 | 33 | CPU/GPU Agnostic Code: NumPy/CuPy 34 | --------------------------------- 35 | 36 | The previous examples can be written in CPU/GPU agnostics manner. 37 | Either using NumPy (``np``) or CuPy (``cp``), we provide a `common short-hand abbreviation `__ named ``xp`` . 38 | 39 | Call ``.to_xp()`` on data objects of pyAMReX. 40 | See the optional arguments of this API. 41 | 42 | Writing to the created NumPy/CuPy array will also modify the underlying AMReX memory. 43 | 44 | 45 | GPU: numba 46 | ---------- 47 | 48 | GPU zero-copy read and write access. 49 | 50 | After ``from numba import cuda``, create a zero-copy tensor on a GPU array via ``marr_numba = cuda.as_cuda_array(marr)``. 51 | 52 | Writing to the created numba array will also modify the underlying AMReX memory. 53 | 54 | 55 | AI/ML: pyTorch 56 | -------------- 57 | 58 | CPU and GPU zero-copy read and write access. 59 | 60 | Create a zero-copy tensor on a GPU array via ``torch.as_tensor(amrex_array_here, device="cuda")``. 61 | 62 | Writing to the created PyTorch tensor will also modify the underlying AMReX memory. 63 | -------------------------------------------------------------------------------- /docs/spack.yaml: -------------------------------------------------------------------------------- 1 | # This is a Spack environment file. 2 | # 3 | # This environment can be used to install all dependencies to build the manual 4 | # locally. 5 | # 6 | # Activating and installing this environment will provide all dependencies 7 | # that are needed for full-feature development. 8 | # https://spack.readthedocs.io/en/latest/environments.html#anonymous-environments 9 | # 10 | # Inside ImpactX' docs/ directory: 11 | # spack env activate -d . 12 | # spack install # only needed the first time 13 | # make clean 14 | # make html 15 | # 16 | spack: 17 | specs: 18 | # note: the spec "doxygen+graphviz" causes an environment issue for me 19 | - doxygen 20 | - graphviz 21 | - py-pybind11-stubgen 22 | - python 23 | - py-sphinx 24 | - py-breathe 25 | - py-recommonmark 26 | - py-pygments 27 | - py-sphinx-copybutton 28 | - py-sphinx-design 29 | - py-sphinx-rtd-theme 30 | -------------------------------------------------------------------------------- /pyAMReXConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | # only add PUBLIC dependencies as well 4 | # https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-a-package-configuration-file 5 | include(CMakeFindDependencyMacro) 6 | 7 | # Search in _ROOT: 8 | # https://cmake.org/cmake/help/v3.12/policy/CMP0074.html 9 | if(POLICY CMP0074) 10 | cmake_policy(SET CMP0074 NEW) 11 | endif() 12 | 13 | # General options 14 | set(pyAMReX_SPACEDIM @AMReX_SPACEDIM@) 15 | set(_search_amrex_dim) 16 | foreach(D IN LISTS AMReX_SPACEDIM) 17 | set(pyAMReX_${D}D_FOUND ON) 18 | set(_search_amrex_dim ${_search_amrex_dim} "${D}D") 19 | endforeach() 20 | 21 | find_dependency(AMReX COMPONENTS ${_search_amrex_dim}) 22 | 23 | set(pyAMReX_MPI @AMReX_MPI@) 24 | set(pyAMReX_OMP @AMReX_OMP@) 25 | set(pyAMReX_CUDA @AMReX_CUDA@) 26 | set(pyAMReX_SYCL @AMReX_SYCL@) 27 | set(pyAMReX_HIP @AMReX_HIP@) 28 | set(pyAMReX_GPU_BACKEND @AMReX_GPU_BACKEND@) 29 | 30 | # define central pyAMReX::pyAMReX_${D}d targets 31 | include("${CMAKE_CURRENT_LIST_DIR}/pyAMReXTargets.cmake") 32 | 33 | # check if components are fulfilled and set pyAMReX__FOUND vars 34 | foreach(comp ${pyAMReX_FIND_COMPONENTS}) 35 | if(NOT pyAMReX_${comp}_FOUND) 36 | if(pyAMReX_FIND_REQUIRED_${comp}) 37 | set(pyAMReX_FOUND FALSE) 38 | endif() 39 | endif() 40 | endforeach() 41 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=42", 4 | "wheel", 5 | "cmake>=3.24.0", 6 | "packaging>=23", 7 | ] 8 | build-backend = "setuptools.build_meta" 9 | 10 | [tool.ruff.format] 11 | docstring-code-format = true 12 | 13 | [tool.ruff.lint] 14 | select = ["E", "F", "I"] 15 | ignore = ["E402", "E501"] 16 | 17 | [tool.ruff.lint.isort] 18 | known-first-party = ["amrex"] 19 | 20 | [tool.isort] 21 | known_first_party = ["amrex"] 22 | profile = "black" 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy>=1.15 2 | -------------------------------------------------------------------------------- /requirements_mpi.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | mpi4py>=2.1.0 3 | -------------------------------------------------------------------------------- /spack.yaml: -------------------------------------------------------------------------------- 1 | # This is a Spack environment file. 2 | # 3 | # This environment can be used to install all dependencies potentially needed 4 | # to build pyAMReX. This environment also sets all dependencies to use MPI. 5 | # 6 | # Activating and installing this environment will provide all dependencies 7 | # that are needed for full-feature development. 8 | # https//spack.readthedocs.io/en/latest/environments.html#anonymous-environments 9 | # 10 | # Inside pyAMReX' source root directory: 11 | # spack env activate -d . 12 | # spack install # only needed the first time 13 | # 14 | # If you furthermore want to build for Nvidia GPUs: 15 | # spack add cuda 16 | # spack install 17 | # 18 | spack: 19 | specs: 20 | - ccache 21 | # optional and heavy 22 | # - cuda 23 | # - py-cupy ^nccl cuda_arch=70 24 | # - py-numba ^llvm+cuda cuda_arch=70 25 | - cmake 26 | - mpi 27 | - python 28 | - py-build 29 | - py-mpi4py 30 | - py-numpy 31 | - py-packaging 32 | - py-pip 33 | - py-setuptools 34 | - py-wheel 35 | -------------------------------------------------------------------------------- /src/AmrCore/AmrMesh.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | #include 11 | 12 | 13 | void init_AmrMesh(py::module &m) 14 | { 15 | using namespace amrex; 16 | 17 | py::class_< AmrInfo >(m, "AmrInfo") 18 | .def("__repr__", 19 | [](AmrInfo const & amr_info) { 20 | std::stringstream s; 21 | s << amr_info.max_level; 22 | return ""; 23 | } 24 | ) 25 | 26 | .def(py::init< >()) 27 | 28 | .def_readwrite("verbose", &AmrInfo::verbose) 29 | .def_readwrite("max_level", &AmrInfo::max_level) 30 | 31 | // note: https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html#making-opaque-types 32 | //.def_readwrite("ref_ratio", &AmrInfo::ref_ratio) 33 | //.def_readwrite("blocking_factor", &AmrInfo::blocking_factor) 34 | //.def_readwrite("max_grid_size", &AmrInfo::max_grid_size) 35 | //.def_readwrite("n_error_buf", &AmrInfo::n_error_buf) 36 | .def("ref_ratio", [](AmrInfo const & amr_info, int lev){ return amr_info.ref_ratio.at(lev); }) 37 | .def("blocking_factor", [](AmrInfo const & amr_info, int lev){ return amr_info.blocking_factor.at(lev); }) 38 | .def("max_grid_size", [](AmrInfo const & amr_info, int lev){ return amr_info.max_grid_size.at(lev); }) 39 | .def("n_error_buf", [](AmrInfo const & amr_info, int lev){ return amr_info.n_error_buf.at(lev); }) 40 | 41 | .def_readwrite("grid_eff", &AmrInfo::grid_eff) 42 | .def_readwrite("n_proper", &AmrInfo::n_proper) 43 | .def_readwrite("use_fixed_upto_level", &AmrInfo::use_fixed_upto_level) 44 | .def_readwrite("use_fixed_coarse_grids", &AmrInfo::use_fixed_coarse_grids) 45 | .def_readwrite("refine_grid_layout", &AmrInfo::refine_grid_layout) 46 | .def_readwrite("refine_grid_layout_dims", &AmrInfo::refine_grid_layout_dims) 47 | .def_readwrite("check_input", &AmrInfo::check_input) 48 | .def_readwrite("use_new_chop", &AmrInfo::use_new_chop) 49 | .def_readwrite("iterate_on_new_grids", &AmrInfo::iterate_on_new_grids) 50 | 51 | ; 52 | 53 | py::class_< AmrMesh /*, AmrInfo*/ >(m, "AmrMesh") 54 | .def("__repr__", 55 | [](AmrMesh const &) { 56 | return ""; 57 | } 58 | ) 59 | 60 | .def(py::init< >()) 61 | .def(py::init< 62 | const RealBox&, 63 | int, 64 | const Vector&, 65 | int, 66 | Vector const&, 67 | Array const& 68 | >(), 69 | py::arg("rb"), py::arg("max_level_in"), py::arg("n_cell_in"), py::arg("coord"), py::arg("ref_ratios"), py::arg("is_per")) 70 | 71 | .def_property_readonly("verbose", &AmrMesh::Verbose) 72 | .def_property_readonly("max_level", &AmrMesh::maxLevel) 73 | .def_property_readonly("finest_level", &AmrMesh::finestLevel) 74 | .def("ref_ratio", py::overload_cast< >(&AmrMesh::refRatio, py::const_)) 75 | .def("ref_ratio", py::overload_cast< int >(&AmrMesh::refRatio, py::const_)) 76 | ; 77 | } 78 | -------------------------------------------------------------------------------- /src/AmrCore/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | foreach(D IN LISTS AMReX_SPACEDIM) 2 | target_sources(pyAMReX_${D}d 3 | PRIVATE 4 | AmrMesh.cpp 5 | ) 6 | endforeach() 7 | -------------------------------------------------------------------------------- /src/Base/Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2025 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | #include 11 | 12 | 13 | void init_Algorithm (py::module& m) 14 | { 15 | using namespace amrex; 16 | 17 | m.def( 18 | "almost_equal", 19 | &almostEqual, 20 | py::arg("x"), py::arg("y"), py::arg("ulp")=2 21 | ); 22 | 23 | if constexpr (!std::is_same_v) 24 | { 25 | m.def( 26 | "almost_equal", 27 | &almostEqual, 28 | py::arg("x"), py::arg("y"), py::arg("ulp")=2 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Base/Arena.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | 11 | void init_Arena(py::module &m) { 12 | using namespace amrex; 13 | 14 | py::class_< Arena >(m, "Arena") 15 | .def_static("initialize", &Arena::Initialize) 16 | .def_static("print_usage", &Arena::PrintUsage) 17 | .def_static("print_usage_to_files", &Arena::PrintUsageToFiles, 18 | py::arg("filename"), py::arg("message")) 19 | .def_static("finalize", &Arena::Finalize) 20 | 21 | // these two can be true at the same time 22 | .def_property_readonly("is_device_accessible", &Arena::isDeviceAccessible) 23 | .def_property_readonly("is_host_accessible", &Arena::isHostAccessible) 24 | 25 | // the next three are mutually exclusive 26 | .def_property_readonly("is_managed", &Arena::isManaged) 27 | .def_property_readonly("is_device", &Arena::isDevice) 28 | .def_property_readonly("is_pinned", &Arena::isPinned) 29 | 30 | #ifdef AMREX_USE_GPU 31 | .def_property_readonly("is_stream_ordered_arena", &Arena::isStreamOrderedArena) 32 | #endif 33 | 34 | .def("has_free_device_memory", &Arena::hasFreeDeviceMemory, 35 | py::arg("sz"), 36 | "Does the device have enough free memory for allocating this " 37 | "much memory? For CPU builds, this always return true.") 38 | ; 39 | 40 | m.def("The_Arena", &The_Arena, py::return_value_policy::reference) 41 | .def("The_Async_Arena", &The_Async_Arena, py::return_value_policy::reference) 42 | .def("The_Device_Arena", &The_Device_Arena, py::return_value_policy::reference) 43 | .def("The_Managed_Arena", &The_Managed_Arena, py::return_value_policy::reference) 44 | .def("The_Pinned_Arena", &The_Pinned_Arena, py::return_value_policy::reference) 45 | .def("The_Cpu_Arena", &The_Cpu_Arena, py::return_value_policy::reference) 46 | ; 47 | 48 | // ArenaInfo 49 | } 50 | -------------------------------------------------------------------------------- /src/Base/Array4.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | 11 | void init_Array4_float(py::module &m); 12 | void init_Array4_float_const(py::module &m); 13 | 14 | void init_Array4_complex(py::module &m); 15 | void init_Array4_complex_const(py::module &m); 16 | 17 | void init_Array4_int(py::module &m); 18 | void init_Array4_int_const(py::module &m); 19 | 20 | void init_Array4_uint(py::module &m); 21 | void init_Array4_uint_const(py::module &m); 22 | 23 | void init_Array4(py::module &m) 24 | { 25 | using namespace pyAMReX; 26 | 27 | init_Array4_float(m); 28 | init_Array4_float_const(m); 29 | 30 | init_Array4_complex(m); 31 | init_Array4_complex_const(m); 32 | 33 | init_Array4_int(m); 34 | init_Array4_int_const(m); 35 | 36 | init_Array4_uint(m); 37 | init_Array4_uint_const(m); 38 | 39 | /* 40 | py::class_< PolymorphicArray4, Array4 >(m, "PolymorphicArray4") 41 | .def("__repr__", 42 | [](PolymorphicArray4 const & pa4) { 43 | std::stringstream s; 44 | s << pa4.size(); 45 | return ""; 46 | } 47 | ) 48 | ; 49 | */ 50 | } 51 | -------------------------------------------------------------------------------- /src/Base/Array4_complex.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | #include 11 | 12 | 13 | void init_Array4_complex(py::module &m) 14 | { 15 | using namespace pyAMReX; 16 | 17 | make_Array4< std::complex >(m, "cfloat"); 18 | make_Array4< std::complex >(m, "cdouble"); 19 | 20 | // not great on device 21 | // NVCC Warning #20208-D: 'long double' is treated as 'double' in device code 22 | //make_Array4< std::complex >(m, "clongdouble"); 23 | } 24 | -------------------------------------------------------------------------------- /src/Base/Array4_complex_const.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | #include 11 | 12 | 13 | void init_Array4_complex_const(py::module &m) 14 | { 15 | using namespace pyAMReX; 16 | 17 | make_Array4< std::complex const >(m, "cfloat_const"); 18 | make_Array4< std::complex const >(m, "cdouble_const"); 19 | 20 | // not great on device: 21 | // NVCC Warning #20208-D: 'long double' is treated as 'double' in device code 22 | //make_Array4< std::complex >(m, "clongdouble_const"); 23 | } 24 | -------------------------------------------------------------------------------- /src/Base/Array4_float.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | 11 | void init_Array4_float(py::module &m) 12 | { 13 | using namespace pyAMReX; 14 | 15 | make_Array4< float >(m, "float"); 16 | make_Array4< double >(m, "double"); 17 | make_Array4< long double >(m, "longdouble"); 18 | } 19 | -------------------------------------------------------------------------------- /src/Base/Array4_float_const.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | 11 | void init_Array4_float_const(py::module &m) 12 | { 13 | using namespace pyAMReX; 14 | 15 | make_Array4< float const >(m, "float_const"); 16 | make_Array4< double const >(m, "double_const"); 17 | make_Array4< long double const >(m, "longdouble_const"); 18 | } 19 | -------------------------------------------------------------------------------- /src/Base/Array4_int.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | #include 11 | 12 | 13 | void init_Array4_int(py::module &m) 14 | { 15 | using namespace pyAMReX; 16 | 17 | make_Array4< short >(m, "short"); 18 | make_Array4< int >(m, "int"); 19 | make_Array4< long >(m, "long"); 20 | make_Array4< long long >(m, "longlong"); 21 | } 22 | -------------------------------------------------------------------------------- /src/Base/Array4_int_const.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | #include 11 | 12 | 13 | void init_Array4_int_const(py::module &m) 14 | { 15 | using namespace pyAMReX; 16 | 17 | make_Array4< short const >(m, "short_const"); 18 | make_Array4< int const >(m, "int_const"); 19 | make_Array4< long const >(m, "long_const"); 20 | make_Array4< long long const >(m, "longlong_const"); 21 | } 22 | -------------------------------------------------------------------------------- /src/Base/Array4_uint.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | #include 11 | 12 | 13 | void init_Array4_uint(py::module &m) 14 | { 15 | using namespace pyAMReX; 16 | 17 | make_Array4< unsigned short >(m, "ushort"); 18 | make_Array4< unsigned int >(m, "uint"); 19 | make_Array4< unsigned long >(m, "ulong"); 20 | make_Array4< unsigned long long >(m, "ulonglong"); 21 | } 22 | -------------------------------------------------------------------------------- /src/Base/Array4_uint_const.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Array4.H" 9 | 10 | #include 11 | 12 | 13 | void init_Array4_uint_const(py::module &m) 14 | { 15 | using namespace pyAMReX; 16 | 17 | make_Array4< unsigned short const >(m, "ushort_const"); 18 | make_Array4< unsigned int const >(m, "uint_const"); 19 | make_Array4< unsigned long const >(m, "ulong_const"); 20 | make_Array4< unsigned long long const >(m, "ulonglong_const"); 21 | } 22 | -------------------------------------------------------------------------------- /src/Base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | foreach(D IN LISTS AMReX_SPACEDIM) 2 | target_sources(pyAMReX_${D}d 3 | PRIVATE 4 | Algorithm.cpp 5 | AMReX.cpp 6 | Arena.cpp 7 | Array4.cpp 8 | Array4_complex.cpp 9 | Array4_complex_const.cpp 10 | Array4_float.cpp 11 | Array4_float_const.cpp 12 | Array4_int.cpp 13 | Array4_int_const.cpp 14 | Array4_uint.cpp 15 | Array4_uint_const.cpp 16 | BaseFab.cpp 17 | Box.cpp 18 | RealBox.cpp 19 | BoxArray.cpp 20 | CoordSys.cpp 21 | Dim3.cpp 22 | DistributionMapping.cpp 23 | FabArray.cpp 24 | FArrayBox.cpp 25 | Geometry.cpp 26 | iMultiFab.cpp 27 | IndexType.cpp 28 | IntVect.cpp 29 | RealVect.cpp 30 | SmallMatrix.cpp 31 | MFInfo.cpp 32 | MultiFab.cpp 33 | ParallelDescriptor.cpp 34 | ParmParse.cpp 35 | Periodicity.cpp 36 | PlotFileUtil.cpp 37 | PODVector.cpp 38 | Utility.cpp 39 | Vector.cpp 40 | Version.cpp 41 | VisMF.cpp 42 | ) 43 | 44 | if (AMReX_MPI) 45 | target_sources(pyAMReX_${D}d 46 | PRIVATE 47 | MPMD.cpp 48 | ) 49 | endif() 50 | endforeach() 51 | -------------------------------------------------------------------------------- /src/Base/CoordSys.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2023 The AMReX Community 2 | * 3 | * Authors: Axel Huebl, Ryan Sandberg 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | 11 | void init_CoordSys(py::module& m) 12 | { 13 | using namespace amrex; 14 | 15 | py::class_ coord_sys(m, "CoordSys"); 16 | 17 | py::enum_(coord_sys, "CoordType") 18 | .value("undef", CoordSys::CoordType::undef) 19 | .value("cartesian", CoordSys::CoordType::cartesian) 20 | .value("RZ", CoordSys::CoordType::RZ) 21 | .value("SPHERICAL", CoordSys::CoordType::SPHERICAL) 22 | .export_values(); 23 | 24 | coord_sys.def("__repr__", 25 | [](const CoordSys&) { 26 | return ""; 27 | } 28 | ) 29 | .def(py::init<>()) 30 | .def(py::init()) 31 | 32 | .def("ok", &CoordSys::Ok) 33 | .def("Coord", &CoordSys::Coord) 34 | .def("SetCoord", &CoordSys::SetCoord) 35 | .def("CoordInt", &CoordSys::CoordInt) 36 | .def("IsSPHERICAL", &CoordSys::IsSPHERICAL) 37 | .def("IsRZ",&CoordSys::IsRZ ) 38 | .def("IsCartesian", &CoordSys::IsCartesian) 39 | 40 | // ... 41 | ; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/Base/Dim3.cpp: -------------------------------------------------------------------------------- 1 | #include "pyAMReX.H" 2 | 3 | #include 4 | 5 | #include 6 | 7 | 8 | void init_Dim3(py::module& m) 9 | { 10 | using namespace amrex; 11 | 12 | py::class_(m, "Dim3") 13 | .def("__repr__", 14 | [](const Dim3& d) { 15 | std::stringstream s; 16 | s << d; 17 | return ""; 18 | } 19 | ) 20 | .def("__str__", 21 | [](const Dim3& d) { 22 | std::stringstream s; 23 | s << d; 24 | return s.str(); 25 | } 26 | ) 27 | .def(py::init()) 28 | .def_readwrite("x", &Dim3::x) 29 | .def_readwrite("y", &Dim3::y) 30 | .def_readwrite("z", &Dim3::z) 31 | ; 32 | 33 | py::class_(m, "XDim3") 34 | .def(py::init()) 35 | .def_readwrite("x", &XDim3::x) 36 | .def_readwrite("y", &XDim3::y) 37 | .def_readwrite("z", &XDim3::z) 38 | ; 39 | } 40 | -------------------------------------------------------------------------------- /src/Base/DistributionMapping.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Base/Vector.H" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | 17 | void init_DistributionMapping(py::module &m) { 18 | using namespace amrex; 19 | 20 | py::class_< DistributionMapping >(m, "DistributionMapping") 21 | .def("__repr__", 22 | [](DistributionMapping const & dm) { 23 | std::stringstream s; 24 | s << dm.size(); 25 | return ""; 26 | } 27 | ) 28 | 29 | .def(py::init< >()) 30 | .def(py::init< DistributionMapping const & >()) 31 | //.def(py::init< DistributionMapping && >()) 32 | //.def(py::init< DistributionMapping const &, DistributionMapping const & >()) 33 | .def(py::init< Vector< int > const & >()) 34 | //.def(py::init< Vector< int > && >()) 35 | .def(py::init< BoxArray const & >(), 36 | py::arg("boxes") 37 | ) 38 | .def(py::init< BoxArray const &, int >(), 39 | py::arg("boxes"), py::arg("nprocs") 40 | ) 41 | 42 | .def("define", 43 | [](DistributionMapping & dm, BoxArray const & boxes) { 44 | dm.define(boxes); 45 | }, 46 | py::arg("boxes") 47 | ) 48 | .def("define", 49 | py::overload_cast< BoxArray const &, int >(&DistributionMapping::define), 50 | py::arg("boxes"), py::arg("nprocs") 51 | ) 52 | .def("define", 53 | py::overload_cast< Vector< int > const & >(&DistributionMapping::define)) 54 | //.def("define", 55 | // py::overload_cast< Vector< int > && >(&DistributionMapping::define)) 56 | //! Length of the underlying processor map. 57 | .def_property_readonly("size", &DistributionMapping::size) 58 | .def_property_readonly("capacity", &DistributionMapping::capacity) 59 | .def_property_readonly("empty", &DistributionMapping::empty) 60 | 61 | //! Number of references to this DistributionMapping 62 | .def_property_readonly("link_count", &DistributionMapping::linkCount) 63 | 64 | /** 65 | * \brief Returns a constant reference to the mapping of boxes in the 66 | * underlying BoxArray to the CPU that holds the FAB on that Box. 67 | * ProcessorMap()[i] is an integer in the interval [0, NCPU) where 68 | * NCPU is the number of CPUs being used. 69 | */ 70 | .def("ProcessorMap", &DistributionMapping::ProcessorMap) 71 | 72 | //! Equivalent to ProcessorMap()[index]. 73 | .def("__getitem__", 74 | [](DistributionMapping const & dm, int index) -> int { 75 | return dm[index]; 76 | }) 77 | ; 78 | 79 | make_Vector (m, "DistributionMapping"); 80 | } 81 | -------------------------------------------------------------------------------- /src/Base/FArrayBox.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | void init_FArrayBox(py::module &m) { 16 | using namespace amrex; 17 | 18 | py::class_< FArrayBox, BaseFab >(m, "FArrayBox") 19 | .def("__repr__", 20 | [](FArrayBox const & /* fab */) { 21 | std::string r = ""; 22 | return r; 23 | } 24 | ) 25 | 26 | .def(py::init< >()) 27 | .def(py::init< Arena* >()) 28 | .def(py::init< Box const &, int, Arena* >()) 29 | .def(py::init< Box const &, int, bool, bool, Arena* >()) 30 | //.def(py::init< FArrayBox const &, MakeType, int, int >()) 31 | .def(py::init< Box const &, int, Real const* >()) 32 | .def(py::init< Box const &, int, Real* >()) 33 | .def(py::init< Array4 const& >()) 34 | .def(py::init< Array4 const&, IndexType >()) 35 | .def(py::init< Array4 const& >()) 36 | .def(py::init< Array4 const&, IndexType >()) 37 | 38 | /* 39 | .def("read_from", 40 | py::overload_cast(&FArrayBox::readFrom), 41 | py::arg("is") 42 | ) 43 | .def("read_from", 44 | py::overload_cast(&FArrayBox::readFrom), 45 | py::arg("is"), py::arg("compIndex") 46 | ) 47 | .def("write_on", 48 | py::overload_cast(&FArrayBox::writeOn, py::const_), 49 | py::arg("of") 50 | ) 51 | .def("write_on", 52 | py::overload_cast(&FArrayBox::writeOn, py::const_), 53 | py::arg("of"), py::arg("comp"), py::arg("num_comp") 54 | ) 55 | */ 56 | ; 57 | } 58 | -------------------------------------------------------------------------------- /src/Base/IndexType.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: David Grote, Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | namespace { 18 | int check_index(const int i) 19 | { 20 | const int ii = (i >= 0) ? i : AMREX_SPACEDIM + i; 21 | if ((ii < 0) || (ii >= AMREX_SPACEDIM)) 22 | throw py::index_error( "IndexType index " + std::to_string(i) + " out of bounds"); 23 | return ii; 24 | } 25 | } 26 | 27 | void init_IndexType(py::module &m) { 28 | using namespace amrex; 29 | 30 | py::class_< IndexType > index_type(m, "IndexType"); 31 | 32 | py::enum_(index_type, "CellIndex") 33 | .value("CELL", IndexType::CellIndex::CELL) 34 | .value("NODE", IndexType::CellIndex::NODE) 35 | .export_values(); 36 | 37 | index_type.def("__repr__", 38 | [](py::object& obj) { 39 | py::str py_name = obj.attr("__class__").attr("__name__"); 40 | const std::string name = py_name; 41 | const auto iv = obj.cast(); 42 | std::stringstream s; 43 | s << iv; 44 | return ""; 45 | } 46 | ) 47 | .def("__str", 48 | [](const IndexType& iv) { 49 | std::stringstream s; 50 | s << iv; 51 | return s.str(); 52 | }) 53 | 54 | .def(py::init<>()) 55 | .def(py::init()) 56 | #if (AMREX_SPACEDIM > 1) 57 | .def(py::init()) 58 | #endif 59 | 60 | .def("__getitem__", 61 | [](const IndexType& v, const int i) { 62 | const int ii = check_index(i); 63 | return v[ii]; 64 | }) 65 | 66 | .def("__len__", [](IndexType const &) { return AMREX_SPACEDIM; }) 67 | .def("__eq__", 68 | py::overload_cast(&IndexType::operator==, py::const_)) 69 | .def("__ne__", 70 | py::overload_cast(&IndexType::operator!=, py::const_)) 71 | .def("__lt__", &IndexType::operator<) 72 | 73 | .def("set", [](IndexType& v, int i) { 74 | const int ii = check_index(i); 75 | v.set(ii); 76 | }) 77 | .def("unset", [](IndexType& v, int i) { 78 | const int ii = check_index(i); 79 | v.unset(ii); 80 | }) 81 | .def("test", [](const IndexType& v, int i) { 82 | const int ii = check_index(i); 83 | return v.test(ii); 84 | }) 85 | .def("setall", &IndexType::setall) 86 | .def("clear", &IndexType::clear) 87 | .def("any", &IndexType::any) 88 | .def("ok", &IndexType::ok) 89 | .def("flip", [](IndexType& v, int i) { 90 | const int ii = check_index(i); 91 | v.flip(ii); 92 | }) 93 | 94 | .def("cell_centered", py::overload_cast<>(&IndexType::cellCentered, py::const_)) 95 | .def("cell_centered", [](const IndexType& v, int i) { 96 | const int ii = check_index(i); 97 | return v.cellCentered(ii); 98 | }) 99 | .def("node_centered", py::overload_cast<>(&IndexType::nodeCentered, py::const_)) 100 | .def("node_centered", [](const IndexType& v, int i) { 101 | const int ii = check_index(i); 102 | return v.nodeCentered(ii); 103 | }) 104 | 105 | .def("set_type", [](IndexType& v, int i, IndexType::CellIndex t) { 106 | const int ii = check_index(i); 107 | v.setType(ii, t); 108 | }) 109 | .def("ix_type", py::overload_cast<>(&IndexType::ixType, py::const_)) 110 | .def("ix_type", [](const IndexType& v, int i) { 111 | const int ii = check_index(i); 112 | return v.ixType(ii); 113 | }) 114 | .def("to_IntVect", &IndexType::toIntVect) 115 | 116 | .def_static("cell_type", &IndexType::TheCellType) 117 | .def_static("node_type", &IndexType::TheNodeType) 118 | 119 | ; 120 | } 121 | -------------------------------------------------------------------------------- /src/Base/MFInfo.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | 11 | void init_MFInfo(py::module &m) 12 | { 13 | using namespace amrex; 14 | 15 | py::class_(m, "MFInfo") 16 | .def_readwrite("alloc", &MFInfo::alloc) 17 | .def_readwrite("arena", &MFInfo::arena) 18 | .def_readwrite("tags", &MFInfo::tags) 19 | 20 | .def(py::init<>()) 21 | 22 | .def("set_alloc", &MFInfo::SetAlloc) 23 | .def("set_arena", &MFInfo::SetArena) 24 | //.def("set_tag", py::overload_cast< std::string >(&MFInfo::SetTag)) 25 | .def("set_tag", [](MFInfo &info, std::string tag) { info.SetTag(std::move(tag)); }); 26 | 27 | py::class_(m, "MFItInfo") 28 | .def_readwrite("do_tiling", &MFItInfo::do_tiling) 29 | .def_readwrite("dynamic", &MFItInfo::dynamic) 30 | .def_readwrite("device_sync", &MFItInfo::device_sync) 31 | .def_readwrite("num_streams", &MFItInfo::num_streams) 32 | .def_readwrite("tilesize", &MFItInfo::tilesize) 33 | 34 | .def(py::init<>()) 35 | 36 | .def("enable_tiling", &MFItInfo::EnableTiling, 37 | py::arg("ts") /*=FabArrayBase::mfiter_tile_size*/ ) 38 | .def("set_dynamic", &MFItInfo::SetDynamic, 39 | py::arg("f")) 40 | .def("disable_device_sync", &MFItInfo::DisableDeviceSync) 41 | .def("set_device_sync", &MFItInfo::SetDeviceSync, 42 | py::arg("f")) 43 | .def("set_num_streams", &MFItInfo::SetNumStreams, 44 | py::arg("n")) 45 | .def("use_default_stream", &MFItInfo::UseDefaultStream); 46 | } 47 | -------------------------------------------------------------------------------- /src/Base/ParallelDescriptor.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | 11 | void init_ParallelDescriptor(py::module &m) 12 | { 13 | using namespace amrex; 14 | 15 | auto mpd = m.def_submodule("ParallelDescriptor"); 16 | 17 | mpd.def("NProcs", py::overload_cast<>(&ParallelDescriptor::NProcs)) 18 | .def("MyProc", py::overload_cast<>(&ParallelDescriptor::MyProc)) 19 | .def("IOProcessor", py::overload_cast<>(&ParallelDescriptor::IOProcessor)) 20 | .def("IOProcessorNumber", py::overload_cast<>(&ParallelDescriptor::IOProcessorNumber)) 21 | ; 22 | // ... 23 | } 24 | -------------------------------------------------------------------------------- /src/Base/ParmParse.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | void init_ParmParse(py::module &m) 18 | { 19 | using namespace amrex; 20 | 21 | py::class_(m, "ParmParse") 22 | .def("__repr__", 23 | [](ParmParse const &) { 24 | // todo: make ParmParse::getPrefix() public? 25 | return ""; 26 | } 27 | ) 28 | .def(py::init(), 29 | py::arg("prefix") = std::string() 30 | ) 31 | 32 | .def("remove", &ParmParse::remove) 33 | 34 | .def_static("addfile", &ParmParse::addfile) 35 | 36 | .def("add", py::overload_cast(&ParmParse::add)) 37 | .def("add", py::overload_cast(&ParmParse::add)) 38 | .def("add", py::overload_cast(&ParmParse::add)) 39 | .def("add", py::overload_cast(&ParmParse::add)) 40 | .def("add", py::overload_cast(&ParmParse::add)) 41 | .def("add", py::overload_cast(&ParmParse::add)) 42 | .def("add", py::overload_cast(&ParmParse::add)) 43 | .def("add", py::overload_cast(&ParmParse::add)) 44 | .def("add", py::overload_cast(&ParmParse::add)) 45 | 46 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 47 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 48 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 49 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 50 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 51 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 52 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 53 | .def("addarr", py::overload_cast const &>(&ParmParse::addarr)) 54 | 55 | // TODO: getters and queries 56 | .def("get_bool", 57 | [](ParmParse &pp, std::string name, int ival) { 58 | bool ref; 59 | pp.get(name.c_str(), ref, ival); 60 | return ref; 61 | }, 62 | "parses input values", py::arg("name"), py::arg("ival")=0 63 | ) 64 | 65 | .def("get_int", 66 | [](ParmParse &pp, std::string name, int ival) { 67 | int ref; 68 | pp.get(name.c_str(), ref, ival); 69 | return ref; 70 | }, 71 | "parses input values", py::arg("name"), py::arg("ival")=0 72 | ) 73 | 74 | .def("get_real", 75 | [](ParmParse &pp, std::string name, int ival) { 76 | amrex::Real ref; 77 | pp.get(name.c_str(), ref, ival); 78 | return ref; 79 | }, 80 | "parses input values", py::arg("name"), py::arg("ival")=0 81 | ) 82 | 83 | .def("query_int", 84 | [](ParmParse &pp, std::string name, int ival) { 85 | int ref; 86 | bool exist = pp.query(name.c_str(), ref, ival); 87 | return std::make_tuple(exist,ref); 88 | }, 89 | "queries input values", py::arg("name"), py::arg("ival")=0 90 | ) 91 | 92 | .def( 93 | "pretty_print_table", 94 | [](ParmParse &pp) { 95 | py::scoped_ostream_redirect stream( 96 | std::cout, // std::ostream& 97 | py::module_::import("sys").attr("stdout") // Python output 98 | ); 99 | pp.prettyPrintTable(std::cout); 100 | }, 101 | "Write the table in a pretty way to the ostream. If there are " 102 | "duplicates, only the last one is printed." 103 | ) 104 | 105 | // TODO: dumpTable, hasUnusedInputs, getUnusedInputs, getEntries 106 | ; 107 | } 108 | -------------------------------------------------------------------------------- /src/Base/Periodicity.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | 17 | void init_Periodicity(py::module &m) 18 | { 19 | using namespace amrex; 20 | 21 | py::class_< Periodicity >(m, "Periodicity") 22 | .def("__repr__", 23 | [](Periodicity const & p) { 24 | std::stringstream s; 25 | s << std::boolalpha 26 | << AMREX_D_TERM( 27 | p.isPeriodic(0), 28 | << ", " << p.isPeriodic(1), 29 | << ", " << p.isPeriodic(2)); 30 | return ""; 31 | } 32 | ) 33 | 34 | .def(py::init<>()) 35 | .def(py::init< IntVect const & >()) 36 | 37 | .def_property_readonly("is_any_periodic", &Periodicity::isAnyPeriodic) 38 | .def_property_readonly("is_all_periodic", &Periodicity::isAllPeriodic) 39 | .def_property_readonly("domain", &Periodicity::Domain, 40 | "Cell-centered domain Box \"infinitely\" long in non-periodic directions.") 41 | .def_property_readonly("shift_IntVect", &Periodicity::shiftIntVect) 42 | 43 | .def("is_periodic", &Periodicity::isPeriodic, 44 | py::arg("dir")) 45 | .def("__getitem__", &Periodicity::isPeriodic, 46 | py::arg("dir")) 47 | 48 | .def(pybind11::self == pybind11::self) 49 | //.def(pybind11::self != pybind11::self) 50 | 51 | .def_static("non_periodic", &Periodicity::NonPeriodic, 52 | "Return the Periodicity object that is not periodic in any direction") 53 | ; 54 | } 55 | -------------------------------------------------------------------------------- /src/Base/PlotFileUtil.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * License: BSD-3-Clause-LBNL 4 | */ 5 | #include "pyAMReX.H" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace py = pybind11; 15 | using namespace amrex; 16 | 17 | void init_PlotFileUtil(py::module &m) { 18 | m.def("write_single_level_plotfile", &amrex::WriteSingleLevelPlotfile, 19 | "Writes single level plotfile", py::arg("plotfilename"), py::arg("mf"), 20 | py::arg("varnames"), py::arg("geom"), py::arg("time"), 21 | py::arg("level_step"), py::arg("versionName") = "HyperCLaw-V1.1", 22 | py::arg("levelPrefix") = "Level_", py::arg("mfPrefix") = "Cell", 23 | py::arg_v("extra_dirs", Vector(), "list[str]")); 24 | 25 | py::class_(m, "PlotFileData") 26 | // explicitly provide constructor argument types 27 | .def(py::init()) 28 | 29 | .def("spaceDim", &PlotFileData::spaceDim) 30 | .def("time", &PlotFileData::time) 31 | .def("finestLevel", &PlotFileData::finestLevel) 32 | .def("refRatio", &PlotFileData::refRatio) 33 | .def("levelStep", &PlotFileData::levelStep) 34 | .def("boxArray", &PlotFileData::boxArray) 35 | .def("DistributionMap", &PlotFileData::DistributionMap) 36 | .def("syncDistributionMap", py::overload_cast(&PlotFileData::syncDistributionMap)) 37 | .def("syncDistributionMap", py::overload_cast(&PlotFileData::syncDistributionMap)) 38 | 39 | .def("coordSys", &PlotFileData::coordSys) 40 | .def("probDomain", &PlotFileData::probDomain) 41 | .def("probSize", &PlotFileData::probSize) 42 | .def("probLo", &PlotFileData::probLo) 43 | .def("probHi", &PlotFileData::probHi) 44 | .def("cellSize", &PlotFileData::cellSize) 45 | .def("varNames", &PlotFileData::varNames) 46 | .def("nComp", &PlotFileData::nComp) 47 | .def("nGrowVect", &PlotFileData::nGrowVect) 48 | 49 | .def("get", py::overload_cast(&PlotFileData::get)) 50 | .def("get", py::overload_cast(&PlotFileData::get)); 51 | } 52 | -------------------------------------------------------------------------------- /src/Base/SmallMatrix.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2025 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "SmallMatrix.H" 9 | 10 | 11 | void init_SmallMatrix (py::module &m) 12 | { 13 | using namespace pyAMReX; 14 | 15 | // 6x6 Matrix as commonly used in accelerator physics 16 | { 17 | constexpr int NRows = 6; 18 | constexpr int NCols = 6; 19 | constexpr amrex::Order ORDER = amrex::Order::F; 20 | constexpr int StartIndex = 1; 21 | 22 | make_SmallMatrix< float, NRows, NCols, ORDER, StartIndex >(m, "float"); 23 | make_SmallMatrix< double, NRows, NCols, ORDER, StartIndex >(m, "double"); 24 | make_SmallMatrix< long double, NRows, NCols, ORDER, StartIndex >(m, "longdouble"); 25 | /* 26 | make_SmallMatrix< float const, NRows, NCols, ORDER, StartIndex >(m, "float_const"); 27 | make_SmallMatrix< double const, NRows, NCols, ORDER, StartIndex >(m, "double_const"); 28 | make_SmallMatrix< long double const, NRows, NCols, ORDER, StartIndex >(m, "longdouble_const"); 29 | */ 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Base/Utility.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * License: BSD-3-Clause-LBNL 4 | * Authors: Revathi Jambunathan, Axel Huebl 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | 10 | #include 11 | 12 | 13 | void init_Utility(py::module& m) 14 | { 15 | m.def("concatenate", 16 | &amrex::Concatenate, 17 | "Builds plotfile name", 18 | py::arg("root"), py::arg("num"), py::arg("mindigits")=5 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/Base/Vector.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2022 The AMReX Community 2 | * 3 | * Authors: Ryan Sandberg 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include "Base/Vector.H" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | 17 | void init_Vector(py::module& m) 18 | { 19 | using namespace amrex; 20 | 21 | make_Vector (m, "Real"); 22 | if constexpr(!std::is_same_v) 23 | make_Vector (m, "ParticleReal"); 24 | 25 | make_Vector (m, "int"); 26 | if constexpr(!std::is_same_v) 27 | make_Vector (m, "Long"); 28 | 29 | make_Vector (m, "Box"); 30 | make_Vector (m, "string"); 31 | } 32 | -------------------------------------------------------------------------------- /src/Base/Version.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2023 The AMReX Community 2 | * 3 | * License: BSD-3-Clause-LBNL 4 | * Authors: Axel Huebl 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | #include 10 | 11 | 12 | void init_Version (py::module& m) 13 | { 14 | // API runtime version 15 | // note PEP-440 syntax: x.y.zaN but x.y.z.devN 16 | m.attr("__version__") = amrex::Version(); 17 | } 18 | -------------------------------------------------------------------------------- /src/Base/VisMF.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2024 The AMReX Community 2 | * 3 | * Authors: David Grote 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | 8 | #include 9 | #include 10 | 11 | void init_VisMF(py::module &m) 12 | { 13 | py::class_< amrex::VisMF > py_VisMF(m, "VisMF"); 14 | 15 | py_VisMF 16 | .def_static("Write", 17 | [](const amrex::FabArray &mf, const std::string& name) { 18 | return amrex::VisMF::Write(mf, name); 19 | }, 20 | py::arg("mf"), py::arg("name"), 21 | "Writes a Multifab to the specified file") 22 | .def_static("Read", 23 | [](const std::string &name) { 24 | amrex::MultiFab mf; 25 | if (amrex::VisMF::Exist(name)) { 26 | amrex::VisMF::Read(mf, name); 27 | } else { 28 | throw std::runtime_error("MultiFab file " + name + " couldn't be found!"); 29 | } 30 | return mf; 31 | }, 32 | py::return_value_policy::move, 33 | py::arg("name"), 34 | "Reads a MultiFab from the specified file") 35 | .def_static("Read", 36 | [](const std::string &name, amrex::MultiFab &mf) { 37 | if (amrex::VisMF::Exist(name)) { 38 | amrex::VisMF::Read(mf, name); 39 | } else { 40 | throw std::runtime_error("MultiFab file " + name + " couldn't be found!"); 41 | } 42 | }, 43 | py::arg("name"), py::arg("mf"), 44 | "Reads a MultiFab from the specified file into the given MultiFab. The BoxArray on the disk must match the BoxArray * in mf") 45 | ; 46 | } 47 | -------------------------------------------------------------------------------- /src/Base/iMultiFab.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2022 The AMReX Community 2 | * 3 | * Authors: Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "pyAMReX.H" 7 | #include "MultiFab.H" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | void init_iMultiFab(py::module &m) 15 | { 16 | using namespace amrex; 17 | 18 | py::class_< iMultiFab, FabArray > py_iMultiFab(m, "iMultiFab"); 19 | make_MultiFab(py_iMultiFab, "iMultiFab"); 20 | 21 | m.def("copy_mfab", py::overload_cast< iMultiFab &, iMultiFab const &, int, int, int, int >(&iMultiFab::Copy), py::arg("dst"), py::arg("src"), py::arg("srccomp"), py::arg("dstcomp"), py::arg("numcomp"), py::arg("nghost")) 22 | .def("copy_mfab", py::overload_cast< iMultiFab &, iMultiFab const &, int, int, int, IntVect const & >(&iMultiFab::Copy), py::arg("dst"), py::arg("src"), py::arg("srccomp"), py::arg("dstcomp"), py::arg("numcomp"), py::arg("nghost")); 23 | } 24 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #add_subdirectory(Amr) 2 | add_subdirectory(AmrCore) 3 | add_subdirectory(Base) 4 | #add_subdirectory(Boundary) 5 | #add_subdirectory(EB) 6 | #add_subdirectory(Extern) 7 | #add_subdirectory(LinearSolvers) 8 | add_subdirectory(Particle) 9 | #add_subdirectory(SDC) 10 | -------------------------------------------------------------------------------- /src/Particle/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | foreach(D IN LISTS AMReX_SPACEDIM) 2 | target_sources(pyAMReX_${D}d 3 | PRIVATE 4 | ParticleContainer.cpp 5 | ParticleContainer_FHDeX.cpp 6 | ParticleContainer_ImpactX.cpp 7 | ParticleContainer_WarpX.cpp 8 | ) 9 | endforeach() 10 | -------------------------------------------------------------------------------- /src/Particle/ParticleContainer.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2022 The AMReX Community 2 | * 3 | * Authors: Ryan Sandberg, Axel Huebl, Andrew Myers 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "ParticleContainer.H" 7 | 8 | #include 9 | 10 | #include 11 | 12 | 13 | namespace 14 | { 15 | using namespace amrex; 16 | 17 | py::object pack_ids (py::array_t idcpus, 18 | py::array_t ids) 19 | { 20 | if (idcpus.ndim() != 1) { 21 | throw std::runtime_error("Input should be 1-D NumPy array"); 22 | } 23 | 24 | auto buf = idcpus.request(); 25 | auto buf2 = ids.request(); 26 | if (buf.size != buf2.size) { 27 | throw std::runtime_error("sizes do not match!"); 28 | } 29 | 30 | int N = idcpus.shape()[0]; 31 | for (int i = 0; i < N; i++) { 32 | uint64_t* idcpus_ptr = (uint64_t*) buf.ptr; 33 | amrex::Long* ids_ptr = (amrex::Long*) buf2.ptr; 34 | particle_impl::pack_id(idcpus_ptr[i], ids_ptr[i]); 35 | } 36 | return py::cast(Py_None); 37 | } 38 | 39 | py::object pack_cpus (py::array_t idcpus, 40 | py::array_t cpus) 41 | { 42 | if (idcpus.ndim() != 1) { 43 | throw std::runtime_error("Input should be 1-D NumPy array"); 44 | } 45 | 46 | auto buf = idcpus.request(); 47 | auto buf2 = cpus.request(); 48 | if (buf.size != buf2.size) { 49 | throw std::runtime_error("sizes do not match!"); 50 | } 51 | 52 | int N = idcpus.shape()[0]; 53 | for (int i = 0; i < N; i++) { 54 | uint64_t* idcpus_ptr = (uint64_t*) buf.ptr; 55 | int* cpus_ptr = (int*) buf2.ptr; 56 | particle_impl::pack_cpu(idcpus_ptr[i], cpus_ptr[i]); 57 | } 58 | return py::cast(Py_None); 59 | } 60 | 61 | Long unpack_id (uint64_t idcpu) { 62 | return particle_impl::unpack_id(idcpu); 63 | } 64 | 65 | int unpack_cpu (uint64_t idcpu) { 66 | return particle_impl::unpack_cpu(idcpu); 67 | } 68 | 69 | uint64_t make_invalid (uint64_t idcpu) { 70 | particle_impl::make_invalid(idcpu); 71 | return idcpu; 72 | } 73 | 74 | uint64_t make_valid (uint64_t idcpu) { 75 | particle_impl::make_valid(idcpu); 76 | return idcpu; 77 | } 78 | 79 | bool is_valid (const uint64_t idcpu) { 80 | return particle_impl::is_valid(idcpu); 81 | } 82 | } 83 | 84 | // forward declarations 85 | void init_ParticleContainer_FHDeX(py::module& m); 86 | void init_ParticleContainer_ImpactX(py::module& m); 87 | void init_ParticleContainer_WarpX(py::module& m); 88 | 89 | void init_ParticleContainer(py::module& m) { 90 | using namespace amrex; 91 | 92 | // TODO: we might need to move all or most of the defines in here into a 93 | // test/example submodule, so they do not collide with downstream projects 94 | 95 | // most common case: ND particle + runtime attributes 96 | // pure SoA 97 | make_ParticleContainer_and_Iterators< 98 | SoAParticle, 99 | AMREX_SPACEDIM, 0 100 | >(m); 101 | // legacy AoS + SoA 102 | //make_ParticleContainer_and_Iterators, 0, 0>(m); 103 | 104 | // used in tests 105 | make_ParticleContainer_and_Iterators, 3, 1>(m); 106 | 107 | // application codes 108 | init_ParticleContainer_FHDeX(m); 109 | init_ParticleContainer_ImpactX(m); 110 | init_ParticleContainer_WarpX(m); 111 | 112 | // for particle idcpu arrays 113 | m.def("pack_ids", &pack_ids); 114 | m.def("pack_cpus", &pack_cpus); 115 | m.def("unpack_ids", py::vectorize(unpack_id)); 116 | m.def("unpack_cpus", py::vectorize(unpack_cpu)); 117 | m.def("make_invalid", make_invalid); 118 | m.def("make_valid", make_valid); 119 | m.def("is_valid", is_valid); 120 | } 121 | -------------------------------------------------------------------------------- /src/Particle/ParticleContainer_FHDeX.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2024 The AMReX Community 2 | * 3 | * Authors: Johannes Blaschke 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "ParticleContainer.H" 7 | 8 | #include 9 | #include 10 | 11 | 12 | void init_ParticleContainer_FHDeX(py::module& m) { 13 | using namespace amrex; 14 | 15 | make_ParticleContainer_and_Iterators, 0, 0>(m); 16 | } 17 | -------------------------------------------------------------------------------- /src/Particle/ParticleContainer_ImpactX.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2022 The AMReX Community 2 | * 3 | * Authors: Ryan Sandberg, Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "ParticleContainer.H" 7 | 8 | #include 9 | #include 10 | 11 | 12 | void init_ParticleContainer_ImpactX(py::module& m) { 13 | using namespace amrex; 14 | 15 | // TODO: we might need to move all or most of the defines in here into a 16 | // test/example submodule, so they do not collide with downstream projects 17 | make_ParticleContainer_and_Iterators, 8, 0>(m); // ImpactX 24.03+ 18 | } 19 | -------------------------------------------------------------------------------- /src/Particle/ParticleContainer_WarpX.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2022 The AMReX Community 2 | * 3 | * Authors: Ryan Sandberg, Axel Huebl 4 | * License: BSD-3-Clause-LBNL 5 | */ 6 | #include "ParticleContainer.H" 7 | 8 | #include 9 | 10 | 11 | void init_ParticleContainer_WarpX(py::module& m) { 12 | using namespace amrex; 13 | 14 | // TODO: we might need to move all or most of the defines in here into a 15 | // test/example submodule, so they do not collide with downstream projects 16 | #if AMREX_SPACEDIM == 1 17 | make_ParticleContainer_and_Iterators, 5, 0>(m); // WarpX 24.03+ 1D 18 | #elif AMREX_SPACEDIM == 2 19 | make_ParticleContainer_and_Iterators, 6, 0>(m); // WarpX 24.03+ 2D 20 | make_ParticleContainer_and_Iterators, 7, 0>(m); // WarpX 24.03+ RZ 21 | #elif AMREX_SPACEDIM == 3 22 | make_ParticleContainer_and_Iterators, 7, 0>(m); // WarpX 24.03+ 3D 23 | #endif 24 | } 25 | -------------------------------------------------------------------------------- /src/amrex/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # __version__ is TODO - only in spaceNd submodules 4 | __author__ = "Axel Huebl, Ryan T. Sandberg, Shreyas Ananthan, David P. Grote, Revathi Jambunathan, Edoardo Zoni, Remi Lehe, Andrew Myers, Weiqun Zhang" 5 | __license__ = "BSD-3-Clause-LBNL" 6 | -------------------------------------------------------------------------------- /src/amrex/extensions/ArrayOfStructs.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file is part of pyAMReX 3 | 4 | Copyright 2023 AMReX community 5 | Authors: Axel Huebl 6 | License: BSD-3-Clause-LBNL 7 | """ 8 | 9 | 10 | def aos_to_numpy(self, copy=False): 11 | """ 12 | Provide NumPy views into a ArrayOfStructs. 13 | 14 | Parameters 15 | ---------- 16 | self : amrex.ArrayOfStructs_* 17 | An ArrayOfStructs class in pyAMReX 18 | copy : bool, optional 19 | Copy the data if true, otherwise create a view (default). 20 | 21 | Returns 22 | ------- 23 | namedtuple 24 | A tuple with real and int components that are each lists 25 | of 1D NumPy arrays. 26 | """ 27 | import numpy as np 28 | 29 | if self.size() == 0: 30 | raise ValueError("AoS is empty.") 31 | 32 | if copy: 33 | # This supports a device-to-host copy. 34 | # 35 | # todo: validate of the to_host() returned object 36 | # lifetime is always managed correctly by 37 | # Python's GC - otherwise copy twice via copy=True 38 | return np.array(self.to_host(), copy=False) 39 | else: 40 | return np.array(self, copy=False) 41 | 42 | 43 | def aos_to_cupy(self, copy=False): 44 | """ 45 | Provide CuPy views into a ArrayOfStructs. 46 | 47 | Parameters 48 | ---------- 49 | self : amrex.ArrayOfStructs_* 50 | An ArrayOfStructs class in pyAMReX 51 | copy : bool, optional 52 | Copy the data if true, otherwise create a view (default). 53 | 54 | Returns 55 | ------- 56 | namedtuple 57 | A tuple with real and int components that are each lists 58 | of 1D NumPy arrays. 59 | 60 | Raises 61 | ------ 62 | ImportError 63 | Raises an exception if cupy is not installed 64 | """ 65 | import cupy as cp 66 | 67 | if self.size() == 0: 68 | raise ValueError("AoS is empty.") 69 | 70 | return cp.array(self, copy=copy) 71 | 72 | 73 | def aos_to_xp(self, copy=False): 74 | """ 75 | Provide NumPy or CuPy views into a ArrayOfStructs, depending on amr.Config.have_gpu . 76 | 77 | This function is similar to CuPy's xp naming suggestion for CPU/GPU agnostic code: 78 | https://docs.cupy.dev/en/stable/user_guide/basic.html#how-to-write-cpu-gpu-agnostic-code 79 | 80 | Parameters 81 | ---------- 82 | self : amrex.ArrayOfStructs_* 83 | An ArrayOfStructs class in pyAMReX 84 | copy : bool, optional 85 | Copy the data if true, otherwise create a view (default). 86 | 87 | Returns 88 | ------- 89 | namedtuple 90 | A tuple with real and int components that are each lists 91 | of 1D NumPy or CuPy arrays. 92 | """ 93 | import inspect 94 | 95 | amr = inspect.getmodule(self) 96 | return self.to_cupy(copy) if amr.Config.have_gpu else self.to_numpy(copy) 97 | 98 | 99 | def register_AoS_extension(amr): 100 | """ArrayOfStructs helper methods""" 101 | import inspect 102 | import sys 103 | 104 | # register member functions for every ArrayOfStructs_* type 105 | for _, AoS_type in inspect.getmembers( 106 | sys.modules[amr.__name__], 107 | lambda member: inspect.isclass(member) 108 | and member.__module__ == amr.__name__ 109 | and member.__name__.startswith("ArrayOfStructs_"), 110 | ): 111 | AoS_type.to_numpy = aos_to_numpy 112 | AoS_type.to_cupy = aos_to_cupy 113 | AoS_type.to_xp = aos_to_xp 114 | -------------------------------------------------------------------------------- /src/amrex/extensions/Iterator.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file is part of pyAMReX 3 | 4 | Copyright 2023 AMReX community 5 | Authors: Axel Huebl 6 | License: BSD-3-Clause-LBNL 7 | """ 8 | 9 | 10 | def next(self): 11 | """This is a helper function for the C++ equivalent of void operator++() 12 | 13 | In Python, iterators always are called with __next__, even for the 14 | first access. This means we need to handle the first iterator element 15 | explicitly, otherwise we will jump directly to the 2nd element. We do 16 | this the same way as pybind11 does this, via a little state: 17 | https://github.com/AMReX-Codes/pyamrex/pull/50 18 | https://github.com/AMReX-Codes/pyamrex/pull/262 19 | https://github.com/pybind/pybind11/blob/v2.10.0/include/pybind11/pybind11.h#L2269-L2282 20 | 21 | Important: we must NOT copy the AMReX iterator (unnecessary and expensive). 22 | 23 | self: the current iterator 24 | returns: the updated iterator 25 | """ 26 | if hasattr(self, "first_or_done") is False: 27 | self.first_or_done = True 28 | 29 | first_or_done = self.first_or_done 30 | if first_or_done: 31 | first_or_done = False 32 | self.first_or_done = first_or_done 33 | else: 34 | self._incr() 35 | if self.is_valid is False: 36 | self.first_or_done = True 37 | self.finalize() 38 | raise StopIteration 39 | 40 | return self 41 | -------------------------------------------------------------------------------- /src/amrex/extensions/PODVector.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file is part of pyAMReX 3 | 4 | Copyright 2023 AMReX community 5 | Authors: Axel Huebl 6 | License: BSD-3-Clause-LBNL 7 | """ 8 | 9 | 10 | def podvector_to_numpy(self, copy=False): 11 | """ 12 | Provide a NumPy view into a PODVector (e.g., RealVector, IntVector). 13 | 14 | Parameters 15 | ---------- 16 | self : amrex.PODVector_* 17 | A PODVector class in pyAMReX 18 | copy : bool, optional 19 | Copy the data if true, otherwise create a view (default). 20 | 21 | Returns 22 | ------- 23 | np.array 24 | A 1D NumPy array. 25 | """ 26 | import numpy as np 27 | 28 | if self.size() > 0: 29 | if copy: 30 | # This supports a device-to-host copy. 31 | # 32 | # todo: validate of the to_host() returned object 33 | # lifetime is always managed correctly by 34 | # Python's GC - otherwise copy twice via copy=True 35 | return np.array(self.to_host(), copy=False) 36 | else: 37 | return np.array(self, copy=False) 38 | else: 39 | raise ValueError("Vector is empty.") 40 | 41 | 42 | def podvector_to_cupy(self, copy=False): 43 | """ 44 | Provide a CuPy view into a PODVector (e.g., RealVector, IntVector). 45 | 46 | Parameters 47 | ---------- 48 | self : amrex.PODVector_* 49 | A PODVector class in pyAMReX 50 | copy : bool, optional 51 | Copy the data if true, otherwise create a view (default). 52 | 53 | Returns 54 | ------- 55 | cupy.array 56 | A 1D cupy array. 57 | 58 | Raises 59 | ------ 60 | ImportError 61 | Raises an exception if cupy is not installed 62 | """ 63 | import cupy as cp 64 | 65 | if self.size() > 0: 66 | return cp.array(self, copy=copy) 67 | else: 68 | raise ValueError("Vector is empty.") 69 | 70 | 71 | def podvector_to_xp(self, copy=False): 72 | """ 73 | Provide a NumPy or CuPy view into a PODVector (e.g., RealVector, IntVector), 74 | depending on amr.Config.have_gpu . 75 | 76 | This function is similar to CuPy's xp naming suggestion for CPU/GPU agnostic code: 77 | https://docs.cupy.dev/en/stable/user_guide/basic.html#how-to-write-cpu-gpu-agnostic-code 78 | 79 | Parameters 80 | ---------- 81 | self : amrex.PODVector_* 82 | A PODVector class in pyAMReX 83 | copy : bool, optional 84 | Copy the data if true, otherwise create a view (default). 85 | 86 | Returns 87 | ------- 88 | xp.array 89 | A 1D NumPy or CuPy array. 90 | """ 91 | import inspect 92 | 93 | amr = inspect.getmodule(self) 94 | return self.to_cupy(copy) if amr.Config.have_gpu else self.to_numpy(copy) 95 | 96 | 97 | def register_PODVector_extension(amr): 98 | """PODVector helper methods""" 99 | import inspect 100 | import sys 101 | 102 | # register member functions for every PODVector_* type 103 | for _, POD_type in inspect.getmembers( 104 | sys.modules[amr.__name__], 105 | lambda member: inspect.isclass(member) 106 | and member.__module__ == amr.__name__ 107 | and member.__name__.startswith("PODVector_"), 108 | ): 109 | POD_type.to_numpy = podvector_to_numpy 110 | POD_type.to_cupy = podvector_to_cupy 111 | POD_type.to_xp = podvector_to_xp 112 | -------------------------------------------------------------------------------- /src/amrex/extensions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AMReX-Codes/pyamrex/c9cec5c0743af5f14d9ed674e4e80ab9fcf153e3/src/amrex/extensions/__init__.py -------------------------------------------------------------------------------- /src/amrex/space1d/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | 5 | # Python 3.8+ on Windows: DLL search paths for dependent 6 | # shared libraries 7 | # Refs.: 8 | # - https://github.com/python/cpython/issues/80266 9 | # - https://docs.python.org/3.8/library/os.html#os.add_dll_directory 10 | if os.name == "nt": 11 | # add anything in the current directory 12 | pwd = __file__.rsplit(os.sep, 1)[0] + os.sep 13 | os.add_dll_directory(pwd) 14 | # add anything in PATH 15 | paths = os.environ.get("PATH", "") 16 | for p in paths.split(";"): 17 | p_abs = os.path.abspath(os.path.expanduser(os.path.expandvars(p))) 18 | if os.path.exists(p_abs): 19 | os.add_dll_directory(p_abs) 20 | 21 | # import core bindings to C++ 22 | from . import amrex_1d_pybind 23 | from .amrex_1d_pybind import * # noqa 24 | 25 | __version__ = amrex_1d_pybind.__version__ 26 | __doc__ = amrex_1d_pybind.__doc__ 27 | __license__ = amrex_1d_pybind.__license__ 28 | __author__ = amrex_1d_pybind.__author__ 29 | 30 | 31 | # at this place we can enhance Python classes with additional methods written 32 | # in pure Python or add some other Python logic 33 | # 34 | def d_decl(x, y, z): 35 | """Return a tuple of the first passed element""" 36 | return (x,) 37 | 38 | 39 | def Print(*args, **kwargs): 40 | """Wrap amrex::Print() - only the IO processor writes""" 41 | if not initialized(): # noqa 42 | print("warning: Print all - AMReX not initialized") 43 | print(*args, **kwargs) 44 | elif ParallelDescriptor.IOProcessor(): # noqa 45 | print(*args, **kwargs) 46 | 47 | 48 | from ..extensions.Array4 import register_Array4_extension 49 | from ..extensions.ArrayOfStructs import register_AoS_extension 50 | from ..extensions.MultiFab import register_MultiFab_extension 51 | from ..extensions.ParticleContainer import register_ParticleContainer_extension 52 | from ..extensions.PODVector import register_PODVector_extension 53 | from ..extensions.SmallMatrix import register_SmallMatrix_extension 54 | from ..extensions.StructOfArrays import register_SoA_extension 55 | 56 | register_Array4_extension(amrex_1d_pybind) 57 | register_MultiFab_extension(amrex_1d_pybind) 58 | register_PODVector_extension(amrex_1d_pybind) 59 | register_SmallMatrix_extension(amrex_1d_pybind) 60 | register_SoA_extension(amrex_1d_pybind) 61 | register_AoS_extension(amrex_1d_pybind) 62 | register_ParticleContainer_extension(amrex_1d_pybind) 63 | -------------------------------------------------------------------------------- /src/amrex/space1d/amrex_1d_pybind/ParallelDescriptor.pyi: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | __all__ = ["IOProcessor", "IOProcessorNumber", "MyProc", "NProcs"] 4 | 5 | def IOProcessor() -> bool: ... 6 | def IOProcessorNumber() -> int: ... 7 | def MyProc() -> int: ... 8 | def NProcs() -> int: ... 9 | -------------------------------------------------------------------------------- /src/amrex/space2d/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | 5 | # Python 3.8+ on Windows: DLL search paths for dependent 6 | # shared libraries 7 | # Refs.: 8 | # - https://github.com/python/cpython/issues/80266 9 | # - https://docs.python.org/3.8/library/os.html#os.add_dll_directory 10 | if os.name == "nt": 11 | # add anything in the current directory 12 | pwd = __file__.rsplit(os.sep, 1)[0] + os.sep 13 | os.add_dll_directory(pwd) 14 | # add anything in PATH 15 | paths = os.environ.get("PATH", "") 16 | for p in paths.split(";"): 17 | p_abs = os.path.abspath(os.path.expanduser(os.path.expandvars(p))) 18 | if os.path.exists(p_abs): 19 | os.add_dll_directory(p_abs) 20 | 21 | # import core bindings to C++ 22 | from . import amrex_2d_pybind 23 | from .amrex_2d_pybind import * # noqa 24 | 25 | __version__ = amrex_2d_pybind.__version__ 26 | __doc__ = amrex_2d_pybind.__doc__ 27 | __license__ = amrex_2d_pybind.__license__ 28 | __author__ = amrex_2d_pybind.__author__ 29 | 30 | 31 | # at this place we can enhance Python classes with additional methods written 32 | # in pure Python or add some other Python logic 33 | # 34 | def d_decl(x, y, z): 35 | """Return a tuple of the first two passed elements""" 36 | return (x, y) 37 | 38 | 39 | def Print(*args, **kwargs): 40 | """Wrap amrex::Print() - only the IO processor writes""" 41 | if not initialized(): # noqa 42 | print("warning: Print all - AMReX not initialized") 43 | print(*args, **kwargs) 44 | elif ParallelDescriptor.IOProcessor(): # noqa 45 | print(*args, **kwargs) 46 | 47 | 48 | from ..extensions.Array4 import register_Array4_extension 49 | from ..extensions.ArrayOfStructs import register_AoS_extension 50 | from ..extensions.MultiFab import register_MultiFab_extension 51 | from ..extensions.ParticleContainer import register_ParticleContainer_extension 52 | from ..extensions.PODVector import register_PODVector_extension 53 | from ..extensions.SmallMatrix import register_SmallMatrix_extension 54 | from ..extensions.StructOfArrays import register_SoA_extension 55 | 56 | register_Array4_extension(amrex_2d_pybind) 57 | register_MultiFab_extension(amrex_2d_pybind) 58 | register_PODVector_extension(amrex_2d_pybind) 59 | register_SmallMatrix_extension(amrex_2d_pybind) 60 | register_SoA_extension(amrex_2d_pybind) 61 | register_AoS_extension(amrex_2d_pybind) 62 | register_ParticleContainer_extension(amrex_2d_pybind) 63 | -------------------------------------------------------------------------------- /src/amrex/space2d/amrex_2d_pybind/ParallelDescriptor.pyi: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | __all__ = ["IOProcessor", "IOProcessorNumber", "MyProc", "NProcs"] 4 | 5 | def IOProcessor() -> bool: ... 6 | def IOProcessorNumber() -> int: ... 7 | def MyProc() -> int: ... 8 | def NProcs() -> int: ... 9 | -------------------------------------------------------------------------------- /src/amrex/space3d/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | 5 | # Python 3.8+ on Windows: DLL search paths for dependent 6 | # shared libraries 7 | # Refs.: 8 | # - https://github.com/python/cpython/issues/80266 9 | # - https://docs.python.org/3.8/library/os.html#os.add_dll_directory 10 | if os.name == "nt": 11 | # add anything in the current directory 12 | pwd = __file__.rsplit(os.sep, 1)[0] + os.sep 13 | os.add_dll_directory(pwd) 14 | # add anything in PATH 15 | paths = os.environ.get("PATH", "") 16 | for p in paths.split(";"): 17 | p_abs = os.path.abspath(os.path.expanduser(os.path.expandvars(p))) 18 | if os.path.exists(p_abs): 19 | os.add_dll_directory(p_abs) 20 | 21 | # import core bindings to C++ 22 | from . import amrex_3d_pybind 23 | from .amrex_3d_pybind import * # noqa 24 | 25 | __version__ = amrex_3d_pybind.__version__ 26 | __doc__ = amrex_3d_pybind.__doc__ 27 | __license__ = amrex_3d_pybind.__license__ 28 | __author__ = amrex_3d_pybind.__author__ 29 | 30 | 31 | # at this place we can enhance Python classes with additional methods written 32 | # in pure Python or add some other Python logic 33 | # 34 | def d_decl(x, y, z): 35 | """Return a tuple of the three passed elements""" 36 | return (x, y, z) 37 | 38 | 39 | def Print(*args, **kwargs): 40 | """Wrap amrex::Print() - only the IO processor writes""" 41 | if not initialized(): # noqa 42 | print("warning: Print all - AMReX not initialized") 43 | print(*args, **kwargs) 44 | elif ParallelDescriptor.IOProcessor(): # noqa 45 | print(*args, **kwargs) 46 | 47 | 48 | from ..extensions.Array4 import register_Array4_extension 49 | from ..extensions.ArrayOfStructs import register_AoS_extension 50 | from ..extensions.MultiFab import register_MultiFab_extension 51 | from ..extensions.ParticleContainer import register_ParticleContainer_extension 52 | from ..extensions.PODVector import register_PODVector_extension 53 | from ..extensions.SmallMatrix import register_SmallMatrix_extension 54 | from ..extensions.StructOfArrays import register_SoA_extension 55 | 56 | register_Array4_extension(amrex_3d_pybind) 57 | register_MultiFab_extension(amrex_3d_pybind) 58 | register_PODVector_extension(amrex_3d_pybind) 59 | register_SmallMatrix_extension(amrex_3d_pybind) 60 | register_SoA_extension(amrex_3d_pybind) 61 | register_AoS_extension(amrex_3d_pybind) 62 | register_ParticleContainer_extension(amrex_3d_pybind) 63 | -------------------------------------------------------------------------------- /src/amrex/space3d/amrex_3d_pybind/ParallelDescriptor.pyi: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | __all__ = ["IOProcessor", "IOProcessorNumber", "MyProc", "NProcs"] 4 | 5 | def IOProcessor() -> bool: ... 6 | def IOProcessorNumber() -> int: ... 7 | def MyProc() -> int: ... 8 | def NProcs() -> int: ... 9 | -------------------------------------------------------------------------------- /src/pyAMReX.H: -------------------------------------------------------------------------------- 1 | /* Copyright 2021-2023 The AMReX Community 2 | * 3 | * This header is used to centrally define classes that shall not violate the 4 | * C++ one-definition-rule (ODR) for various Python translation units. 5 | * 6 | * Authors: Axel Huebl 7 | * License: BSD-3-Clause-LBNL 8 | */ 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | //include 21 | 22 | namespace py = pybind11; 23 | 24 | //PYBIND11_MAKE_OPAQUE(std::list<...>) 25 | -------------------------------------------------------------------------------- /tests/parmparse_inputs: -------------------------------------------------------------------------------- 1 | param.dt = 1.e-5 2 | param.ncell = 100 3 | param.do_pml = 1 4 | -------------------------------------------------------------------------------- /tests/test_MPMD/test_1/GNUmakefile: -------------------------------------------------------------------------------- 1 | AMREX_HOME ?= ../../../../amrex 2 | 3 | DEBUG = TRUE 4 | 5 | DIM = 3 6 | 7 | COMP = gcc 8 | 9 | USE_MPI = TRUE 10 | 11 | USE_OMP = FALSE 12 | USE_CUDA = FALSE 13 | USE_HIP = FALSE 14 | 15 | include $(AMREX_HOME)/Tools/GNUMake/Make.defs 16 | 17 | include ./Make.package 18 | include $(AMREX_HOME)/Src/Base/Make.package 19 | 20 | include $(AMREX_HOME)/Tools/GNUMake/Make.rules 21 | -------------------------------------------------------------------------------- /tests/test_MPMD/test_1/Make.package: -------------------------------------------------------------------------------- 1 | CEXE_sources += main.cpp 2 | -------------------------------------------------------------------------------- /tests/test_MPMD/test_1/README.rst: -------------------------------------------------------------------------------- 1 | AMReX-MPMD 2 | ========== 3 | 4 | AMReX-MPMD utilizes the Multiple Program Multiple Data (MPMD) feature of MPI to provide cross-functionality for AMReX-based codes. 5 | 6 | Test 7 | ==== 8 | 9 | The current test leverages the AMReX-MPMD capability to perform a data (MultiFab) transfer between *main.cpp* and *main.py* scripts. 10 | The test is based on a two component MultiFab. The first component is populated in *main.cpp* before it is transferred to *main.py*. 11 | Then *main.py* script fills the second component based on the obtained first component value. 12 | Finally, the second component is transferred back from *main.py* to *main.cpp*. 13 | **This test requires MPI and mpi4py**. 14 | 15 | pyAMReX compile 16 | --------------- 17 | 18 | .. code-block:: bash 19 | 20 | # find dependencies & configure 21 | # Include -DAMReX_GPU_BACKEND=CUDA for gpu version 22 | cmake -S . -B build -DAMReX_SPACEDIM="1;2;3" -DAMReX_MPI=ON -DpyAMReX_amrex_src=/path/to/amrex 23 | 24 | # compile & install, here we use four threads 25 | cmake --build build -j 4 --target pip_install 26 | 27 | main.cpp compile 28 | ---------------- 29 | 30 | .. code-block:: bash 31 | 32 | # Include USE_CUDA=TRUE for gpu version 33 | make AMREX_HOME=/path/to/amrex -j 4 34 | 35 | Run 36 | --- 37 | 38 | Please note that MPI ranks attributed to each application/code need to be continuous, i.e., MPI ranks 0-7 are for *main.cpp* and 8-11 are for *main.py*. 39 | This may be default behaviour on several systems. 40 | 41 | .. code-block:: bash 42 | 43 | mpirun -np 8 ./main3d.gnu.DEBUG.MPI.ex : -np 4 python main.py 44 | -------------------------------------------------------------------------------- /tests/test_MPMD/test_1/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | // Initialize amrex::MPMD to establish communication across the two apps 12 | MPI_Comm comm = amrex::MPMD::Initialize(argc, argv); 13 | amrex::Initialize(argc,argv,true,comm); 14 | { 15 | amrex::Print() << "Hello world from AMReX version " << amrex::Version() << "\n"; 16 | // Number of data components at each grid point in the MultiFab 17 | int ncomp = 2; 18 | // how many grid cells in each direction over the problem domain 19 | int n_cell = 32; 20 | // how many grid cells are allowed in each direction over each box 21 | int max_grid_size = 16; 22 | //BoxArray -- Abstract Domain Setup 23 | // integer vector indicating the lower coordindate bounds 24 | amrex::IntVect dom_lo(0,0,0); 25 | // integer vector indicating the upper coordindate bounds 26 | amrex::IntVect dom_hi(n_cell-1, n_cell-1, n_cell-1); 27 | // box containing the coordinates of this domain 28 | amrex::Box domain(dom_lo, dom_hi); 29 | // will contain a list of boxes describing the problem domain 30 | amrex::BoxArray ba(domain); 31 | // chop the single grid into many small boxes 32 | ba.maxSize(max_grid_size); 33 | // Distribution Mapping 34 | amrex::DistributionMapping dm(ba); 35 | // Create an MPMD Copier that 36 | // sends the BoxArray information to the other (python) application 37 | auto copr = amrex::MPMD::Copier(ba,dm,true); 38 | //Define MuliFab 39 | amrex::MultiFab mf(ba, dm, ncomp, 0); 40 | //Geometry -- Physical Properties for data on our domain 41 | amrex::RealBox real_box ({0., 0., 0.}, {1. , 1., 1.}); 42 | amrex::Geometry geom(domain, &real_box); 43 | //Calculate Cell Sizes 44 | amrex::GpuArray dx = geom.CellSizeArray(); //dx[0] = dx dx[1] = dy dx[2] = dz 45 | //Fill only the first component of the MultiFab 46 | for(amrex::MFIter mfi(mf); mfi.isValid(); ++mfi){ 47 | const amrex::Box& bx = mfi.validbox(); 48 | const amrex::Array4& mf_array = mf.array(mfi); 49 | 50 | amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k){ 51 | 52 | amrex::Real x = (i+0.5) * dx[0]; 53 | amrex::Real y = (j+0.5) * dx[1]; 54 | amrex::Real z = (k+0.5) * dx[2]; 55 | amrex::Real r_squared = ((x-0.5)*(x-0.5)+(y-0.5)*(y-0.5)+(z-0.5)*(z-0.5))/0.01; 56 | 57 | mf_array(i,j,k,0) = 1.0 + std::exp(-r_squared); 58 | 59 | }); 60 | } 61 | // Send ONLY the first populated MultiFab component to the other app 62 | copr.send(mf,0,1); 63 | // Receive ONLY the second MultiFab component from the other app 64 | copr.recv(mf,1,1); 65 | // Cross-verification 66 | for(amrex::MFIter mfi(mf); mfi.isValid(); ++mfi){ 67 | const amrex::Box& bx = mfi.validbox(); 68 | const amrex::Array4& mf_array = mf.array(mfi); 69 | 70 | amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k){ 71 | 72 | mf_array(i,j,k,1) -= (amrex::Real(10.0)*mf_array(i,j,k,0)); 73 | 74 | }); 75 | } 76 | amrex::Real glb_max = amrex::Real(0.0); 77 | // Local Max 78 | for(amrex::MFIter mfi(mf); mfi.isValid(); ++mfi) { 79 | amrex::FArrayBox& fab = mf[mfi]; 80 | glb_max = amrex::max(glb_max,fab.maxabs(1)); 81 | } 82 | // Global Max 83 | amrex::ParallelAllReduce::Max(glb_max,comm); 84 | if (glb_max != amrex::Real(0.0)) { 85 | amrex::Abort("There appears to be a mismatch in data-ordering \n"); 86 | } 87 | } 88 | amrex::Finalize(); 89 | amrex::MPMD::Finalize(); 90 | } 91 | -------------------------------------------------------------------------------- /tests/test_MPMD/test_1/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright 2023 The AMReX Community 5 | # 6 | # This file is part of AMReX. 7 | # 8 | # License: BSD-3-Clause-LBNL 9 | # Authors: Bhargav Sriram Siddani, Revathi Jambunathan, Edoardo Zoni, Olga Shapoval, David Grote, Axel Huebl 10 | 11 | from mpi4py import MPI 12 | 13 | import amrex.space3d as amr 14 | 15 | # Initialize amrex::MPMD to establish communication across the two apps 16 | # However, leverage MPMD_Initialize_without_split 17 | # so that communication split can be performed using mpi4py.MPI 18 | amr.MPMD_Initialize_without_split([]) 19 | # Leverage MPI from mpi4py to perform communication split 20 | app_comm_py = MPI.COMM_WORLD.Split(amr.MPMD_AppNum(), amr.MPMD_MyProc()) 21 | # Initialize AMReX 22 | amr.initialize_when_MPMD([], app_comm_py) 23 | 24 | amr.Print(f"Hello world from pyAMReX version {amr.__version__}\n") 25 | # Create a MPMD Copier that gets the BoxArray information from the other (C++) app 26 | copr = amr.MPMD_Copier(True) 27 | # Number of data components at each grid point in the MultiFab 28 | ncomp = 2 29 | # Define a MultiFab using the created MPMD_Copier 30 | mf = amr.MultiFab(copr.box_array(), copr.distribution_map(), ncomp, 0) 31 | mf.set_val(0.0) 32 | 33 | # Receive ONLY the FIRST MultiFab component populated in the other (C++) app 34 | copr.recv(mf, 0, 1) 35 | 36 | # Fill the second MultiFab component based on the first component 37 | for mfi in mf: 38 | # Convert Array4 to numpy/cupy array 39 | mf_array = mf.array(mfi).to_xp(copy=False, order="F") 40 | mf_array[:, :, :, 1] = 10.0 * mf_array[:, :, :, 0] 41 | 42 | # Send ONLY the second MultiFab component to the other (C++) app 43 | copr.send(mf, 1, 1) 44 | 45 | # Finalize AMReX 46 | amr.finalize() 47 | # Finalize AMReX::MPMD 48 | amr.MPMD_Finalize() 49 | -------------------------------------------------------------------------------- /tests/test_aos.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | 5 | import amrex.space3d as amr 6 | 7 | 8 | def test_aos_init(): 9 | aos = amr.ArrayOfStructs_2_1_default() 10 | 11 | assert aos.numParticles() == 0 12 | assert aos.numTotalParticles() == aos.numRealParticles() == 0 13 | assert aos.empty() 14 | 15 | 16 | def test_aos_push_pop(): 17 | aos = ( 18 | amr.ArrayOfStructs_2_1_managed() 19 | if amr.Config.have_gpu 20 | else amr.ArrayOfStructs_2_1_default() 21 | ) 22 | p1 = amr.Particle_2_1() 23 | p1.set_rdata([1.5, 2.2]) 24 | p1.set_idata([3]) 25 | aos.push_back(p1) 26 | p2 = amr.Particle_2_1() 27 | p2.set_rdata([2.1, 25.2]) 28 | p2.set_idata([5]) 29 | aos.push_back(p2) 30 | 31 | ## test aos.back() 32 | pback = aos.back() 33 | assert np.allclose(pback.get_rdata(), p2.get_rdata()) 34 | assert np.allclose(pback.get_idata(), p2.get_idata()) 35 | assert pback.x == p2.x and pback.y == p2.y and pback.z == p2.z 36 | 37 | assert aos.numParticles() == aos.numTotalParticles() == aos.numRealParticles() == 2 38 | assert aos.getNumNeighbors() == 0 39 | aos.setNumNeighbors(5) 40 | assert aos.getNumNeighbors() == 5 41 | assert not aos.empty() 42 | assert aos.size() == 7 43 | assert aos[0].get_rdata() == p1.get_rdata() 44 | p3 = amr.Particle_2_1() 45 | p3.set_rdata([3.14, -3.14]) 46 | p3.set_idata([10]) 47 | aos[0] = p3 48 | assert aos[0].get_idata() == p3.get_idata() 49 | 50 | aos.pop_back() 51 | assert aos.numParticles() == aos.numRealParticles() == 1 52 | assert aos.numTotalParticles() == 6 53 | 54 | 55 | def test_array_interface(): 56 | aos = ( 57 | amr.ArrayOfStructs_2_1_managed() 58 | if amr.Config.have_gpu 59 | else amr.ArrayOfStructs_2_1_default() 60 | ) 61 | p1 = amr.Particle_2_1() 62 | p1.setPos([1, 2, 3]) 63 | p1.set_rdata([4.5, 5.2]) 64 | p1.set_idata([6]) 65 | aos.push_back(p1) 66 | p2 = amr.Particle_2_1() 67 | p2.setPos([8, 9, 10]) 68 | p2.set_rdata([11.1, 12.2]) 69 | p2.set_idata([13]) 70 | aos.push_back(p2) 71 | 72 | print(aos[0]) 73 | print(dir(aos[0])) 74 | 75 | # print('particle 1 from aos:\n',aos[0]) 76 | # print('particle 2 from aos:\n',aos[1]) 77 | # print('array interface\n', aos.__array_interface__) 78 | arr = aos.to_numpy() 79 | assert ( 80 | np.isclose(arr[0][0], 1.0) 81 | and np.isclose(arr[0][4], 5.2) 82 | and np.isclose(arr[0][6], 6) 83 | ) 84 | assert ( 85 | np.isclose(arr[1][2], 10) 86 | and np.isclose(arr[1][3], 11.1) 87 | and np.isclose(arr[1][6], 13) 88 | ) 89 | 90 | p3 = amr.Particle_2_1(x=-3) 91 | p4 = amr.Particle_2_1(y=-5) 92 | print(arr) 93 | print(aos[0], aos[1]) 94 | print("-------") 95 | aos[0] = p4 96 | assert aos[0].x == 0 97 | assert aos[0].y == -5 98 | aos[0] = p3 99 | print("array:", arr) 100 | print("aos[0]:", aos[0], "aos[1]:", aos[1]) 101 | assert aos[0].x == arr[0][0] == -3 102 | assert aos[0].y == arr[0][1] == 0 103 | assert aos[0].z == arr[0][2] == 0 104 | 105 | shape = amr.Config.spacedim + amr.Particle_2_1.NReal + amr.Particle_2_1.NInt + 1 106 | for ii in range(shape): 107 | arr[1][ii] = 0 108 | arr[1][1] = -5 # np.array([0, -5, 0,0,0,0,0]) 109 | print("array:", arr) 110 | print("aos[0]:", aos[0], "aos[1]:", aos[1]) 111 | assert aos[1].y == arr[1][1] == -5 112 | assert aos[1].x == arr[1][0] == 0 113 | assert aos[1].z == arr[1][2] == 0 114 | -------------------------------------------------------------------------------- /tests/test_array4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | import amrex.space3d as amr 7 | 8 | 9 | def test_array4_empty(): 10 | empty = amr.Array4_double() 11 | 12 | # Check properties 13 | assert empty.size == 0 14 | assert empty.nComp == 0 15 | 16 | # assign empty 17 | emptyc = amr.Array4_double(empty) 18 | # Check properties 19 | assert emptyc.size == 0 20 | assert emptyc.nComp == 0 21 | 22 | 23 | def test_array4(): 24 | # from numpy (also a non-owning view) 25 | x = np.ones( 26 | ( 27 | 2, 28 | 3, 29 | 4, 30 | ) 31 | ) 32 | print(f"\nx: {x.__array_interface__} {x.dtype}") 33 | arr = amr.Array4_double(x) 34 | print(f"arr: {arr.__array_interface__}") 35 | print(arr) 36 | assert arr.nComp == 1 37 | 38 | # change original array 39 | x[1, 1, 1] = 42 40 | # check values in Array4 view changed 41 | assert arr[1, 1, 1] == 42 42 | assert arr[1, 1, 1, 0] == 42 # with component 43 | # check existing values stayed 44 | assert arr[0, 0, 0] == 1 45 | assert arr[3, 2, 1] == 1 46 | 47 | # copy to numpy 48 | c_arr2np = np.array(arr, copy=True) # segfaults on Windows 49 | assert c_arr2np.ndim == 4 50 | assert c_arr2np.dtype == np.dtype("double") 51 | print(f"c_arr2np: {c_arr2np.__array_interface__}") 52 | np.testing.assert_array_equal(x, c_arr2np[0, :, :, :]) 53 | assert c_arr2np[0, 1, 1, 1] == 42 54 | 55 | # view to numpy 56 | v_arr2np = np.array(arr, copy=False) 57 | assert c_arr2np.ndim == 4 58 | assert v_arr2np.dtype == np.dtype("double") 59 | np.testing.assert_array_equal(x, v_arr2np[0, :, :, :]) 60 | assert v_arr2np[0, 1, 1, 1] == 42 61 | 62 | # change original buffer once more 63 | x[1, 1, 1] = 43 64 | assert v_arr2np[0, 1, 1, 1] == 43 65 | 66 | # copy array4 (view) 67 | c_arr = amr.Array4_double(arr) 68 | v_carr2np = np.array(c_arr, copy=False) 69 | x[1, 1, 1] = 44 70 | assert v_carr2np[0, 1, 1, 1] == 44 71 | 72 | 73 | @pytest.mark.skipif( 74 | amr.Config.gpu_backend != "CUDA", reason="Requires AMReX_GPU_BACKEND=CUDA" 75 | ) 76 | def test_array4_numba(): 77 | # https://numba.pydata.org/numba-doc/dev/cuda/cuda_array_interface.html 78 | from numba import cuda 79 | 80 | # numba -> AMReX Array4 81 | x = np.ones( 82 | ( 83 | 2, 84 | 3, 85 | 4, 86 | ) 87 | ) # type: numpy.ndarray 88 | 89 | # host-to-device copy 90 | x_numba = cuda.to_device(x) # noqa 91 | # type is numba.cuda.cudadrv.devicearray.DeviceNDArray 92 | # x_cupy = cupy.asarray(x_numba) 93 | # type is cupy.ndarray 94 | 95 | # TODO: Implement __cuda_array_interface__ or DLPack in Array4 constructor 96 | # x_arr = amr.Array4_double(x_numba) # type: amr.Array4_double 97 | 98 | # assert ( 99 | # x_arr.__cuda_array_interface__["data"][0] 100 | # == x_numba.__cuda_array_interface__["data"][0] 101 | # ) 102 | 103 | 104 | @pytest.mark.skipif( 105 | amr.Config.gpu_backend != "CUDA", reason="Requires AMReX_GPU_BACKEND=CUDA" 106 | ) 107 | def test_array4_cupy(): 108 | # https://docs.cupy.dev/en/stable/user_guide/interoperability.html 109 | import cupy as cp 110 | 111 | # cupy -> AMReX Array4 112 | x = np.ones( 113 | ( 114 | 2, 115 | 3, 116 | 4, 117 | ) 118 | ) # TODO: merge into next line and create on device? 119 | x_cupy = cp.asarray(x) # type: cupy.ndarray 120 | print(f"x_cupy={x_cupy}") 121 | print(x_cupy.__cuda_array_interface__) 122 | 123 | # TODO: Implement __cuda_array_interface__ or DLPack in Array4 constructor 124 | # cupy -> AMReX array4 125 | # x_arr = amr.Array4_double(x_cupy) # type: amr.Array4_double 126 | # print(f"x_arr={x_arr}") 127 | # print(x_arr.__cuda_array_interface__) 128 | 129 | # assert ( 130 | # x_arr.__cuda_array_interface__["data"][0] 131 | # == x_cupy.__cuda_array_interface__["data"][0] 132 | # ) 133 | 134 | 135 | @pytest.mark.skipif( 136 | amr.Config.gpu_backend != "CUDA", reason="Requires AMReX_GPU_BACKEND=CUDA" 137 | ) 138 | def test_array4_pytorch(): 139 | # https://docs.cupy.dev/en/stable/user_guide/interoperability.html#pytorch 140 | # arr_torch = torch.as_tensor(arr, device='cuda') 141 | # assert(arr_torch.__cuda_array_interface__['data'][0] == arr.__cuda_array_interface__['data'][0]) 142 | # TODO 143 | 144 | pass 145 | -------------------------------------------------------------------------------- /tests/test_basefab.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | 5 | import amrex.space3d as amr 6 | 7 | 8 | def test_basefab(): 9 | bf = amr.BaseFab_Real() # noqa 10 | 11 | 12 | def test_basefab_to_host(): 13 | box = amr.Box((0, 0, 0), (127, 127, 127)) 14 | bf = amr.BaseFab_Real(box, 2, amr.The_Arena()) 15 | 16 | host_bf = bf.to_host() 17 | x1 = np.array(host_bf, copy=False) 18 | x2 = np.array(host_bf.array(), copy=False) 19 | 20 | np.testing.assert_allclose(x1, x2) 21 | -------------------------------------------------------------------------------- /tests/test_box.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | import amrex.space3d as amr 7 | 8 | 9 | @pytest.fixture(scope="function") 10 | def box(): 11 | return amr.Box((0, 0, 0), (127, 127, 127)) 12 | 13 | 14 | def test_box_setget(box): 15 | print(box.length()) 16 | print(box.numPts()) 17 | assert box.numPts() == 128 * 128 * 128 18 | 19 | box.small_end = amr.IntVect(3) 20 | assert box.numPts() == 125 * 125 * 125 21 | 22 | box.big_end = amr.IntVect(40) 23 | assert box.numPts() == 38 * 38 * 38 24 | 25 | 26 | def test_length(box): 27 | print(box.length()) 28 | assert box.length() == amr.IntVect(128, 128, 128) 29 | 30 | domain = box.length() 31 | ncells = 1 32 | for ii in range(amr.Config.spacedim): 33 | ncells *= domain[ii] 34 | print("ncells by hand", ncells) 35 | print("ncells from box", box.numPts()) 36 | assert ncells == box.numPts() 37 | 38 | 39 | def test_num_pts(box): 40 | np.testing.assert_allclose(box.lo_vect, [0, 0, 0]) 41 | np.testing.assert_allclose(box.hi_vect, [127, 127, 127]) 42 | assert box.num_pts == 2**21 43 | assert box.volume == 2**21 44 | 45 | 46 | def test_grow(box): 47 | """box.grow""" 48 | bx = box.grow(3) 49 | np.testing.assert_allclose(bx.lo_vect, [-3, -3, -3]) 50 | np.testing.assert_allclose(bx.hi_vect, [130, 130, 130]) 51 | assert bx.num_pts == (134**3) 52 | 53 | 54 | def test_slab(box): 55 | """box.make_slab""" 56 | box.make_slab(direction=2, slab_index=60) 57 | np.testing.assert_allclose(box.lo_vect, [0, 0, 60]) 58 | np.testing.assert_allclose(box.hi_vect, [127, 127, 60]) 59 | assert box.num_pts == (128 * 128 * 1) 60 | 61 | 62 | # def test_convert(box): 63 | # """Conversion to node""" 64 | # bx = box.convert(amr.CellIndex.NODE, amr.CellIndex.NODE, amr.CellIndex.NODE) 65 | # assert(bx.num_pts == 129**3) 66 | # assert(bx.volume == 128**3) 67 | 68 | # bx = box.convert(amr.CellIndex.NODE, amr.CellIndex.CELL, amr.CellIndex.CELL) 69 | # np.testing.assert_allclose(bx.hi_vect, [128, 127, 127]) 70 | # assert(bx.num_pts == 129 * 128 * 128) 71 | # assert(bx.volume == 128**3) 72 | 73 | 74 | @pytest.mark.parametrize("dir", [None, 0, 1, 2]) 75 | def test_surrounding_nodes(box, dir): 76 | """Surrounding nodes""" 77 | nx = np.array(box.hi_vect) 78 | 79 | if dir is None: 80 | bx = box.surrounding_nodes() 81 | assert bx.num_pts == 129**3 82 | assert bx.volume == 128**3 83 | nx += 1 84 | np.testing.assert_allclose(bx.hi_vect, nx) 85 | else: 86 | bx = box.surrounding_nodes(dir=dir) 87 | assert bx.num_pts == 129 * 128 * 128 88 | assert bx.volume == 128**3 89 | nx[dir] += 1 90 | np.testing.assert_allclose(bx.hi_vect, nx) 91 | 92 | 93 | ''' 94 | @pytest.mark.parametrize("dir", [-1, 0, 1, 2]) 95 | def test_enclosed_cells(box, dir): 96 | """Enclosed cells""" 97 | bxn = box.convert(amr.CellIndex.NODE, amr.CellIndex.NODE, amr.CellIndex.NODE) 98 | nx = np.array(bxn.hi_vect) 99 | bx = bxn.enclosed_cells(dir) 100 | 101 | if dir < 0: 102 | assert(bx.num_pts == 128**3) 103 | assert(bx.volume == 128**3) 104 | nx -= 1 105 | np.testing.assert_allclose(bx.hi_vect, nx) 106 | else: 107 | assert(bx.num_pts == 129 * 129 * 128) 108 | assert(bx.volume == 128**3) 109 | nx[dir] -= 1 110 | np.testing.assert_allclose(bx.hi_vect, nx) 111 | ''' 112 | -------------------------------------------------------------------------------- /tests/test_boxarray.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import amrex.space3d as amr 4 | 5 | 6 | def test_boxarray(std_box): 7 | ba = amr.BoxArray(std_box) 8 | 9 | assert ba.size == 1 10 | ba.max_size(32) 11 | assert ba.size == 8 12 | 13 | assert not ba.empty 14 | assert ba.numPts == 64**3 15 | 16 | 17 | def test_boxarray_empty(): 18 | ba = amr.BoxArray() 19 | 20 | assert ba.size == 0 21 | assert ba.empty 22 | assert ba.numPts == 0 23 | 24 | 25 | def test_boxarray_list(): 26 | bx_1 = amr.Box(amr.IntVect(0, 0, 0), amr.IntVect(31, 31, 31)) 27 | bx_2 = amr.Box(amr.IntVect(32, 32, 32), amr.IntVect(63, 63, 63)) 28 | bx_3 = amr.Box(amr.IntVect(64, 64, 64), amr.IntVect(95, 95, 95)) 29 | 30 | box_list = amr.Vector_Box([bx_1, bx_2, bx_3]) 31 | ba = amr.BoxArray(box_list) 32 | print(ba) 33 | 34 | assert ba.size == 3 35 | assert not ba.empty 36 | assert ba.numPts == 98304 37 | 38 | print(ba.d_numPts) 39 | print(ba.ix_type()) 40 | -------------------------------------------------------------------------------- /tests/test_coordsys.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import amrex.space3d as amr 4 | 5 | # import amrex.space3d as amr.CoordSys.CoordType as CoordType 6 | 7 | 8 | def test_coordSys_coordType(): 9 | CType = amr.CoordSys.CoordType 10 | cs = amr.CoordSys() 11 | 12 | print(cs.ok()) 13 | assert not cs.ok() 14 | print(cs.Coord()) 15 | assert cs.Coord() == CType.undef 16 | print(cs.CoordInt()) 17 | assert cs.CoordInt() == -1 18 | 19 | cs.SetCoord(CType.cartesian) 20 | assert cs.Coord() == CType.cartesian 21 | assert cs.CoordInt() == 0 22 | 23 | cs.SetCoord(CType.RZ) 24 | assert cs.Coord() == CType.RZ 25 | assert cs.CoordInt() == 1 26 | 27 | cs.SetCoord(CType.SPHERICAL) 28 | assert cs.Coord() == CType.SPHERICAL 29 | assert cs.CoordInt() == 2 30 | -------------------------------------------------------------------------------- /tests/test_dim3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | 5 | import amrex.space3d as amr 6 | 7 | 8 | def test_dim3(): 9 | obj = amr.Dim3(1, 2, 3) 10 | assert obj.x == 1 11 | assert obj.y == 2 12 | assert obj.z == 3 13 | 14 | 15 | def test_xdim3(): 16 | obj = amr.XDim3(1.0, 2.0, 3.0) 17 | np.testing.assert_allclose(obj.x, 1.0) 18 | np.testing.assert_allclose(obj.y, 2.0) 19 | np.testing.assert_allclose(obj.z, 3.0) 20 | -------------------------------------------------------------------------------- /tests/test_farraybox.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import amrex.space3d as amr 4 | 5 | 6 | def test_farraybox(): 7 | fab = amr.FArrayBox() # noqa 8 | 9 | 10 | def test_farraybox_io(): 11 | fab = amr.FArrayBox() # noqa 12 | 13 | # https://docs.python.org/3/library/io.html 14 | # https://gist.github.com/asford/544323a5da7dddad2c9174490eb5ed06#file-test_ostream_example-py 15 | # import io 16 | # iob = io.BytesIO() 17 | # assert iob.getvalue() == b"..." 18 | # fab.read_from(iob) 19 | -------------------------------------------------------------------------------- /tests/test_indextype.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import pytest 4 | 5 | import amrex.space3d as amr 6 | 7 | 8 | @pytest.mark.skipif(amr.Config.spacedim != 1, reason="Requires AMREX_SPACEDIM = 1") 9 | def test_indextype_1d(): 10 | obj = amr.IndexType(amr.IndexType.CellIndex.NODE) 11 | assert obj.node_centered() 12 | assert not obj.cell_centered() 13 | with pytest.raises(IndexError): 14 | obj[-2] 15 | with pytest.raises(IndexError): 16 | obj[1] 17 | 18 | 19 | @pytest.mark.skipif(amr.Config.spacedim != 2, reason="Requires AMREX_SPACEDIM = 2") 20 | def test_indextype_2d(): 21 | obj = amr.IndexType(amr.IndexType.CellIndex.NODE, amr.IndexType.CellIndex.CELL) 22 | assert obj.node_centered(0) 23 | assert obj.cell_centered(1) 24 | assert obj.node_centered(-2) 25 | assert obj.cell_centered(-1) 26 | 27 | with pytest.raises(IndexError): 28 | obj[-3] 29 | with pytest.raises(IndexError): 30 | obj[2] 31 | 32 | 33 | @pytest.mark.skipif(amr.Config.spacedim != 3, reason="Requires AMREX_SPACEDIM = 3") 34 | def test_indextype_3d(): 35 | obj = amr.IndexType( 36 | amr.IndexType.CellIndex.NODE, 37 | amr.IndexType.CellIndex.CELL, 38 | amr.IndexType.CellIndex.NODE, 39 | ) 40 | 41 | # Check indexing 42 | assert obj.node_centered(0) 43 | assert obj.cell_centered(1) 44 | assert obj.node_centered(2) 45 | assert obj.node_centered(-3) 46 | assert obj.cell_centered(-2) 47 | assert obj.node_centered(-1) 48 | with pytest.raises(IndexError): 49 | obj[-4] 50 | with pytest.raises(IndexError): 51 | obj[3] 52 | 53 | # Check methods 54 | obj.set(1) 55 | assert obj.node_centered() 56 | obj.unset(1) 57 | assert not obj.node_centered() 58 | 59 | 60 | def test_indextype_static(): 61 | cell = amr.IndexType.cell_type() 62 | for i in range(amr.Config.spacedim): 63 | assert not cell.test(i) 64 | 65 | node = amr.IndexType.node_type() 66 | for i in range(amr.Config.spacedim): 67 | assert node[i] 68 | 69 | assert cell == amr.IndexType.cell_type() 70 | assert node == amr.IndexType.node_type() 71 | assert cell < node 72 | 73 | 74 | def test_indextype_conversions(): 75 | node = amr.IndexType.node_type() 76 | assert node.ix_type() == amr.IntVect(1) 77 | assert node.to_IntVect() == amr.IntVect(1) 78 | -------------------------------------------------------------------------------- /tests/test_intvect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | import amrex.space3d as amr 7 | 8 | 9 | @pytest.mark.skipif(amr.Config.spacedim != 1, reason="Requires AMREX_SPACEDIM = 1") 10 | def test_iv_1d(): 11 | obj = amr.IntVect(1) 12 | assert obj[0] == 1 13 | assert obj[-1] == 1 14 | with pytest.raises(IndexError): 15 | obj[-2] 16 | with pytest.raises(IndexError): 17 | obj[1] 18 | 19 | 20 | @pytest.mark.skipif(amr.Config.spacedim != 2, reason="Requires AMREX_SPACEDIM = 2") 21 | def test_iv_2d(): 22 | obj = amr.IntVect(1, 2) 23 | assert obj[0] == 1 24 | assert obj[1] == 2 25 | assert obj[-1] == 3 26 | assert obj[-2] == 2 27 | 28 | with pytest.raises(IndexError): 29 | obj[-3] 30 | with pytest.raises(IndexError): 31 | obj[2] 32 | 33 | 34 | @pytest.mark.skipif(amr.Config.spacedim != 3, reason="Requires AMREX_SPACEDIM = 3") 35 | def test_iv_3d1(): 36 | obj = amr.IntVect(1, 2, 3) 37 | 38 | # Check indexing 39 | assert obj[0] == 1 40 | assert obj[1] == 2 41 | assert obj[2] == 3 42 | assert obj[-1] == 3 43 | assert obj[-2] == 2 44 | assert obj[-3] == 1 45 | with pytest.raises(IndexError): 46 | obj[-4] 47 | with pytest.raises(IndexError): 48 | obj[3] 49 | 50 | # Check properties 51 | assert obj.max == 3 52 | assert obj.min == 1 53 | assert obj.sum == 6 54 | 55 | # Check assignment 56 | obj[0] = 2 57 | obj[1] = 3 58 | obj[2] = 4 59 | assert obj[0] == 2 60 | assert obj[1] == 3 61 | assert obj[2] == 4 62 | 63 | 64 | @pytest.mark.skipif(amr.Config.spacedim != 3, reason="Requires AMREX_SPACEDIM = 3") 65 | def test_iv_3d2(): 66 | obj = amr.IntVect(3) 67 | assert obj[0] == 3 68 | assert obj[1] == 3 69 | assert obj[2] == 3 70 | assert obj[-1] == 3 71 | assert obj[-2] == 3 72 | assert obj[-3] == 3 73 | 74 | with pytest.raises(IndexError): 75 | obj[-4] 76 | with pytest.raises(IndexError): 77 | obj[3] 78 | 79 | obj = amr.IntVect([2, 3, 4]) 80 | assert obj[0] == 2 81 | assert obj[1] == 3 82 | assert obj[2] == 4 83 | 84 | 85 | def test_iv_static(): 86 | zero = amr.IntVect.zero_vector() 87 | for i in range(amr.Config.spacedim): 88 | assert zero[i] == 0 89 | 90 | one = amr.IntVect.unit_vector() 91 | for i in range(amr.Config.spacedim): 92 | assert one[i] == 1 93 | 94 | assert zero == amr.IntVect.cell_vector() 95 | assert one == amr.IntVect.node_vector() 96 | 97 | 98 | def test_iv_ops(): 99 | gold = amr.IntVect(2) 100 | one = amr.IntVect.unit_vector() 101 | 102 | two = one + one 103 | assert two == gold 104 | assert two != amr.IntVect.zero_vector() 105 | assert two > one 106 | assert two >= gold 107 | assert one < two 108 | assert one <= one 109 | 110 | assert not (one > two) 111 | 112 | zero = one - one 113 | assert zero == amr.IntVect.zero_vector() 114 | 115 | mtwo = one * gold 116 | assert two == mtwo 117 | 118 | four = amr.IntVect(4) 119 | dtwo = four / gold 120 | assert dtwo == mtwo 121 | 122 | 123 | def test_iv_conversions(): 124 | obj = amr.IntVect.max_vector().numpy() 125 | assert isinstance(obj, np.ndarray) 126 | assert obj.dtype == np.int32 127 | 128 | # check that memory is not collected too early 129 | iv = amr.IntVect(2) 130 | obj = iv.numpy() 131 | del iv 132 | assert obj[0] == 2 133 | 134 | 135 | def test_iv_iter(): 136 | a0 = amr.IntVect(4) 137 | b0 = amr.IntVect(2) 138 | 139 | a1 = [x // 2 for x in a0] 140 | b1 = [x for x in b0] 141 | 142 | np.testing.assert_allclose(a1, b1) 143 | 144 | 145 | def test_iv_d_decl(): 146 | iv = amr.IntVect(*amr.d_decl(1, 2, 3)) 147 | assert iv == amr.IntVect(1, 2, 3) 148 | -------------------------------------------------------------------------------- /tests/test_parmparse.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | 4 | import amrex.space3d as amr 5 | 6 | 7 | def test_parmparse(): 8 | pp = amr.ParmParse("") 9 | dir_name = os.path.dirname(__file__) 10 | pp.addfile(os.path.join(dir_name, "parmparse_inputs")) 11 | pp_param = amr.ParmParse("param") 12 | _, ncell = pp_param.query_int("ncell") 13 | dt = pp_param.get_real("dt") 14 | dopml = pp_param.get_bool("do_pml") 15 | 16 | assert dopml 17 | assert dt == 1.0e-5 18 | assert ncell == 100 19 | 20 | pp.pretty_print_table() 21 | -------------------------------------------------------------------------------- /tests/test_particle.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | import amrex.space3d as amr 7 | 8 | 9 | def test_particle_init(): 10 | p1 = amr.Particle_8_0() 11 | print(p1) 12 | 13 | p2 = amr.Particle_8_0(1.0, 2.0, 3.0) 14 | assert p2.x == 1.0 and p2.y == 2.0 and p2.z == 3.0 15 | 16 | p3 = amr.Particle_8_0(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0) 17 | assert p3.x == 1.0 and p3.get_rdata(0) == 4.0 and p3.get_rdata(6) == 10.0 18 | 19 | p4 = amr.Particle_8_0(1.0, 2.0, 3.0, rdata_0=4.0) 20 | assert ( 21 | p4.x == 1.0 22 | and p4.z == 3.0 23 | and p4.get_rdata(0) == 4.0 24 | and p4.get_rdata(1) == 0 == p4.get_rdata(2) == p4.get_rdata(3) 25 | ) 26 | 27 | p5 = amr.Particle_8_0(x=1.0, rdata_1=1.0, rdata_3=3.0) 28 | assert ( 29 | p5.x == 1.0 30 | and p5.get_rdata(1) == 1.0 31 | and p5.get_rdata(3) == 3.0 32 | and p5.get_rdata(4) == 0 33 | ) 34 | 35 | 36 | @pytest.mark.skipif(amr.Config.spacedim != 3, reason="Requires AMREX_SPACEDIM = 3") 37 | def test_particle_set(): 38 | p1 = amr.Particle_8_0() 39 | p1.setPos(1, 1.5) 40 | assert p1.pos(0) == 0 and p1.pos(1) == 1.5 and p1.pos(2) == 0 41 | p1.setPos([1.0, 1, 2]) 42 | assert p1.pos(0) == 1 and p1.pos(1) == 1 and p1.pos(2) == 2 43 | p1.setPos(amr.RealVect(2, 3.3, 4.2)) 44 | assert p1.pos(0) == 2 and p1.pos(1) == 3.3 and p1.pos(2) == 4.2 45 | 46 | print(p1.x, p1.y, p1.z) 47 | p1.x = 2.1 48 | assert p1.x == 2.1 49 | p1.y = 3.2 50 | assert p1.y == 3.2 51 | p1.z = 5.1 52 | assert p1.z == 5.1 53 | 54 | 55 | def test_rdata(): 56 | p1 = amr.Particle_2_1() 57 | rvec = [1.5, 2.0] 58 | p1.set_rdata(rvec) 59 | assert np.allclose(p1.get_rdata(), rvec) 60 | p1.set_rdata(1, 2.5) 61 | assert np.allclose(p1.get_rdata(1), 2.5) 62 | 63 | with pytest.raises(ValueError): 64 | p1.set_rdata(100, 5.2) 65 | 66 | with pytest.raises(ValueError): 67 | p1.get_rdata(100) 68 | 69 | 70 | def test_idata(): 71 | p1 = amr.Particle_2_1() 72 | ivec = [-1] 73 | p1.set_idata(ivec) 74 | assert p1.get_idata() == ivec 75 | p1.set_idata(0, 3) 76 | assert p1.get_idata(0) == 3 77 | with pytest.raises(ValueError): 78 | p1.set_idata(100, 5) 79 | 80 | with pytest.raises(ValueError): 81 | p1.get_idata(100) 82 | -------------------------------------------------------------------------------- /tests/test_periodicity.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import pytest 4 | 5 | import amrex.space3d as amr 6 | 7 | 8 | def test_periodicity(): 9 | obj = amr.Periodicity() 10 | assert not obj.is_any_periodic 11 | assert not obj.is_all_periodic 12 | assert not obj.is_periodic(0) 13 | assert not obj[0] 14 | # with pytest.raises(IndexError): 15 | # obj[3] 16 | 17 | non_periodic = amr.Periodicity.non_periodic() 18 | assert obj == non_periodic 19 | 20 | 21 | @pytest.mark.skipif(amr.Config.spacedim == 3, reason="Requires AMREX_SPACEDIM = 3") 22 | def test_periodicity_3d(): 23 | iv = amr.IntVect(1, 0, 1) 24 | obj = amr.Periodicity(iv) 25 | assert obj.is_any_periodic 26 | assert not obj.is_all_periodic 27 | assert obj.is_periodic(0) 28 | assert not obj.is_periodic(1) 29 | assert obj.is_periodic(2) 30 | assert obj[2] 31 | 32 | bx = obj.domain 33 | print(bx) 34 | v_iv = obj.shift_IntVect 35 | print(v_iv) 36 | -------------------------------------------------------------------------------- /tests/test_plotfiledata.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | import amrex.space3d as amr 7 | 8 | 9 | def write_test_plotfile(filename): 10 | """Write single-level plotfile (in order to read it back in).""" 11 | domain_box = amr.Box([0, 0, 0], [31, 31, 31]) 12 | real_box = amr.RealBox([-0.5, -0.5, -0.5], [0.5, 0.5, 0.5]) 13 | geom = amr.Geometry(domain_box, real_box, amr.CoordSys.cartesian, [0, 0, 0]) 14 | 15 | ba = amr.BoxArray(domain_box) 16 | dm = amr.DistributionMapping(ba, 1) 17 | mf = amr.MultiFab(ba, dm, 1, 0) 18 | mf.set_val(np.pi) 19 | 20 | time = 1.0 21 | level_step = 200 22 | var_names = amr.Vector_string(["density"]) 23 | amr.write_single_level_plotfile(filename, mf, var_names, geom, time, level_step) 24 | 25 | 26 | @pytest.mark.skipif(amr.Config.spacedim != 3, reason="Requires AMREX_SPACEDIM = 3") 27 | def test_plotfiledata_read(): 28 | """Generate and then read plotfile using PlotFileUtil bindings.""" 29 | plt_filename = "test_plt00200" 30 | write_test_plotfile(plt_filename) 31 | plt = amr.PlotFileData(plt_filename) 32 | 33 | assert plt.spaceDim() == 3 34 | assert plt.time() == 1.0 35 | assert plt.finestLevel() == 0 36 | assert plt.refRatio(0) == 0 37 | assert plt.coordSys() == amr.CoordSys.cartesian 38 | 39 | probDomain = plt.probDomain(0) 40 | probSize = plt.probSize() 41 | probLo = plt.probLo() 42 | probHi = plt.probHi() 43 | cellSize = plt.cellSize(0) 44 | varNames = plt.varNames() 45 | nComp = plt.nComp() 46 | nGrowVect = plt.nGrowVect(0) 47 | 48 | assert probDomain.small_end == amr.IntVect(0, 0, 0) 49 | assert probDomain.big_end == amr.IntVect(31, 31, 31) 50 | 51 | assert probSize == [1.0, 1.0, 1.0] 52 | assert probLo == [-0.5, -0.5, -0.5] 53 | assert probHi == [0.5, 0.5, 0.5] 54 | assert cellSize == [1.0 / 32.0, 1.0 / 32.0, 1.0 / 32.0] 55 | assert varNames == amr.Vector_string(["density"]) 56 | assert nComp == 1 57 | assert nGrowVect == amr.IntVect(0, 0, 0) 58 | 59 | for compname in varNames: 60 | mfab_comp = plt.get(0, compname) 61 | nboxes = 0 62 | 63 | for mfi in mfab_comp: 64 | marr = mfab_comp.array(mfi) 65 | # numpy/cupy representation: non-copying view, including the 66 | # guard/ghost region 67 | marr_xp = marr.to_xp() 68 | assert marr_xp.shape == (32, 32, 32, 1) 69 | assert np.all(marr_xp[:, :, :, :] == np.pi) 70 | nboxes += 1 71 | 72 | assert nboxes == 1 73 | -------------------------------------------------------------------------------- /tests/test_podvector.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import amrex.space3d as amr 4 | 5 | 6 | def test_podvector_init(): 7 | podv = amr.PODVector_real_std() 8 | print(podv.__array_interface__) 9 | # podv[0] = 1 10 | # podv[2] = 3 11 | assert podv.size() == 0 12 | podv.push_back(1) 13 | podv.push_back(2) 14 | assert podv.size() == 2 and podv[1] == 2 15 | podv.pop_back() 16 | assert podv.size() == 1 17 | podv.push_back(2.14) 18 | assert not podv.empty() 19 | podv.push_back(3.1) 20 | podv[2] = 5 21 | assert podv.size() == 3 and podv[2] == 5 22 | podv.clear() 23 | assert podv.size() == 0 24 | assert podv.empty() 25 | 26 | 27 | def test_array_interface(): 28 | podv = amr.PODVector_int_std() 29 | podv.push_back(1) 30 | podv.push_back(2) 31 | podv.push_back(1) 32 | podv.push_back(5) 33 | arr = podv.to_numpy() 34 | print(arr) 35 | 36 | # podv[2] = 3 37 | arr[2] = 3 38 | print(arr) 39 | print(podv) 40 | assert arr[2] == podv[2] == 3 41 | 42 | podv[1] = 5 43 | assert arr[1] == podv[1] == 5 44 | -------------------------------------------------------------------------------- /tests/test_realbox.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import amrex.space3d as amr 4 | from amrex.space3d import RealVect as RV 5 | from amrex.space3d import XDim3 6 | 7 | 8 | def test_realbox_empty(): 9 | rb = amr.RealBox() 10 | assert not rb.ok() 11 | assert rb.xlo[0] == 0 and rb.xlo[1] == 0 and rb.xlo[2] == 0 and rb.xhi[0] == -1 12 | assert rb.length(2) == -1 and rb.length(2) == -1 and rb.length(2) == -1 13 | assert rb.volume() == 0 14 | 15 | rb.setLo([-1, -2, -3]) 16 | rb.setHi([0, 0, 0]) 17 | assert rb.volume() == 6 18 | rb.setHi(0, 1.2) 19 | assert rb.hi(0) == 1.2 20 | 21 | 22 | def test_realbox_frombox(std_box): 23 | dx = [1.0, 2.0, 3.0] 24 | base = [100.0, 200.0, 300.0] # offset 25 | rb1 = amr.RealBox(std_box, dx, base) 26 | 27 | rb2 = amr.RealBox( 28 | [100.0, 200.0, 300.0], 29 | [100.0 + dx[0] * 64, 200.0 + dx[1] * 64, 300.0 + dx[2] * 64], 30 | ) 31 | assert amr.AlmostEqual(rb1, rb2) 32 | 33 | 34 | def test_realbox_contains(): 35 | rb1 = amr.RealBox([0, 0, 0], [1, 2, 1.5]) 36 | point1 = [-1, 0, 2] 37 | point2 = [0.5, 0.5, 0.5] 38 | assert not rb1.contains(point1) 39 | assert rb1.contains(point2) 40 | 41 | rb2 = amr.RealBox(0.1, 0.2, 0.3, 0.3, 1, 1.0) 42 | rb3 = amr.RealBox([4, 5.0, 6.0], [5.0, 5.5, 7.0]) 43 | assert rb1.contains(rb2) 44 | assert not rb1.contains(rb3) 45 | tol = 8 46 | assert rb1.contains(rb3, eps=tol) 47 | 48 | # contains Real Vect 49 | rv1 = RV(point1) 50 | rv2 = RV(point2) 51 | assert not rb1.contains(rv1) 52 | assert rb1.contains(rv2) 53 | tol = 0.1 54 | assert not rb1.contains(rv1, eps=tol) 55 | tol = 2 56 | assert rb1.contains(rb1, eps=tol) 57 | # contains XDim3 58 | d1 = XDim3(-1, 0, 2) 59 | d2 = XDim3(0.5, 0.5, 0.5) 60 | assert not rb1.contains(d1) 61 | assert rb1.contains(d2) 62 | 63 | 64 | def test_realbox_intersects(): 65 | rb1 = amr.RealBox([0, 0, 0], [1, 2, 1.5]) 66 | rb2 = amr.RealBox([0.1, 0.2, 0.3], [0.3, 1, 1.0]) 67 | rb3 = amr.RealBox([4, 5.0, 6.0], [5.0, 5.5, 7.0]) 68 | assert rb1.intersects(rb2) 69 | assert not rb3.intersects(rb1) 70 | 71 | 72 | def test_almost_equal(): 73 | rb1 = amr.RealBox([0, 0, 0], [1, 2, 1.5]) 74 | rb2 = amr.RealBox([0, 0, 0], [1, 2, 1.5]) 75 | rb3 = amr.RealBox([0, 0.1, -0.1], [1, 2, 1.4]) 76 | assert amr.AlmostEqual(rb1, rb2) 77 | assert not amr.AlmostEqual(rb1, rb3) 78 | tol = 0.05 79 | assert not amr.AlmostEqual(rb1, rb3, tol) 80 | tol = 0.2 81 | assert amr.AlmostEqual(rb1, rb3, tol) 82 | -------------------------------------------------------------------------------- /tests/test_soa.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import numpy as np 4 | 5 | import amrex.space3d as amr 6 | 7 | 8 | def test_soa_init(): 9 | soa = amr.StructOfArrays_3_1_default() 10 | print("--test init --") 11 | print("num real components", soa.num_real_comps) 12 | print("num int components", soa.num_int_comps) 13 | assert soa.num_real_comps == 3 and soa.num_int_comps == 1 14 | 15 | soa.define(1, 3, ["x", "y", "z", "w"], ["i1", "i2", "i3", "i4"]) 16 | print("--test define --") 17 | print("num real components", soa.num_real_comps) 18 | print("num int components", soa.num_int_comps) 19 | assert soa.num_real_comps == 4 and soa.num_int_comps == 4 20 | print("num particles", soa.num_particles) 21 | print("num real particles", soa.num_real_particles) 22 | print("num totalparticles", soa.num_total_particles) 23 | print("num Neighbors", soa.get_num_neighbors()) 24 | print("soa size", soa.size) 25 | assert soa.num_particles == soa.num_real_particles == 0 26 | assert soa.size == soa.num_total_particles == 0 27 | assert soa.get_num_neighbors() == 0 28 | 29 | soa.resize(5) 30 | print("--test resize --") 31 | print("num particles", soa.num_particles) 32 | print("num real particles", soa.num_real_particles) 33 | print("num totalparticles", soa.num_total_particles) 34 | print("num Neighbors", soa.get_num_neighbors()) 35 | print("soa size", soa.size) 36 | assert soa.num_particles == soa.num_real_particles == 5 37 | assert soa.size == soa.num_total_particles == 5 38 | assert soa.get_num_neighbors() == 0 39 | 40 | soa.set_num_neighbors(3) 41 | print("--test set neighbor num--") 42 | print("num particles", soa.num_particles) 43 | print("num real particles", soa.num_real_particles) 44 | print("num totalparticles", soa.num_total_particles) 45 | print("num Neighbors", soa.get_num_neighbors()) 46 | print("soa size", soa.size) 47 | assert soa.num_particles == soa.num_real_particles == 5 48 | assert soa.size == soa.num_total_particles == 8 49 | assert soa.get_num_neighbors() == 3 50 | 51 | 52 | def test_soa_from_tile(): 53 | pt = ( 54 | amr.ParticleTile_2_1_3_1_managed() 55 | if amr.Config.have_gpu 56 | else amr.ParticleTile_2_1_3_1_default() 57 | ) 58 | p = amr.Particle_5_2( 59 | 1.0, 60 | 2.0, 61 | 3.0, 62 | rdata_0=4.0, 63 | rdata_1=5.0, 64 | rdata_2=6.0, 65 | rdata_3=7.0, 66 | rdata_4=8.0, 67 | idata_0=9, 68 | idata_1=10, 69 | ) 70 | sp = amr.Particle_5_2(1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1, 9, 10) 71 | pt.push_back(p) 72 | pt.push_back(sp) 73 | 74 | soa = pt.get_struct_of_arrays() 75 | print("num particles", soa.num_particles) 76 | print("num real particles", soa.num_real_particles) 77 | print("num totalparticles", soa.num_total_particles) 78 | print("num Neighbors", soa.get_num_neighbors()) 79 | print("soa size", soa.size) 80 | assert soa.num_particles == soa.size == 2 81 | assert soa.num_total_particles == soa.num_real_particles == 2 82 | assert soa.get_num_neighbors() == 0 83 | 84 | real_arrays = soa.get_real_data() 85 | int_arrays = soa.get_int_data() 86 | print(real_arrays) 87 | assert np.isclose(real_arrays[0][1], 6.1) and np.isclose(real_arrays[1][1], 7.1) 88 | assert isinstance(int_arrays[0][0], int) 89 | assert int_arrays[0][1] == 10 90 | 91 | real_arrays[1][0] = -1.2 92 | 93 | ra1 = soa.get_real_data() 94 | print(real_arrays) 95 | print(ra1) 96 | for ii, arr in enumerate(real_arrays): 97 | assert np.allclose(arr.to_numpy(), ra1[ii].to_numpy()) 98 | 99 | print("soa int test") 100 | iarr_np = int_arrays[0].to_numpy() 101 | iarr_np[0] = -3 102 | ia1 = soa.get_int_data() 103 | ia1_np = ia1[0].to_numpy() 104 | print(iarr_np) 105 | print(ia1_np) 106 | assert np.allclose(iarr_np, ia1_np) 107 | -------------------------------------------------------------------------------- /tests/test_utility.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import amrex.space3d as amr 4 | 5 | 6 | def test_concatenate(): 7 | pltname = amr.concatenate("plt", 1000, 5) 8 | assert pltname == "plt01000" 9 | 10 | 11 | def test_print(): 12 | print("hello from everyone") 13 | amr.Print("byeee from IO processor") 14 | -------------------------------------------------------------------------------- /tools/plot_plotfile_2d.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | import pytest 4 | 5 | import amrex.space2d as amr 6 | 7 | 8 | def plot_mf(arr, compname, plo, phi): 9 | plt.plot() 10 | im = plt.imshow( 11 | arr.T, 12 | origin="lower", 13 | interpolation="none", 14 | extent=[plo[0], phi[0], plo[1], phi[1]], 15 | aspect="equal", 16 | ) 17 | plt.colorbar(im) 18 | plt.tight_layout() 19 | plt.savefig(f"{compname}.png", dpi=150) 20 | plt.close() 21 | 22 | 23 | @pytest.mark.skipif(amr.Config.spacedim != 2, reason="Requires AMREX_SPACEDIM = 2") 24 | def plot_plotfile_2d(filename, level=0): 25 | plt = amr.PlotFileData(filename) 26 | assert level <= plt.finestLevel() 27 | 28 | probDomain = plt.probDomain(level) 29 | probLo = plt.probLo() 30 | probHi = plt.probHi() 31 | varNames = plt.varNames() 32 | 33 | for compname in varNames: 34 | mfab_comp = plt.get(level, compname) 35 | arr = np.zeros((probDomain.big_end - probDomain.small_end + 1)) 36 | for mfi in mfab_comp: 37 | bx = mfi.tilebox() 38 | marr = mfab_comp.array(mfi) 39 | marr_xp = marr.to_xp() 40 | i_s, j_s = tuple(bx.small_end) 41 | i_e, j_e = tuple(bx.big_end) 42 | arr[i_s : i_e + 1, j_s : j_e + 1] = marr_xp[:, :, 0, 0] 43 | plot_mf(arr, compname, probLo, probHi) 44 | 45 | 46 | if __name__ == "__main__": 47 | import argparse 48 | 49 | parser = argparse.ArgumentParser( 50 | "Plots each variable in a 2D plotfile using matplotlib." 51 | ) 52 | parser.add_argument("filename", help="AMReX 2D plotfile to read") 53 | parser.add_argument("level", type=int, help="AMR level to plot (default: 0)") 54 | args = parser.parse_args() 55 | 56 | amr.initialize([]) 57 | plot_plotfile_2d(args.filename, level=args.level) 58 | --------------------------------------------------------------------------------