diff --git a/.github/workflows/tests+pypi.yml b/.github/workflows/tests+pypi.yml index 6709fb32..bc5648e6 100644 --- a/.github/workflows/tests+pypi.yml +++ b/.github/workflows/tests+pypi.yml @@ -224,13 +224,16 @@ jobs: cd ../../../ rm -rf libmpdataxx + - uses: julia-actions/setup-julia@v2 + - run: julia --version + # https://github.com/numba/numba/issues/6350#issuecomment-728174860 - if: matrix.platform == 'ubuntu-latest' run: echo NUMBA_THREADING_LAYER=omp >> $GITHUB_ENV - env: NUMBA_OPT: 1 - run: python -m pytest --durations=10 -p no:unraisableexception -We tests/devops_tests/test_notebooks.py + run: python -m pytest -rP -vv --durations=10 -p no:unraisableexception -We tests/devops_tests/test_notebooks.py - if: ${{ matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.11'}} run: | diff --git a/examples/PyMPDATA_examples/trixi_comparison/advection_comparison.ipynb b/examples/PyMPDATA_examples/trixi_comparison/advection_comparison.ipynb new file mode 100644 index 00000000..b35ce079 --- /dev/null +++ b/examples/PyMPDATA_examples/trixi_comparison/advection_comparison.ipynb @@ -0,0 +1,627 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e333839d", + "metadata": {}, + "source": [ + "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PyMPDATA.git/main?urlpath=lab/tree/examples/PyMPDATA_examples/advection_diffusion_2d/advection-diffusion-2d.ipynb)\n", + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/examples/blob/main/examples/PyMPDATA_examples/advection_diffusion_2d/advection-diffusion-2d.ipynb)" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Introduction\n", + "Trixi.jl is a numerical simulation framework for conservation laws written in Julia. It is based on the Discontinuous Galerkin (DG) method and for the purpose of this comparison, we will use the StructuredMesh for data representation.\n", + "\n", + "This notebook compares the results of a simple advection equation solved in 2D by PyMPDATA and Trixi.jl.\n", + "The general flow of the notebook is as follows:\n", + "1. We define the advection equation and the common settings for both PyMPDATA and Trixi.jl in the JSON file.\n", + "2. We run the simulation in Trixi.jl and save the results.\n", + "3. We use Trixi2Vtk to convert the results to a vtk file.\n", + "4. We reshape the results from Trixi.jl to match the shape of the results from PyMPDATA.\n", + "5. We run the simulation in PyMPDATA for a bigger nx and ny, to account for the polynomial degree in Trixi.jl. \n", + "6. We compare the results from PyMPDATA and Trixi.jl.\n", + "7. We assert that the results are close to each other, this is to ensure that the implementation of PyMPDATA is correct.\n", + "\n", + "To run the notebook, Julia and the following Julia packages are required:\n", + "- JSON\n", + "- Trixi\n", + "- OrdinaryDiffEq\n", + "- Trixi2Vtk\n", + "- Pkg" + ], + "id": "2448bffa3ee6d9ff" + }, + { + "cell_type": "markdown", + "id": "0f162ce9-5704-4464-8b67-be8c86ecabc8", + "metadata": {}, + "source": [ + "## common settings" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:15.785252Z", + "start_time": "2024-10-17T20:54:15.764141Z" + } + }, + "cell_type": "code", + "source": [ + "SETUP = {\n", + " \"nx\": 32,\n", + " \"ny\": 32,\n", + " \"ux\": 0.25,\n", + " \"uy\": 0.25,\n", + " \"dt\": 0.025,\n", + " \"tmax\": 2.0,\n", + " \"polydeg\": 2,\n", + " \"omega\": 3.141592,\n", + " \"min_x\": -1.0,\n", + " \"min_y\": -1.0,\n", + " \"max_x\": 1.0,\n", + " \"max_y\": 1.0\n", + "}\n", + "\n", + "assert SETUP[\"nx\"] == SETUP[\"ny\"]\n", + "\n", + "import json\n", + "import subprocess\n", + "with open('setup.json', 'w', encoding='UTF-8') as f:\n", + " json.dump(SETUP, f)" + ], + "id": "dff76910f0610a2d", + "outputs": [], + "execution_count": 1 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Trixi.jl" + ], + "id": "52cd27020f7efe9" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:15.972485Z", + "start_time": "2024-10-17T20:54:15.955869Z" + } + }, + "cell_type": "code", + "source": [ + "%%writefile trixi.jl\n", + "import Pkg\n", + "Pkg.add([\"JSON\", \"Trixi\", \"OrdinaryDiffEq\", \"Trixi2Vtk\"])\n", + "using JSON\n", + "using Trixi\n", + "using OrdinaryDiffEq\n", + "using Trixi2Vtk\n", + "\n", + "setup = JSON.parsefile(\"./setup.json\")\n", + "\n", + "advection_velocity = (setup[\"ux\"], setup[\"uy\"])\n", + "equations = LinearScalarAdvectionEquation2D(advection_velocity)\n", + "solver = DGSEM(polydeg = setup[\"polydeg\"])\n", + "\n", + "function initial_condition(x, t, equations::LinearScalarAdvectionEquation2D)\n", + " return SVector(sin(setup[\"omega\"]*sum(x)) + 1)\n", + "end\n", + "\n", + "cells_per_dimension = (setup[\"nx\"], setup[\"ny\"])\n", + "coordinates_min = (setup[\"min_x\"], setup[\"min_y\"])\n", + "coordinates_max = (setup[\"max_x\"], setup[\"max_y\"])\n", + "\n", + "mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max)\n", + "semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)\n", + "\n", + "tspan = (0.0, setup[\"tmax\"])\n", + "ode = semidiscretize(semi, tspan);\n", + "\n", + "summary_callback = SummaryCallback()\n", + "save_solution = SaveSolutionCallback(save_initial_solution = false, interval=100)\n", + "\n", + "stepsize_callback = StepsizeCallback(cfl = 1.6)\n", + "\n", + "callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback)\n", + "\n", + "time_int_tol = 1e-6\n", + "sol = solve(ode, CarpenterKennedy2N54();\n", + " abstol = time_int_tol,\n", + " reltol = time_int_tol,\n", + " dt = setup[\"dt\"],\n", + " ode_default_options()..., callback = callbacks);\n", + "\n", + "summary_callback()" + ], + "id": "6586bff9a39d588f", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting trixi.jl\n" + ] + } + ], + "execution_count": 2 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:58.817780Z", + "start_time": "2024-10-17T20:54:16.041469Z" + } + }, + "cell_type": "code", + "source": "subprocess.run([\"julia\", \"trixi.jl\"], check=True)", + "id": "56fb8302adfc01e7", + "outputs": [ + { + "data": { + "text/plain": [ + "CompletedProcess(args=['julia', 'trixi.jl'], returncode=0)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 3 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## PyMPDATA", + "id": "a30cc2b4961f1be7" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:59.897488Z", + "start_time": "2024-10-17T20:54:58.817780Z" + } + }, + "cell_type": "code", + "source": [ + "import numpy as np\n", + "import meshio\n", + "from open_atmos_jupyter_utils import show_plot\n", + "import matplotlib.pyplot as plt\n", + "from PyMPDATA import Solver, ScalarField, VectorField, Stepper, Options\n", + "from PyMPDATA.boundary_conditions import Periodic\n", + "import os" + ], + "id": "9aaadc4a5234804a", + "outputs": [], + "execution_count": 4 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:59.904992Z", + "start_time": "2024-10-17T20:54:59.898836Z" + } + }, + "cell_type": "code", + "source": [ + "dt = SETUP[\"dt\"]\n", + "tmax = SETUP[\"tmax\"]\n", + "nt = int(tmax / dt)\n", + "\n", + "nx = SETUP[\"nx\"] * SETUP[\"polydeg\"] + 1\n", + "ny = SETUP[\"ny\"] * SETUP[\"polydeg\"] + 1\n", + "ux = SETUP[\"ux\"]\n", + "uy = SETUP[\"uy\"]\n", + "omega = SETUP[\"omega\"]\n", + "\n", + "min_x, min_y = SETUP[\"min_x\"], SETUP[\"min_y\"]\n", + "max_x, max_y = SETUP[\"max_x\"], SETUP[\"max_y\"]\n", + "dx_temp = (max_x - min_x) / (nx - 1)\n", + "dy_temp = (max_y - min_y) / (ny - 1)\n", + "min_x, max_x = min_x - dx_temp/2, max_x + dx_temp/2\n", + "min_y, max_y = min_y - dy_temp/2, max_y + dy_temp/2\n", + "dx = (max_x - min_x) / nx\n", + "dy = (max_y - min_y) / ny\n", + "Cx = ux * dt / dx\n", + "Cy = uy * dt / dy" + ], + "id": "9a0f60b51e32ce3e", + "outputs": [], + "execution_count": 5 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:59.949432Z", + "start_time": "2024-10-17T20:54:59.908312Z" + } + }, + "cell_type": "code", + "source": [ + "opt = Options(n_iters=3)\n", + "boundary_conditions = (Periodic(), Periodic())" + ], + "id": "64e3274fa4ac14a6", + "outputs": [], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:59.966791Z", + "start_time": "2024-10-17T20:54:59.949432Z" + } + }, + "cell_type": "code", + "source": [ + "def initial_condition():\n", + " return np.array(\n", + " [\n", + " np.sin(omega*(x+y)) + 1 for x in np.linspace(min_x, max_x, nx)\n", + " for y in np.linspace(min_y, max_y, ny)\n", + " ],\n", + " dtype=float\n", + ").reshape((nx, ny))\n", + "\n", + "advectee = ScalarField(data=initial_condition(), halo=opt.n_halo, boundary_conditions=boundary_conditions)" + ], + "id": "cab790be5c425ea5", + "outputs": [], + "execution_count": 7 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:54:59.976655Z", + "start_time": "2024-10-17T20:54:59.966791Z" + } + }, + "cell_type": "code", + "source": [ + "field_x = np.full((nx+1, ny), Cx, dtype=opt.dtype)\n", + "field_y = np.full((nx, ny+1), Cy, dtype=opt.dtype)\n", + "\n", + "advector = VectorField(\n", + " data=(field_x, field_y),\n", + " halo=opt.n_halo,\n", + " boundary_conditions=(boundary_conditions[0], Periodic())\n", + ")" + ], + "id": "b454a74473b8f900", + "outputs": [], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:00.539653Z", + "start_time": "2024-10-17T20:54:59.977172Z" + } + }, + "cell_type": "code", + "source": [ + "stepper = Stepper(options=opt, n_dims=2)\n", + "solver = Solver(stepper=stepper, advector=advector, advectee=advectee)" + ], + "id": "ce055b2d3a61a491", + "outputs": [], + "execution_count": 9 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:00.546502Z", + "start_time": "2024-10-17T20:55:00.539653Z" + } + }, + "cell_type": "code", + "source": [ + "vmin = np.min(solver.advectee.get())\n", + "vmax = np.max(solver.advectee.get())" + ], + "id": "5290dbc73bd36d29", + "outputs": [], + "execution_count": 10 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:33.467534Z", + "start_time": "2024-10-17T20:55:00.547019Z" + } + }, + "cell_type": "code", + "source": "_ = solver.advance(n_steps=nt)", + "id": "b29adee15e8ff545", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:33.475062Z", + "start_time": "2024-10-17T20:55:33.469404Z" + } + }, + "cell_type": "code", + "source": "pympdata_result_state = solver.advectee.get().copy()", + "id": "f59fd725765b765e", + "outputs": [], + "execution_count": 12 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:34.277608Z", + "start_time": "2024-10-17T20:55:33.478136Z" + } + }, + "cell_type": "code", + "source": [ + "plt.imshow(pympdata_result_state, cmap='viridis', vmin=vmin, vmax=vmax)\n", + "plt.colorbar()\n", + "plt.xlabel('x')\n", + "plt.ylabel('y')\n", + "plt.title('PyMDATA solution')\n", + "show_plot()" + ], + "id": "a041cd5f2c2dbaa", + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2024-10-17T22:55:34.227695\n image/svg+xml\n \n \n Matplotlib v3.9.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HTML(value=\".\\\\tmp5dn26voe.pdf
\")" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "3bcbfcb213bf4e0ea60a2233169c1f18" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:34.285578Z", + "start_time": "2024-10-17T20:55:34.277608Z" + } + }, + "cell_type": "code", + "source": "solution_filename = [f for f in os.listdir(\"./out\") if \"solution\" in f][0]", + "id": "c58862c96237cccf", + "outputs": [], + "execution_count": 14 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:34.308041Z", + "start_time": "2024-10-17T20:55:34.288863Z" + } + }, + "cell_type": "code", + "source": [ + "%%writefile to_vtk.jl\n", + "using Trixi2Vtk\n", + "trixi2vtk(joinpath(\"out\", ARGS[1]))" + ], + "id": "8d35a730ab764f86", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting to_vtk.jl\n" + ] + } + ], + "execution_count": 15 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:46.898943Z", + "start_time": "2024-10-17T20:55:34.308041Z" + } + }, + "cell_type": "code", + "source": "subprocess.run([\"julia\", \"to_vtk.jl\", solution_filename], check=True)", + "id": "960cee65b6c01544", + "outputs": [ + { + "data": { + "text/plain": [ + "CompletedProcess(args=['julia', 'to_vtk.jl', 'solution_000030.h5'], returncode=0)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 16 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:46.910997Z", + "start_time": "2024-10-17T20:55:46.899967Z" + } + }, + "cell_type": "code", + "source": [ + "try:\n", + " vtu_filename = [f for f in os.listdir(\"./\") if \"vtu\" in f][0]\n", + " mesh = meshio.read(vtu_filename)\n", + " trixi_points = ((mesh.points[:,:2] + 1)*SETUP[\"nx\"]*SETUP[\"polydeg\"]/2).round().astype(np.int16)\n", + " assert trixi_points.shape[0] == SETUP[\"nx\"]**2 * (SETUP[\"polydeg\"] + 1)**2\n", + "except Exception as e:\n", + " e.args += (list(os.walk(os.path.curdir)),)\n", + " raise e" + ], + "id": "451911db51e18682", + "outputs": [], + "execution_count": 17 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:46.956826Z", + "start_time": "2024-10-17T20:55:46.911540Z" + } + }, + "cell_type": "code", + "source": [ + "try:\n", + " trixi_output = np.zeros(pympdata_result_state.shape)\n", + " for i in range(trixi_points.shape[0]):\n", + " trixi_output[trixi_points[i][0], trixi_points[i][1]] = mesh.point_data['scalar'][i][0]\n", + "except Exception as e:\n", + " e.args += (list(mesh.point_data.keys()),)\n", + " e.args += (list(mesh.points.shape),)\n", + " raise e" + ], + "id": "58595cff705f196c", + "outputs": [], + "execution_count": 18 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:47.264497Z", + "start_time": "2024-10-17T20:55:46.956826Z" + } + }, + "cell_type": "code", + "source": [ + "plt.imshow(trixi_output, cmap='viridis', vmin=vmin, vmax=vmax)\n", + "plt.colorbar()\n", + "plt.xlabel('x')\n", + "plt.ylabel('y')\n", + "plt.title(\"Trixi solution\")\n", + "show_plot()" + ], + "id": "a126dbabdf719ee3", + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2024-10-17T22:55:47.209431\n image/svg+xml\n \n \n Matplotlib v3.9.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HTML(value=\".\\\\tmpxihl3pnw.pdf
\")" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "4df018beaba9453890f0578670985150" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 19 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:47.270117Z", + "start_time": "2024-10-17T20:55:47.264497Z" + } + }, + "cell_type": "code", + "source": [ + "residual = pympdata_result_state - trixi_output\n", + "rmse = np.sqrt(np.mean(residual**2))\n", + "mse = np.mean(residual**2)\n", + "max_diff = np.max(np.abs(residual))\n", + "min_diff = np.min(np.abs(residual))" + ], + "id": "ec2fffd2627288b4", + "outputs": [], + "execution_count": 20 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:47.288908Z", + "start_time": "2024-10-17T20:55:47.270117Z" + } + }, + "cell_type": "code", + "source": [ + "assert np.allclose(rmse, 6.94e-2, 0.1)\n", + "assert np.allclose(mse, 4.81e-3, 0.1)\n", + "assert np.allclose(max_diff, 0.285, 0.1)\n", + "assert np.allclose(min_diff, 2.69e-5, 0.1)" + ], + "id": "a7496a6f898495a3", + "outputs": [], + "execution_count": 21 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2024-10-17T20:55:47.293617Z", + "start_time": "2024-10-17T20:55:47.289032Z" + } + }, + "cell_type": "code", + "source": "", + "id": "119bd01509fa1ceb", + "outputs": [], + "execution_count": 21 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/setup.py b/examples/setup.py index 9b8678d7..9964905e 100644 --- a/examples/setup.py +++ b/examples/setup.py @@ -33,8 +33,10 @@ def get_long_description(): "scipy", "pint", "joblib", + "h5py", "sympy", "imageio", + "meshio", ], author="https://github.com/open-atmos/PyMPDATA/graphs/contributors", license="GPL-3.0",