diff --git a/.github/workflows/dependencies/dependencies.sh b/.github/workflows/dependencies/dependencies.sh
index d0e86e99..ecaa6eca 100755
--- a/.github/workflows/dependencies/dependencies.sh
+++ b/.github/workflows/dependencies/dependencies.sh
@@ -13,4 +13,8 @@ sudo apt-get install -y --no-install-recommends\
build-essential \
g++ gfortran \
libopenmpi-dev \
- openmpi-bin
+ openmpi-bin \
+ python3 \
+ python3-pip
+
+python3 -m pip install -U pip setuptools wheel
diff --git a/.github/workflows/dependencies/dependencies_clang6.sh b/.github/workflows/dependencies/dependencies_clang6.sh
index 19b348b9..596dd8c3 100755
--- a/.github/workflows/dependencies/dependencies_clang6.sh
+++ b/.github/workflows/dependencies/dependencies_clang6.sh
@@ -11,4 +11,8 @@ sudo apt-get update
sudo apt-get install -y \
build-essential \
- clang gfortran
+ clang gfortran \
+ python3 \
+ python3-pip
+
+python3 -m pip install -U pip setuptools wheel
diff --git a/.github/workflows/dependencies/dependencies_gcc10.sh b/.github/workflows/dependencies/dependencies_gcc10.sh
index 583c5018..66573abc 100755
--- a/.github/workflows/dependencies/dependencies_gcc10.sh
+++ b/.github/workflows/dependencies/dependencies_gcc10.sh
@@ -14,4 +14,8 @@ sudo apt-get install -y --no-install-recommends \
build-essential \
g++-10 gfortran-10 \
libopenmpi-dev \
- openmpi-bin
+ openmpi-bin \
+ python3 \
+ python3-pip
+
+python3 -m pip install -U pip setuptools wheel
diff --git a/.github/workflows/dependencies/dependencies_nofortran.sh b/.github/workflows/dependencies/dependencies_nofortran.sh
index 36d759f6..d00c1ff8 100755
--- a/.github/workflows/dependencies/dependencies_nofortran.sh
+++ b/.github/workflows/dependencies/dependencies_nofortran.sh
@@ -17,4 +17,8 @@ sudo apt-get install -y --no-install-recommends\
build-essential \
g++ \
libopenmpi-dev \
- openmpi-bin
+ openmpi-bin \
+ python3 \
+ python3-pip
+
+python3 -m pip install -U pip setuptools wheel
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 25f93f6e..428d21e8 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -16,17 +16,21 @@ jobs:
- name: Build & Install
run: |
cd ExampleCodes
- mkdir build
- cd build
- cmake .. \
+ cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DAMReX_LINEAR_SOLVERS=ON \
-DAMReX_FORTRAN=ON \
-DAMReX_FORTRAN_INTERFACES=ON \
-DAMReX_EB=ON \
- -DAMReX_PARTICLES=ON
- make -j 2
+ -DAMReX_PARTICLES=ON \
+ -DTUTORIAL_PYTHON=ON
+ cmake --build build -j 2
+ cmake --build build -j 2 --target pyamrex_pip_install
+ - name: Run Python
+ run: |
+ cd GuidedTutorials/MultiFab/
+ python main.py
# Build all tutorials
tutorials_cxx20:
@@ -40,9 +44,7 @@ jobs:
- name: Build & Install
run: |
cd ExampleCodes
- mkdir build
- cd build
- cmake .. \
+ cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DAMReX_OMP=ON \
@@ -50,12 +52,18 @@ jobs:
-DAMReX_LINEAR_SOLVERS=ON \
-DAMReX_FORTRAN=ON \
-DAMReX_FORTRAN_INTERFACES=ON \
- -DAMReX_EB=ON \
+ -DAMReX_EB=ON \
+ -DTUTORIAL_PYTHON=ON \
-DCMAKE_CXX_STANDARD=20 \
-DCMAKE_C_COMPILER=$(which gcc-10) \
-DCMAKE_CXX_COMPILER=$(which g++-10) \
-DCMAKE_Fortran_COMPILER=$(which mpif90)
- make -j 2
+ cmake --build build -j 2
+ cmake --build build -j 2 --target pyamrex_pip_install
+ - name: Run Python
+ run: |
+ cd GuidedTutorials/MultiFab/
+ python main.py
tutorials_clang:
name: Clang@6.0 C++14 SP Particles DP Mesh Debug [tutorials]
@@ -68,9 +76,7 @@ jobs:
- name: Build & Install
run: |
cd ExampleCodes
- mkdir build
- cd build
- cmake .. \
+ cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DAMReX_MPI=OFF \
@@ -81,11 +87,17 @@ jobs:
-DAMReX_EB=ON \
-DAMReX_PRECISION=DOUBLE \
-DAMReX_PARTICLES_PRECISION=SINGLE \
+ -DTUTORIAL_PYTHON=ON \
-DCMAKE_CXX_STANDARD=14 \
-DCMAKE_C_COMPILER=$(which clang) \
-DCMAKE_CXX_COMPILER=$(which clang++) \
-DCMAKE_Fortran_COMPILER=$(which gfortran)
- make -j 2
+ cmake --build build -j 2
+ cmake --build build -j 2 --target pyamrex_pip_install
+ - name: Run Python
+ run: |
+ cd GuidedTutorials/MultiFab/
+ python main.py
# Build all tutorials w/o MPI
tutorials-nonmpi:
@@ -99,9 +111,7 @@ jobs:
- name: Build & Install
run: |
cd ExampleCodes
- mkdir build
- cd build
- cmake .. \
+ cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DAMReX_MPI=OFF \
@@ -109,8 +119,14 @@ jobs:
-DAMReX_FORTRAN=ON \
-DAMReX_FORTRAN_INTERFACES=ON \
-DAMReX_EB=ON \
- -DAMReX_PARTICLES=ON
- make -j 2
+ -DAMReX_PARTICLES=ON \
+ -DTUTORIAL_PYTHON=ON
+ cmake --build build -j 2
+ cmake --build build -j 2 --target pyamrex_pip_install
+ - name: Run Python
+ run: |
+ cd GuidedTutorials/MultiFab/
+ python main.py
# Build all tutorials
tutorials-nofortran:
@@ -124,16 +140,20 @@ jobs:
- name: Build & Install
run: |
cd ExampleCodes
- mkdir build
- cd build
- cmake .. \
+ cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DAMReX_LINEAR_SOLVERS=ON \
-DAMReX_EB=ON \
-DAMReX_PARTICLES=ON \
- -DAMReX_FORTRAN=OFF
- make -j 2
+ -DAMReX_FORTRAN=OFF \
+ -DTUTORIAL_PYTHON=ON
+ cmake --build build -j 2
+ cmake --build build -j 2 --target pyamrex_pip_install
+ - name: Run Python
+ run: |
+ cd GuidedTutorials/MultiFab/
+ python main.py
# Build all tutorials with CUDA 11.0.2 (recent supported)
tutorials-cuda11:
diff --git a/Docs/source/Python_Tutorial.rst b/Docs/source/Python_Tutorial.rst
new file mode 100644
index 00000000..37c6fc7d
--- /dev/null
+++ b/Docs/source/Python_Tutorial.rst
@@ -0,0 +1,17 @@
+.. _tutorials_python:
+
+======
+Python
+======
+
+These examples show how to use AMReX from Python.
+AMReX applications can also be interfaced to Python with the same logic.
+
+In order to build the Python tutorials, add ``-DTUTORIAL_PYTHON=ON`` to the CMake configuration options.
+Then install with ``cmake --build build --target pyamrex_pip_install``.
+
+Examples:
+
+- ``GuidedTutorials/MultiFab/main.py``
+
+Please see `pyAMReX `__ for more details.
diff --git a/Docs/source/index.rst b/Docs/source/index.rst
index 555b56c3..d9995d95 100644
--- a/Docs/source/index.rst
+++ b/Docs/source/index.rst
@@ -50,6 +50,7 @@ sorted by the following categories:
- :ref:`Linear Solvers` -- Examples of several linear solvers.
- :ref:`MUI` -- Incorporates the MxUI/MUI (Multiscale Universal interface) frame into AMReX.
- :ref:`Particles` -- Basic usage of AMReX's particle data structures.
+- :ref:`Python` -- Using AMReX and interfacing with AMReX applications form Python - via `pyAMReX `__
- :ref:`SDC` -- Example usage of a "Multi-Implicit" Spectral Deferred Corrections (MISDC) integrator
to solve a scalar advection-diffusion-reaction equation.
- :ref:`SENSEI` -- In situ data analysis and visualization through a unified interface.
@@ -71,6 +72,7 @@ sorted by the following categories:
ML_Tutorial
MUI_Tutorial
Particles_Tutorial
+ Python_Tutorial
SDC_Tutorial
SENSEI_Tutorial
SUNDIALS_Tutorial
@@ -95,6 +97,8 @@ sorted by the following categories:
.. _`Particles`: Particles_Tutorial.html
+.. _`Python`: Python_Tutorial.html
+
.. _`SDC`: SDC_Tutorial.html
.. _`SENSEI`: SENSEI_Tutorial.html
diff --git a/ExampleCodes/CMakeLists.txt b/ExampleCodes/CMakeLists.txt
index 75e2688b..be729404 100644
--- a/ExampleCodes/CMakeLists.txt
+++ b/ExampleCodes/CMakeLists.txt
@@ -14,17 +14,34 @@ set( CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake )
# If AMReX_DIR is passed then we link to the library found there. Otherwise
# the sources are fetched and compiled from the repo pointed to by AMReX_GIT_REPO
#
-set ( AMReX_GIT_REPO "https://github.com/AMReX-Codes/amrex.git/"
- CACHE STRING "The URL identifying the repo to fetchg AMReX from" )
+set ( AMReX_GIT_REPO "https://github.com/AMReX-Codes/amrex.git"
+ CACHE STRING "The URL identifying the repo to fetch AMReX from" )
#
# Fetch and compile AMReX or link to an existing CMake build install of libamrex.
# If AMReX_DIR is passed then we link to the library found there. Otherwise
-# the sources are fetched and compiled from the repo pointed to by AMReX_GIT_REPO
+# the sources are fetched and compiled from the repo pointed to by pyAMReX_GIT_REPO
+#
+set ( pyAMReX_GIT_REPO "https://github.com/AMReX-Codes/pyamrex.git"
+ CACHE STRING "The URL identifying the repo to fetch pyAMReX from" )
+option(TUTORIAL_PYTHON OFF)
+
+#
+# Fetch and compile AMReX or link to an existing CMake build install of libamrex.
+# If AMReX_DIR is passed then we link to the library found there. Otherwise
+# the sources are fetched and compiled from the repo pointed to by SUNDIALS_GIT_REPO
#
set ( SUNDIALS_GIT_REPO "https://github.com/LLNL/sundials.git"
CACHE STRING "The URL identifying the repo to fetch SUNDIALS from" )
+#
+# For Python, we need AMReX as a a sahred library, otherwise we cannot share all
+# its global variables between multiple Python modules
+#
+if(TUTORIAL_PYTHON)
+ set(AMReX_BUILD_SHARED_LIBS ON CACHE BOOL "Build AMReX shared library" FORCE)
+endif()
+
if( NOT DEFINED AMReX_DIR )
#
# Fetch amrex repo
@@ -174,6 +191,33 @@ else()
endif()
endif()
+if(TUTORIAL_PYTHON)
+ if(DEFINED pyAMReX_DIR)
+ add_subdirectory(${pyAMReX_DIR})
+ else()
+ #
+ # Fetch pyAMReX repo
+ #
+ message(STATUS "Fetching from ${pyAMReX_GIT_REPO} branch ${pyAMReX_GIT_BRANCH}" )
+
+ set(pyAMReX_GIT_BRANCH "development" CACHE STRING "The pyAMReX branch to checkout")
+ set(pyAMReX_INSTALL "NO" CACHE INTERNAL "Disable install target for pyAMReX")
+
+ include(FetchContent)
+ #set(FETCHCONTENT_QUIET OFF) # Verbose ON
+
+ FetchContent_Declare( fetchedpyamrex
+ GIT_REPOSITORY ${pyAMReX_GIT_REPO}
+ GIT_TAG ${pyAMReX_GIT_BRANCH}
+ )
+
+ if(NOT fetchedpyamrex_POPULATED)
+ FetchContent_Populate(fetchedpyamrex)
+ add_subdirectory(${fetchedpyamrex_SOURCE_DIR} ${fetchedpyamrex_BINARY_DIR})
+ endif()
+ endif()
+endif()
+
#
# List of subdirectories to search for CMakeLists.
# For now, we do not include MUI, SDC, SWFFT
diff --git a/GuidedTutorials/MultiFab/main.py b/GuidedTutorials/MultiFab/main.py
new file mode 100644
index 00000000..e4418b98
--- /dev/null
+++ b/GuidedTutorials/MultiFab/main.py
@@ -0,0 +1,99 @@
+import amrex.space3d as amr
+
+# CPU/GPU logic
+if amr.Config.have_gpu:
+ try:
+ import cupy as cp
+ xp = cp
+ print("Note: found and will use cupy")
+ except ImportError:
+ print("Warning: GPU found but cupy not available! Trying managed memory in numpy...")
+ import numpy as np
+ xp = np
+ if amr.Config.gpu_backend == "SYCL":
+ print("Warning: SYCL GPU backend not yet implemented for Python")
+ import numpy as np
+ xp = np
+
+else:
+ import numpy as np
+ xp = np
+ print("Note: found and will use numpy")
+
+
+# Initialize AMReX
+amr.initialize([])
+
+if amr.ParallelDescriptor.IOProcessor():
+ print(f"Hello world from pyAMReX version {amr.__version__}\n")
+
+# Goals:
+# * Define a MultiFab
+# * Fill a MultiFab with data
+# * Plot it
+
+# Parameters
+
+# Number of data components at each grid point in the MultiFab
+ncomp = 1
+# How many grid cells in each direction over the problem domain
+n_cell = 32
+# How many grid cells are allowed in each direction over each box
+max_grid_size = 16
+
+# BoxArray: abstract domain setup
+
+# Integer vector indicating the lower coordinate bounds
+dom_lo = amr.IntVect(0,0,0)
+# Integer vector indicating the upper coordinate bounds
+dom_hi = amr.IntVect(n_cell-1, n_cell-1, n_cell-1)
+# Box containing the coordinates of this domain
+domain = amr.Box(dom_lo, dom_hi)
+
+# Will contain a list of boxes describing the problem domain
+ba = amr.BoxArray(domain)
+
+# Chop the single grid into many small boxes
+ba.max_size(max_grid_size)
+
+# Distribution Mapping
+dm = amr.DistributionMapping(ba)
+
+# Define MultiFab
+mf = amr.MultiFab(ba, dm, ncomp, 0)
+mf.set_val(0.)
+
+# Geometry: physical properties for data on our domain
+real_box = amr.RealBox([0., 0., 0.], [1. , 1., 1.])
+
+coord = 0 # Cartesian
+is_per = [0, 0, 0] # periodicity
+geom = amr.Geometry(domain, real_box, coord, is_per)
+
+# Calculate cell sizes
+dx = geom.data().CellSize() # dx[0]=dx dx[1]=dy dx[2]=dz
+
+# Fill a MultiFab with data
+mf_val = 0.
+for mfi in mf:
+ bx = mfi.validbox()
+ # Preferred way to fill array using fast ranged operations:
+ # - xp.array is indexed in reversed order (n,z,y,x),
+ # .T creates a view into the AMReX (x,y,z,n) order
+ # - indices are local (range from 0 to box size)
+ mf_array = xp.array(mf.array(mfi), copy=False).T
+ x = (xp.arange(bx.small_end[0], bx.big_end[0]+1)+0.5)*dx[0]
+ y = (xp.arange(bx.small_end[1], bx.big_end[1]+1)+0.5)*dx[1]
+ z = (xp.arange(bx.small_end[2], bx.big_end[2]+1)+0.5)*dx[2]
+ v = (x[xp.newaxis,xp.newaxis,:]
+ + y[xp.newaxis,:,xp.newaxis]*0.1
+ + z[:,xp.newaxis,xp.newaxis]*0.01)
+ mf_array = 1. + xp.exp(-v)
+
+# Plot MultiFab data
+plotfile = amr.concatenate(root="plt", num=1, mindigits=3)
+varnames = amr.Vector_string(["comp0"])
+amr.write_single_level_plotfile(plotfile, mf, varnames, geom, time=0., level_step=0)
+
+# Finalize AMReX
+amr.finalize()