diff --git a/.gitignore b/.gitignore index 2dc53ca3..040b5214 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,6 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ + +# VS Code +.vscode/ diff --git a/.zenodo.json b/.zenodo.json index b7699758..eff2b784 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -49,6 +49,22 @@ { "affiliation": "Jagiellonian University, Kraków, Poland", "name": "Sadowski, Michał" + }, + { + "affiliation": "AGH University of Krakow, Poland", + "name": "Jaśkowiec, Adrian" + }, + { + "affiliation": "AGH University of Krakow, Poland", + "name": "Paterak, Arkadiusz" + }, + { + "affiliation": "AGH University of Krakow, Poland", + "name": "Prosowicz, Wiktor" + }, + { + "affiliation": "AGH University of Krakow, Poland", + "name": "Stryszewski, Jan" } ], "keywords": [ diff --git a/PyMPDATA/impl/formulae_laplacian.py b/PyMPDATA/impl/formulae_laplacian.py index b6d31a78..df0768bb 100644 --- a/PyMPDATA/impl/formulae_laplacian.py +++ b/PyMPDATA/impl/formulae_laplacian.py @@ -43,7 +43,56 @@ def apply(traversals_data, advector, advectee): null_vecfield_bc, *null_scalarfield, null_scalarfield_bc, - traversals_data.buffer + traversals_data.buffer, + ) + + return apply + + +def make_heterogeneous_laplacian( + non_unit_g_factor: bool, options: Options, traversals: Traversals +): + """returns njit-ted function for heterogeneous diffusion with spatially varying diffusivity + + Note: heterogeneous diffusion is only supported when options.non_zero_mu_coeff is enabled + """ + if not options.non_zero_mu_coeff: + raise NotImplementedError( + "Heterogeneous diffusion requires options.non_zero_mu_coeff to be enabled" + ) + elif not options.heterogeneous_diffusion: + raise NotImplementedError( + "Heterogeneous diffusion requires options.heterogeneous_diffusion to be enabled" + ) + + else: + idx = traversals.indexers[traversals.n_dims] + apply_vector = traversals.apply_vector() + + formulae_heterogeneous = tuple( + ( + __make_heterogeneous_laplacian( + options.jit_flags, idx.ats[i], options.epsilon, non_unit_g_factor + ) + if idx.ats[i] is not None + else None + ) + for i in range(MAX_DIM_NUM) + ) + + @numba.njit(**options.jit_flags) + def apply(traversals_data, advector, advectee, diffusivity_field): + null_vecfield, null_vecfield_bc = traversals_data.null_vector_field + return apply_vector( + *formulae_heterogeneous, + *advector.field, + *advectee.field, + advectee.bc, + *null_vecfield, + null_vecfield_bc, + *diffusivity_field.field, + diffusivity_field.bc, + traversals_data.buffer, ) return apply @@ -62,3 +111,40 @@ def fun(advectee, _, __): ) return fun + + +def __make_heterogeneous_laplacian(jit_flags, ats, epsilon, non_unit_g_factor): + """Create heterogeneous Laplacian function that matches MPDATA's one-sided gradient pattern + + Note: Diffusivity values are expected to be non-negative. Negative values will cause + an assertion error. Zero values are handled by setting a minimum threshold (epsilon). + """ + if non_unit_g_factor: + raise NotImplementedError() + + @numba.njit(**jit_flags) + def fun(advectee, _, diffusivity): + # Get concentration values (matching regular laplacian pattern) + c_curr = ats(*advectee, 0) + c_right = ats(*advectee, 1) + + # Get diffusivity values + D_curr = ats(*diffusivity, 0) + D_right = ats(*diffusivity, 1) + + # Input validation for diffusivity values + assert D_curr >= 0.0, "Diffusivity values must be non-negative" + assert D_right >= 0.0, "Diffusivity values must be non-negative" + + # Handle near-zero diffusivity by setting minimum threshold + D_curr = max(D_curr, epsilon) + D_right = max(D_right, epsilon) + + # Match the exact MPDATA pattern but with diffusivity weighting + # Regular: -2 * (c[i+1] - c[i]) / (c[i+1] + c[i] + epsilon) + # Heterogeneous: weight by diffusivity at face + D_face = 0.5 * (D_curr + D_right) + + return -2 * D_face * (c_right - c_curr) / (c_right + c_curr + epsilon) + + return fun diff --git a/PyMPDATA/options.py b/PyMPDATA/options.py index 4ed9d181..224dd819 100644 --- a/PyMPDATA/options.py +++ b/PyMPDATA/options.py @@ -2,6 +2,8 @@ MPDATA variants, iterations, data-type and jit-flags settings """ +from typing import Union + import numpy as np from pystrict import strict @@ -32,8 +34,9 @@ def __init__( DPDC: bool = False, # pylint: disable=invalid-name epsilon: float = 1e-15, non_zero_mu_coeff: bool = False, + heterogeneous_diffusion: bool = False, dimensionally_split: bool = False, - dtype: [np.float32, np.float64] = np.float64 + dtype: Union[np.float32, np.float64] = np.float64, ): self._values = HashableDict( { @@ -47,6 +50,7 @@ def __init__( "dimensionally_split": dimensionally_split, "dtype": dtype, "DPDC": DPDC, + "heterogeneous_diffusion": heterogeneous_diffusion, } ) @@ -136,6 +140,11 @@ def dimensionally_split(self) -> bool: """flag disabling cross-dimensional terms in antidiffusive velocities""" return self._values["dimensionally_split"] + @property + def heterogeneous_diffusion(self) -> bool: + """flag enabling spatially varying diffusivity support""" + return self._values["heterogeneous_diffusion"] + def __str__(self): return str(self._values) diff --git a/PyMPDATA/solver.py b/PyMPDATA/solver.py index 8e6fff61..fd525b5c 100644 --- a/PyMPDATA/solver.py +++ b/PyMPDATA/solver.py @@ -50,7 +50,8 @@ def __init__( stepper: Stepper, advectee: ScalarField, advector: VectorField, - g_factor: [ScalarField, None] = None, + g_factor: Union[ScalarField, None] = None, + diffusivity_field: Union[ScalarField, None] = None, ): def scalar_field(dtype=None): return ScalarField.clone(advectee, dtype=dtype) @@ -64,8 +65,10 @@ def vector_field(): def null_vector_field(): return VectorField.make_null(advector.n_dims, stepper.traversals) - for field in [advector, advectee] + ( - [g_factor] if g_factor is not None else [] + for field in ( + [advector, advectee] + + ([g_factor] if g_factor is not None else []) + + ([diffusivity_field] if diffusivity_field is not None else []) ): assert field.halo == stepper.options.n_halo assert field.dtype == stepper.options.dtype @@ -75,6 +78,7 @@ def null_vector_field(): "advectee": advectee, "advector": advector, "g_factor": g_factor or null_scalar_field(), + "diffusivity_field": diffusivity_field or null_scalar_field(), "vectmp_a": vector_field(), "vectmp_b": vector_field(), "vectmp_c": ( @@ -122,6 +126,12 @@ def g_factor(self) -> ScalarField: e.g. the changing density of a fluid.""" return self.__fields["g_factor"] + @property + def diffusivity_field(self) -> ScalarField: + """Diffusivity field (with halo), unmodified by advance(), + assumed to be constant-in-time. Used for heterogeneous diffusion.""" + return self.__fields["diffusivity_field"] + def advance( self, n_steps: int, @@ -138,9 +148,12 @@ def advance( assert self.__stepper.options.non_zero_mu_coeff else: mu_coeff = (0.0, 0.0, 0.0) + + # Check for heterogeneous diffusion if ( self.__stepper.options.non_zero_mu_coeff and not self.__fields["g_factor"].meta[META_IS_NULL] + and not self.__stepper.options.heterogeneous_diffusion ): raise NotImplementedError() diff --git a/PyMPDATA/stepper.py b/PyMPDATA/stepper.py index 34c70f7a..ebb6b0f0 100644 --- a/PyMPDATA/stepper.py +++ b/PyMPDATA/stepper.py @@ -13,7 +13,7 @@ from .impl.formulae_antidiff import make_antidiff from .impl.formulae_axpy import make_axpy from .impl.formulae_flux import make_flux_first_pass, make_flux_subsequent -from .impl.formulae_laplacian import make_laplacian +from .impl.formulae_laplacian import make_heterogeneous_laplacian, make_laplacian from .impl.formulae_nonoscillatory import make_beta, make_correction, make_psi_extrema from .impl.formulae_upwind import make_upwind from .impl.meta import _Impl @@ -34,7 +34,7 @@ def __init__( grid: (tuple, None) = None, n_threads: (int, None) = None, left_first: (tuple, None) = None, - buffer_size: int = 0 + buffer_size: int = 0, ): if n_dims is not None and grid is not None: raise ValueError() @@ -144,6 +144,7 @@ def make_step_impl( n_iters = options.n_iters non_zero_mu_coeff = options.non_zero_mu_coeff nonoscillatory = options.nonoscillatory + heterogeneous_diffusion = options.heterogeneous_diffusion upwind = make_upwind(options, non_unit_g_factor, traversals) flux_first_pass = make_flux_first_pass(options, traversals) @@ -153,6 +154,9 @@ def make_step_impl( non_unit_g_factor, options, traversals, last_pass=True ) laplacian = make_laplacian(non_unit_g_factor, options, traversals) + heterogeneous_laplacian = make_heterogeneous_laplacian( + non_unit_g_factor, options, traversals + ) nonoscillatory_psi_extrema = make_psi_extrema(options, traversals) nonoscillatory_beta = make_beta(non_unit_g_factor, options, traversals) nonoscillatory_correction = make_correction(options, traversals) @@ -168,6 +172,7 @@ def step( advectee, advector, g_factor, + diffusivity_field, vectmp_a, vectmp_b, vectmp_c, @@ -185,7 +190,12 @@ def step( if nonoscillatory: nonoscillatory_psi_extrema(null_impl, psi_extrema, advectee) if non_zero_mu_coeff: - laplacian(null_impl, advector, advectee) + if heterogeneous_diffusion: + heterogeneous_laplacian( + null_impl, advector, advectee, diffusivity_field + ) + else: + laplacian(null_impl, advector, advectee) axpy( *advector.field, mu_coeff, diff --git a/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/__init__.py b/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/__init__.py new file mode 100644 index 00000000..c5d43f9a --- /dev/null +++ b/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/__init__.py @@ -0,0 +1,6 @@ +""" +Comparison between [the *py-pde* example](https://py-pde.readthedocs.io/en/latest/examples_gallery/simple_pdes/pde_heterogeneous_diffusion.html) of d iffusion equation with spatial dependence and the reimplementation with PyMPDATA. + +diffusion_equation_with_spatial_dependence.ipynb: +.. include:: ./diffusion_equation_with_spatial_dependence.ipynb +""" diff --git a/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/diffusion_equation_with_spatial_dependence.ipynb b/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/diffusion_equation_with_spatial_dependence.ipynb new file mode 100644 index 00000000..af495b45 --- /dev/null +++ b/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/diffusion_equation_with_spatial_dependence.ipynb @@ -0,0 +1,592 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cf1777b0", + "metadata": {}, + "source": [ + "# Diffusion equation with spatial dependence\n", + "\n", + "Comparison between [the *py-pde* example](https://py-pde.readthedocs.io/en/latest/examples_gallery/simple_pdes/pde_heterogeneous_diffusion.html) and the reimplementation with PyMPDATA.\n", + "\n", + "## Background\n", + "**What is a kymograph?**\n", + "\n", + "A kymograph is a two-dimensional plot of the evolution of a quantity over time and space. It is often used in physics to visualise how a variable changes along a spatial dimension as time progresses. The name is derived from the Greek words *\"kyma\"* (swell or wave) and *\"graph\"* (writing), reflecting its use in capturing wave-like phenomena." + ] + }, + { + "cell_type": "markdown", + "id": "78ed9ea7", + "metadata": {}, + "source": [ + "## Initial setup" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "46e47a0b", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c91b4ebc", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "import time\n", + "\n", + "import numpy as np\n", + "import pde as py_pde\n", + "from IPython.display import display\n", + "from PyMPDATA_examples.comparisons_against_pypde.diffusion_equation_with_spatial_dependence import (\n", + " solutions,\n", + ")\n", + "from PyMPDATA_examples.comparisons_against_pypde.diffusion_equation_with_spatial_dependence.solutions import (\n", + " SimulationArgs,\n", + ")\n", + "\n", + "logging.basicConfig(level=logging.INFO, force=True)\n", + "\n", + "original_simulation_args = SimulationArgs(\n", + " grid_bounds= (-5.0, 5.0),\n", + " grid_points=64,\n", + " initial_value=1.0,\n", + " sim_time=100.0,\n", + " dt=1e-3,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "76f14b27", + "metadata": {}, + "source": [ + "## Original example from the *py-pde* library\n", + "\n", + "We use the almost identical code as in the original example from the *py-pde* library, which is available [here](https://py-pde.readthedocs.io/en/latest/examples_gallery/simple_pdes/pde_heterogeneous_diffusion.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "209d79d2", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:pde.tools.numba:Compile `dot_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `gradient` in PDE for `c`\n", + "INFO:pde.tools.numba:Compile `gradient` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid_bcs` with parallel=True\n", + "INFO:pde.tools.numba:Compile `apply_op_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `laplace` in PDE for `c`\n", + "INFO:pde.tools.numba:Compile `laplace` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid_bcs` with parallel=True\n", + "INFO:pde.tools.numba:Compile `apply_op_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:RHS for `c` has signature ('c', 't', 'none', 'bc_args', 'x')\n", + "INFO:pde.tools.numba:Compile `_heaviside_implemention` with parallel=True\n", + "INFO:pde.tools.numba:Compile `` with parallel=True\n", + "INFO:pde.tools.expressions.ScalarExpression:Parse sympy expression `(tanh(x) + 1.01)*laplace(c, none, bc_args) + dot(gradient(tanh(x) + 1.01, none, bc_args), gradient(c, none, bc_args))`\n", + "INFO:pde.tools.numba:Compile `_lambdifygenerated` with parallel=True\n", + "INFO:pde.tools.numba:Compile `rhs_func` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `gradient` in PDE for `c`\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `laplace` in PDE for `c`\n", + "INFO:pde.pdes.PDE:RHS for `c` has signature ('c', 't', 'none', 'bc_args', 'x')\n", + "INFO:pde.tools.expressions.ScalarExpression:Parse sympy expression `(tanh(x) + 1.01)*laplace(c, none, bc_args) + dot(gradient(tanh(x) + 1.01, none, bc_args), gradient(c, none, bc_args))`\n", + "INFO:pde.solvers.ExplicitSolver:Init explicit Euler stepper with dt=0.001\n", + "INFO:pde.solvers.controller:Simulation finished at t=100.0.\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "diffusivity = \"1.01 + tanh(x)\"\n", + "term_1 = f\"({diffusivity}) * laplace(c)\"\n", + "term_2 = f\"dot(gradient({diffusivity}), gradient(c))\"\n", + "eq = py_pde.PDE({\"c\": f\"{term_1} + {term_2}\"}, bc={\"value\": 0})\n", + "\n", + "grid = py_pde.CartesianGrid([[-5, 5]], 64)\n", + "field = py_pde.ScalarField(grid, 1)\n", + "\n", + "storage = py_pde.MemoryStorage()\n", + "res = eq.solve(field, t_range=100, dt=1e-3, tracker=storage.tracker(1))\n", + "\n", + "py_pde.plot_kymograph(storage)" + ] + }, + { + "cell_type": "markdown", + "id": "7dc1823d", + "metadata": {}, + "source": [ + "## Our parametrised implementation of the original *py-pde* example" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "1c5bf44b", + "metadata": {}, + "outputs": [], + "source": [ + "class Timer:\n", + " \"\"\"A simple timer class to measure elapsed time.\"\"\"\n", + "\n", + " def __init__(self):\n", + " self._start = None\n", + " self._time = None\n", + "\n", + " @property\n", + " def time(self):\n", + " return self._time\n", + "\n", + " def __enter__(self):\n", + " self._start = time.perf_counter()\n", + " return self\n", + "\n", + " def __exit__(self, *args):\n", + " self._time = time.perf_counter() - self._start" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ba25763a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:pde.tools.numba:Compile `dot_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `laplace` in PDE for `c`\n", + "INFO:pde.tools.numba:Compile `laplace` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid_bcs` with parallel=True\n", + "INFO:pde.tools.numba:Compile `apply_op_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `gradient` in PDE for `c`\n", + "INFO:pde.tools.numba:Compile `gradient` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid_bcs` with parallel=True\n", + "INFO:pde.tools.numba:Compile `apply_op_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:RHS for `c` has signature ('c', 't', 'none', 'bc_args', 'x')\n", + "INFO:pde.tools.numba:Compile `_heaviside_implemention` with parallel=True\n", + "INFO:pde.tools.numba:Compile `` with parallel=True\n", + "INFO:pde.tools.expressions.ScalarExpression:Parse sympy expression `(tanh(x) + 1.01)*laplace(c, none, bc_args) + dot(gradient(tanh(x) + 1.01, none, bc_args), gradient(c, none, bc_args))`\n", + "INFO:pde.tools.numba:Compile `_lambdifygenerated` with parallel=True\n", + "INFO:pde.tools.numba:Compile `rhs_func` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `laplace` in PDE for `c`\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `gradient` in PDE for `c`\n", + "INFO:pde.pdes.PDE:RHS for `c` has signature ('c', 't', 'none', 'bc_args', 'x')\n", + "INFO:pde.tools.expressions.ScalarExpression:Parse sympy expression `(tanh(x) + 1.01)*laplace(c, none, bc_args) + dot(gradient(tanh(x) + 1.01, none, bc_args), gradient(c, none, bc_args))`\n", + "INFO:pde.solvers.ExplicitSolver:Init explicit Euler stepper with dt=0.001\n", + "INFO:pde.solvers.controller:Simulation finished at t=100.0.\n" + ] + } + ], + "source": [ + "with Timer() as timer:\n", + " py_pde_result = solutions.py_pde_solution(original_simulation_args)\n", + "py_pde_time = timer.time" + ] + }, + { + "cell_type": "markdown", + "id": "c2abbc5f", + "metadata": {}, + "source": [ + "Verify that the parametrised implementation produces the same results as the original example:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "42c6278f", + "metadata": {}, + "outputs": [], + "source": [ + "assert np.allclose(\n", + " res.data, py_pde_result.extra[\"final_result\"].data\n", + ")\n", + "\n", + "assert np.allclose(\n", + " storage.data, py_pde_result.kymograph_result\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ed7199bc", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAG2CAYAAACtaYbcAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUmVJREFUeJzt3QuYHFWd9/FT3T2X3LmZhHBfFwWWmxJBxBuSNa48akTd4LISEeO6LyAQFQhqEGWNohuzSgRXBcSFNd7AVdiwGDcgGgSDuoCKomAimITI5s5kZrrqfU7FmZ2Z1O8kp7qmq6r7++GpJ0x1d1V1Tc/UmfO/VBBFUWQAAAByUslrxwAAABaDEQAAkCsGIwAAIFcMRgAAQK4YjAAAgFwxGAEAALliMAIAAHLFYAQAAOSKwQgAAMgVgxEAANC+g5F77rnHvO51rzPTpk0zQRCY2267bdjjtlP9ggULzP7772/GjBljZsyYYX7zm98Me84zzzxjzjrrLDNx4kSz1157mXPPPdds3bq1ye8EAIDyu2c31+UkK1asMC984QtNV1eX+cu//Etz4403lmswsm3bNnPccceZJUuWJD5+9dVXm8985jPmuuuuMz/+8Y/NuHHjzMyZM01PT8/gc+xA5JFHHjF33XWX+e53vxufyHe9611NfBcAALSGbbu5Lo/0+OOPm9NPP92ceuqp5mc/+5m56KKLzDvf+U5z5513eu03KMqN8uwI7NZbbzWzZs2Kv7aHZUdm733ve8373ve+eN2mTZvMlClT4lHXmWeeaX75y1+ao446yjzwwANm+vTp8XOWLVtmXvva15o//OEP8esBAEDj1+Ukl156qbn99tvNww8/PLjOXp83btwYX4/3VM0UlB1trV27Ng7NDJg0aZI56aSTzMqVK+M3a/+1oZmBgYhln1+pVOKZlDe+8Y2J296xY0e8DAjDMA737LvvvvHJBwAgif1DecuWLfEfu/ZaM1p6enpMb29vZsc88tpmQyp2aZS9Dg+9Tls2gmFnSHwUdjBiByKWnQkZyn498Jj9d/LkycMer9VqZp999hl8TpKFCxeaK6+8clSOGwDQ+tasWWMOPPDAURuIHHbIeLN2fT2T7Y0fP36XXMorrrjCfPjDH2542/Zam3Sd3rx5s3n22WfjfM9SD0ZG0/z58828efMGv7bhn4MPPti84tB/MLXK8JFi/34TErfRu3en3H7vpGry+nHJsy793cnrQ7GLMMV3LRDBuEpf8vqqGJBXe3RUr+PZ5Mdq28Pk9c+K9dv6E9dXnk1eHz/Wk3zAQa94g2p9f/IPf9Sv923C5Pdh6mJbKjKqtuOKpKrXCJkGZcMcI7yR3/vOU5TneSrb+StG1oBTv+kz95o7zIQJydeGLPT29sYDkd+vOtRMnNDY7MvmLaE55IQn4sGTLfQYkMWsSJYKOxiZOnVq/O+6deviapoB9uvjjz9+8Dnr168f9rr+/v445DLw+iRqesoORGrVEetr3YnbCDv0YKTekTwYqXYmDzqiruT1gdhFkOVgRHzOk9+BMVXHL9ZqvxiMdIhBR59YXxODkaoYQMSPiXOo3qBcn7zvyDUdq36xB2IwYsQ5DNQFwvELWr5GbSnDX/bqQ9UUBb2YJohyPU9lO39FPFfJh9iMkP74CUG8NCI0O19vByJDByNZsddae10eyn5t97WnsyKF7jNy2GGHxW9y+fLlg+vstI/NBTn55JPjr+2/Nklm1apVg8/5/ve/H+eA2NwSAADKqh6FmSyjyV6Hh16nLVvdOnCdLsXMiI1hPfbYY8OSVm1pkM35sGETmwBz1VVXmcMPPzwenHzoQx+Kk4YGMnuPPPJI85rXvMbMnTs3Lv/t6+sz559/fpzcmmclTaQGsp7rozRDRbUtz2P1fg/ObQXZ7Nt1Pkg8br6KOOfNCEsElXKFH4AUQhPFS6PbyPK6bNMcnnzySXPTTTfFj7/73e8211xzjbnkkkvMO97xjnhC4Gtf+1pcYVOawchPfvKTuDZ5wEAex5w5c+LyXfvmbM2z7RtiZ0Be+tKXxqVC3d3/Fzq5+eab4wHIaaedFmc2v+lNb4p7kwAAgGyvy3/84x/N6tWrBx+3EwV24HHxxRebf/mXf4mTer/4xS/GFTWl7DOSJxv+sWXDp/3Fe3bJGel/TnKMrXcfnTPSs1dyxkXfeJHAOiZ5fb0rxYyJmiDwTWD9v8rnYWqOBNba9uTHOsT62va6VwJr9VlHzoh4LBCJrTqBtd8/gbVepgTWJvy4k9g6DAmsHkpwOeqP+swK8+248GE0cjCGXpOeevTATBJYpz3/D6N6vC2dwFoYnqGH3MM3gVcupQx9qH3I9+DYtyu0k5s2DeuopDv+JkGhfy7b9PNZj6J4aXQbZVDYBFYAANAemBkBAKCAwhwSWPPCYAQAgAIKTWTqDEbaNF65p7kEGeZOZFle65tnIvPYUpX2qhJe1eQryGa947FIlJ+2TMaIasbmmdjaMgpY8huIz2Cuia3qPBU5uRUtjcEIAAAFFBKmAQAAeapTTQMAANAczIzsTqp+Iip3QuU1qH17rnfkmci3kVF+S6bbynOILPNVXAcV+rVLr5fjL5VStokHWkiYwS0Ny5IBxGAEAIACqmdQTdPo65uFwQgAAAVUjxqfSC3LRCyDkZRS3R8mq5LfDO9N05y79vpvK/n5+gUqBKban8tQQhoyHJPdLgCglTEYAQCggEJyRgAAQJ5CE5h6gy0a7TbKgNJeAACQK2ZGdtMOPsvciaxySVLtu+J5x27VVduVa+Hd9l3sI0U5dZmoPBaZZ+Y6Hxk1NJLHlGXDpDxLfkvUJj73VvEojDBq/MejLB8lBiMAABRQPYMwTaOvbxbCNAAAIFfMjAAAUED1NpoZYTCyO56t3Xe+ZnT7cESVyL8dvHggs/wWV56Jdz8R/+04u7WXRUW8ibAsxXkAshRGQbw0uo0yaIVf4QAAoMSYGQEAoIDqhGnQiKxCH6nCHp6hHVlemCJU4h1u8i3hTdPCXZYVqzbx4qRXHKGSIkZRCPnsGVd8L8ey31wVsAy6XdVNJV4a20Y5MBgBAKCAogxyRuw2yoCcEQAAkCtmRgAAKKA6OSNtKqEdvJw7SpO3kVFpbzP2rfJVstx3pu3gi9hCXuYjlCWKq9vEZ9oq3pULVJZe1sAoqEeVeGlsG6YUCNMAAIBcMTMCAEABhSYwYYNzBqG+BWehMBgBAKCA6uSMYHey7Lfh2xvEGUL0axsiA3XeuSSunWSUl5JpLkmWOSZyW+X4iwTFo/r/ROTQoEUxGAEAoGUTWCNTBgxGAAAobM5I0PA2yoDByG7I0ECKEtdRL/nNch+e20+1j6yOKd5WRj9wRSwRTnO8JflrKHXZbzPCFbRFL45W/5yDwQgAAEUUZnBvGqppAABAanVyRgAAQN4zIyEzI23IxqfT3KZ+pKxarKfJqQg8w9+yfFiUFmaaK+N5rtN8a7L4fu6uLXpWx9SMvs0V8UEIw8zOSWZt4gG0DQYjAAAUUD0K4qXRbZQBgxEAAAqonkECa70kYRpulAcAAHLFzMjupMjb8O23oXJJvHNMHI+pML5MhUjRDl6+D9mrJfLLqXDlbYjHghL1E5E5GCrPI2WuB8or1zbx9F1pujCqxEtj2yjHzAiDEQAACqhOmAYAAKA5mBlJyzXNn9Fde9OESlToIxAbyzJE5BuO8Q5nNaNNfKo7A4uTJcqmTd1/FxiBNvFoA2EG1TBl+VQyGAEAoGWbnlVMGZTjKAEAQMtiZgQAgJa9N03FlAGDkZH5AiNyBlQeRJrS3szavquSWFeuR0alvanKir33kSJGOto/bwUsBc4UbeKBwglNEC+NbqMMGIwAAFBA9TaaGSnHUQIAgJbFzAgAAC3b9KxiyoDByO40IXciUv0oUvUZEevFPmROTCXDfWfVT8TZ28WvhXwk+lSUI7q6B9T5aPW8jTz7jwAZC6MgXhrdRhmUY8gEAABaFjMjAAAUUJhBmKYsTc8YjIwC3RZdPT/Dluyenztd2usX1nHtW78Pv/PUlJ8pNc3fjHbiLd4nvuVLfnNsE5/r3XxR8Lv2VkwZlOMoAQBAy2JmBACAAqqbIF4a3UYZMBgBAKCAwjYK0zAY2W07+OSnRk1pix6lKK/16/vun+ehd+17rjKtOJNt+0UJb5bt3WU5aXa7aEYbd6/tZ7kPlFuOuTJoHQxGAAAooHoGYZaypMUzGAEAoIBCwjQAACBPdW6UVwz1et186EMfMocddpgZM2aMee5zn2s++tGPDutLYP9/wYIFZv/994+fM2PGDPOb3/xm9A8uyG6xn5WkRb7GtnaXi0lcbMv5pEVuRx2rY8nynCTvO5DLqLO5E2rZXQ7SyEXuI0hcbH6LWrz5HlMTZPr+PM9t03IqkhagoJYsWWIOPfRQ093dbU466SRz//33O5+/ePFi8/znPz++Bh900EHm4osvNj09PV77LPRPxCc+8Qlz7bXXmmuuucb88pe/jL+++uqrzWc/+9nB59ivP/OZz5jrrrvO/PjHPzbjxo0zM2fO9D4RAAAUSWQCEza42G34WLp0qZk3b5654oorzIMPPmiOO+64+Jq6fv36xOffcsst5rLLLoufb6/TX/rSl+JtXH755a0zGPnRj35k3vCGN5jTTz89HqW9+c1vNq9+9asHR2l2VsSOyD74wQ/Gzzv22GPNTTfdZJ566ilz22235X34AAA0HKapN7j4WLRokZk7d64555xzzFFHHRX/oT927Fhz/fXXy+v0KaecYv7u7/4uvk7ba/Rb3/rW3c6mlGow8pKXvMQsX77c/PrXv46//vnPf27uvfde8zd/8zfx148//rhZu3ZtHJoZMGnSpHhaaeXKlXK7O3bsMJs3bx62+E7vusIVvktm4ZvAFY4R4Rt1XKn27fcafU5EKMYZwhHnVrxvGa4oYBgDABo18ppnr4Mj9fb2mlWrVg27plYqlfhrdU2112n7moHBx+9+9ztzxx13mNe+9rWtk8Bqp37sSTviiCNMtVqNc0j+6Z/+yZx11lnx43YgYk2ZMmXY6+zXA48lWbhwobnyyitH+egBAEgvjIJ4aXQbls3lGMqGVT784Q8PW7dhw4b4Opt0Tf3Vr36VuH07I2Jf99KXvjSOVvT395t3v/vdrRWm+drXvmZuvvnmOCZlY1df/vKXzac+9an430bMnz/fbNq0aXBZs2ZNZscMAEAW6n++a2+ji2Wvc0Ove/Y6mIUVK1aYj33sY+Zzn/tcfJ3+1re+ZW6//fa42KRlZkbe//73x7MjZ555Zvz1McccY37/+9/HMxtz5swxU6dOjdevW7curqYZYL8+/vjj5Xa7urriBQCAdjBx4sR4cdlvv/3iKIS9hg5lvx643o5kK17f9ra3mXe+852D1+lt27aZd73rXeYDH/hAHOYp/czI9u3bd3kj9kSFf25DbUt+7QmyeSUDbFjHVtWcfPLJ3vtLzlUY/TJW37wNlRcS54b47j+jXJI0uSGZlvbmWbrZrnxLnYuo0tqfncCWhicsLaPFc7zCP4dpGl32VGdnpznhhBOGXVPt9dZ+ra6p6jptDW3DUeqZkde97nVxjsjBBx9s/uqv/sr89Kc/jTN93/GOd8SP2z4EF110kbnqqqvM4YcfHg9O7Cht2rRpZtasWXkfPgAAqYWmEi+NbsOHLeu1kYfp06ebE088Ma5YtTMdtrrGOvvss80BBxwQRygGrtP2uvyCF7wgLh557LHH4uuwXT8wKCn9YMT2E7Fv6v/9v/8X1zjbQcY//MM/xE3OBlxyySWDU0IbN26Mk2iWLVsWN2sBAAB7bvbs2ebpp5+Or7O2EMSmPNhr6kBS6+rVq4fNhNjWGnZiwP775JNPmuc85zmDEwk+gshnHqVF2dCOLQl+1VHvN7Xq8FySngPGJ77m2efocVzPPskj0V4Rrusbn/wtqI8Rd+3tcNwNU8zIBWHyA0Ff8vpKT/L62nY95dexTazfkvw+OreK9VuS319tm77lU217X+L6yvbexPVBT/Lzg97k9aavX+476heP1cXx1kO/u5yG+kdU/vj63lE3y18DGd7NN9dfT47znokc72objfZ727mT0d+H3Pfovb/+qM+sMN+Ok0B3l4PR6DXpH39whuka39HQtnZs7TPXvuxbo3q8WSj0zEiRuVqQyxCd93rxA+UKAYrH4nySJGoGT70/x4yfet+q547v8z0bCf75NcHorv9zuDCJ/HWoYvZZ3l5T5W6ogYJ6fzn/rSLPbSv8DeVqCZ/nhRwtWdpbdAxGAAAooCiDu/babZRBOY4SAAC0LGZGhhoobR0q1Z1RMwo/pAlXqHCMyBnxPVbnjJ/v8fqud2jKnXuzmoaPsozHFJBviKioVDitGfkWrUB+/kv2OchR3QTx0ug2yoDBCAAABRRGjed8lGXsTJgGAADkipkRAAAKKMwggbXR1zcLg5G0UpTXepfdylwSx7yb67HE56sSXtHjxFnaG3iu991OmnOu3l9Qnhh7RcfYA9WypBVKX9u15LcJXC3hm9KDBHskNEG8NLqNMijHkAkAALQsZkYAACigehTES6PbKAMGIwAAFFBIzgh2n9eQ4WuyyiVxPea5D9m3w/W+K6Pcf8SV5+GZryK3lKIdfCvdstzrvfnmZ7RK/5FmoEcH2gyDEQAAiprAGrVHAiuDEQAACijKoJrGbqMMGIyMnJIeOS2dpmW5b0jEu018hqW9nnfnTRN+zOxuvln+TDUjtFLxfSNNKKls8VBJU0p+aROPJgnb6K695chsAQAALYuZEQAACiikmgYAAOQpbKMwDYORlNKU9nrnnwSRd15IoPJS5AtUHovat6ONtGfui/95cuxb5tfIlyRvR7w/V/tsjFIeSwvlsgBwYzACAEABhW10bxoGIwAAFFDYRmGacmS2AACAlsXMyO5k2GfEu+17xS8vZHePJe9bPKB6gLg2FoxuLolzgO/bNyTLPiNZ9e5QeSn1gvbbUOcwy31kpGX6jzShTbzKj4roo9J0YRvNjDAYAQCggMI2GowQpgEAALliZmQ37eDVXV/dIYOsSln979qrZnFVgMX7zsCO4Wt2pb3+dwzWdwbOMXyTFf1NNaYipud9p9SL2ia+qMeF0fk8c1fitp0ZYTACAEABRRmU5pYl04fBCAAABRS20cwIOSMAACBXzIyMAt9yWd/1zvJdkWci25mr9vGe63duK8imfDhNObUic35E23fP7bh3rfat3niKGt4iaoGS30zLfptR8ouWFLbRzAiDEQAACihso8EIYRoAAJArZkYAACigsI1mRhiMjMgj2CWXIEX+gmxnLp+v8jz81lsVsS1Vva+2Jd+Dq0VARu3d1T5UnofrMbWPLHNDCtmbJKu26KrPR969Pug/0vQ28aVSorwllygK4qXRbZQBYRoAAJArZkYAACig0AQNNz1r9PXNwmBkN3xbnDv5tlgXIRcVinGFXVTXcO8SXld4St592DNWkuWdkrOaE2xGKEbuI2qNctKSTZ035U6/JcLdfJsvbKOcEcI0AAAgV8yMAABQQFEbJbAyGAEAoIDCNgrTMBhJyfn9TVEWm1lpb8W3tFdtSOWSyF17t3ePMnr+ztcEnvkqnutdfLeljkl1g1fPt8IcSzqLWF5bxGMyab6v5GHAtNXMCDkjAAAgV8yMAABQQFEGYZqyzIwwGAEAoICiDCrfyxLwYzAyMmg1MnCVYTt41TdE5WeofI7A0WekohqKiIhcKI9JbSbyb8nu295dHVOaPJ2s+oOUqOV76XpquM5tAXt6lKr/CG3iURIMRgAAKKDQBPF/jW6jDBiMAABQQFEbVdMwGNkN37vBZtrmXLWDT1Haq4p7VYtnWT6corTX9/mRajvtvGuveECu9yy7bUaZqZxSr2d4TE1oE1/E8toiHlPZ2vk3A2GltsVgBACAAgqjwAQ0PQMAAHmJogyqaUoymUbTMwAAkCtmRoYKPEo4s2wHL/IzKmlyRjxLdeW2ZDt4V2lvRm3fU5RT++Z6qPwTWbbp2L7Ku1E9+OU+CtgRQB1r7mW/Bfxzr1QlvxlSn/+o1fNbmiAigRUAAOQpYjACAADyFLZRAis5IwAAIFfMjOxOijbjMjfEMxdC9frQLd+NqarHxK3mVc6I2rdrkK1zYjyf75tL4swzKcdfBU6u96DOYVjAfg1Z9vrIKpdEHVORe5CMZj8Pi54ehRG1UTUNgxEAAAo7GAka3kYZEKYBAAC5YmZkN1KVmcoSV7+QiAqhVB137a16toOvi2lq3Q7eMcyWoR0Vh8oozBU/5tm2X+5DHatj52lek3hM4vkZdoP33rejPLNdS1l9ZXqe2rVNfJuKqKYBAAB5iv68NLqNMiBMAwAAcsXMCAAABRQRpmlTNrabQTt47zwTlUsSZFjaKybB1LZUW/l6inbwvqW9uq18kF1pb54lv3m2OC/iLdqzLK/N8txmWYoMpBG1T5ym8GGaJ5980vz93/+92Xfffc2YMWPMMcccY37yk58MSwJbsGCB2X///ePHZ8yYYX7zm9/keswAADQs2jkz0sjibNAkLFmyxBx66KGmu7vbnHTSSeb+++93Pn/jxo3mvPPOi6/DXV1d5nnPe5654447Wmcw8r//+7/mlFNOMR0dHeY///M/zS9+8Qvzz//8z2bvvfcefM7VV19tPvOZz5jrrrvO/PjHPzbjxo0zM2fOND09PbkeOwAAZbN06VIzb948c8UVV5gHH3zQHHfccfE1df369YnP7+3tNX/9139tnnjiCfONb3zDPProo+YLX/iCOeCAA1onTPOJT3zCHHTQQeaGG24YXHfYYYcNmxVZvHix+eAHP2je8IY3xOtuuukmM2XKFHPbbbeZM888M5fjBgCgjB1YFy1aZObOnWvOOeec+Gv7h/7tt99urr/+enPZZZft8ny7/plnnjE/+tGP4okDy86q+Cr0zMh//Md/mOnTp5u3vOUtZvLkyeYFL3hBPOIa8Pjjj5u1a9fGoZkBkyZNiqeVVq5cKbe7Y8cOs3nz5mGLFCQvkWMxNt8icUnels0NSVpsn5GkpepcQr8liBIX22ckaYk/MZ6L7a+StKjzke6ci0Ud10B+0IglEovJckmT5yEXsY+KWHxV/Ldl+2okLQD8RBmEaQYSWEde8+x1MGmWY9WqVcOuqZVKJf5aXVPtdfrkk0+OwzR2IuDoo482H/vYx0y9Xm+dwcjvfvc7c+2115rDDz/c3HnnneYf//EfzXve8x7z5S9/OX7cDkQsewKGsl8PPJZk4cKF8aBlYLGzLwAAtKqDDjpo2HXPXgdH2rBhQzyI8Lmm2uu0Dc/Y19k8kQ996ENxOsVVV13VOmGaMAzjmRE7yrLszMjDDz8cTxvNmTMn9Xbnz58fx8QG2FEiAxIAQKFE6RJQd9mGMWbNmjVm4sSJg6ttomlW12kbufjXf/1XU61WzQknnBAXnnzyk5+M805aYjBiM3OPOuqoYeuOPPJI881vfjP+/6lTp8b/rlu3Ln7uAPv18ccfL7drvwlJ34i4iipovB28Lk1VpbrGq+xWl+/qVvGBeE2fKu31bF3ven+qJFeW9qZqBy+25dkmXt7MNMswg2rBL4K7UVlq80ZDVuW1BSz5dYWuvFvFZ9kmPqPy70D93Od4TO2cMzJx4sRhg5Ek++23XzygsNfQoezXA9fbkey11+aK2NcNvU7bmRQb9uns7Cx/mMZW0tjM3KF+/etfm0MOOWQwmdWeoOXLlw+b5bBVNTaGBQAA9owdONiZjaHXVDvzYb9W11R7nX7sscfi5w29TttByp4ORAo/GLn44ovNfffdF4dp7Ju95ZZb4qkgmygz8JfFRRddFMembBLNQw89ZM4++2wzbdo0M2vWrLwPHwCAxpueRQ0uHmwKgy0UsbmZv/zlL+NczW3btg1W19hrrE11GGAft9U0F154YTwIsZU39po9cJ1uiTDNi170InPrrbfGb/wjH/lIPBNiS3nPOuuswedccskl8Yl617veFTdeeelLX2qWLVsWN2sBAKCsohzawc+ePds8/fTTcTNRG2qxKQ/2mjqQ1Lp69eq4wmaAzbe0BSZ28uDYY4+N+4vYgcmll17qtd8g4n7fcWjHZhe/8oT5plYbPojZesjYxNdsnfZ/8bGReiYnn9LefZJLnaqTehPXTxiX3LhtbFfy863Oat3rA7m9b2dd+EjbepKn157d5kh62py8rdrm5Am4zk3Jx9S1Mfn8dW7WH9XOLcmx445t/Ynrq9v6EtdXdiQ/P+hJfn78WF/ya4wqbeuvez3f+SOq9qFe4xuvTxOT99xHpr+CsmzV7ntcGe47s3OSJj9DySg/I1XOiN5Yhtvas+Pqj/rMCvNts2nTpt3mYDR6TTr4XxeYytjG/rAOt/eY1e/6yKgebxYKPTMCAEBbi0xbYDACAEABRdy1FwAA5Cpqn7v2MhgZKqnNtbwFvd6Mb2+SiuoNItarXiJWTfQNCcVBdYgckzR9RkL1mGffEO/+I65tqe+fb2t0x/NVH5VAdUOWn6kUvTBkYxQRS5dPz+83Vqb9NlqhJ4rjnOTafwQYRQxGAAAopGA33R73dBvFx2AEAIAiigjToIF28PIx2apdhGPkelc7eNHeXRyUCvmocI8rTKNCAJFv23wZxnC0oleV1t778Fzv0gp3qpVhIEdZZZ6hgQxDJZm2kG8FbdqSHc3BYAQAgCKKmBkBAAAtctfeoiv0vWkAAEDrY2ZkRB7BLrkEMufAsaHAb+gnS3hF3obK50hT2qv2UVHrHXkbdc/SXlmqK5/vKAFVpZCeOT9qO0GWuSGez3eWvmY1B5smz8M3hyDFPrIrcc0wl6QVSn5zFLh+jik5HsZ+Wxv91pblo8FgBACAIoraJ2eEMA0AAMgVMyMAABRR1D4JrKkHI4899pj57W9/a17+8pebMWPGxDFLV2y75aRqBx95tV5X+Ryql4hVE4+F4nujckxUj5NK1RHnFq+JZC6JiH9XsszT8ewbIlvXN6HPiMotqKu+8q48DM828WUJLBchdyKr/iPq+92MXBbX7RDI2yiMIHK2V9rjbbRkmOZPf/qTmTFjhnne855nXvva15o//vGP8fpzzz3XvPe97x2NYwQAoH1zRqIGl1YcjFx88cWmVquZ1atXm7Fjxw6unz17tlm2bFnWxwcAAFqcd5jmv/7rv8ydd95pDjzwwGHrDz/8cPP73//etBrdsjy70l4ZpvFs1b7zMceUfoLeoOpZ8puiHXw1m7vzuu7a6xva0aE0VSKsv+He4UkZWvE7pp0HFhVvOj+rkl/XPrKSZagkx/bx+YatcmwT3+ot6iNyRqRt27YNmxEZ8Mwzz5iurq6sjgsAgPYWUdorvexlLzM33XTTsBF5GIbm6quvNqeeemrWxwcAAFqc98yIHXScdtpp5ic/+Ynp7e01l1xyiXnkkUfimZEf/vCHo3OUAAC0m6h9Zka8ByNHH320+fWvf22uueYaM2HCBLN161ZzxhlnmPPOO8/sv//+ptRsaG1keM2znXia0l7vdvCu0l5HPkmSzmpyjklHipyRQJb2euaAZHjOZQv5IKOS3zTb8t2O8yV+5dGZlvz6tndPE9/33EemuRMt0kIeJRYxGHGaNGmS+cAHPpD90QAAgLaTajDS09Nj/ud//sesX78+zhcZ6vWvf31WxwYAQPuKqKaRbC+Rs88+22zYsCFxirTu6hYJAAD2SNBGHVi9ByMXXHCBectb3mIWLFhgpkyZYlqd7y3odz4m4tmqxbpqEy/7jOgBnyufJPn5db9W9K6cFNn23a9NvMrziFLlbYjne/Ylcf5tIY83eX0QZtQm3hrtwX+ePU4y1BLt45vFNxcoQ4H6WaJFfcvzHoysW7fOzJs3ry0GIgAA5CZqnwRW7z4jb37zm82KFStG52gAAEDb8Z4ZsSW9Nkzzgx/8wBxzzDGmo6Nj2OPvec97TGnZ6dQ9LK905QT5lqz6lvC6yne7Kv2J60Ox81ql6nk3X73vSjXyqyZtQjt4dc5le3ffUuC8p/N9X+N7l980bbWzKvl17T+jUIKrlb8M4ZSo5DfX8BSy6TYRNb6NlhyM/Pu//3t8f5ru7u54hmToh93+f6kHIwAAoPiDEdtf5MorrzSXXXaZqbgS6wAAQHoRpb2SbQE/e/ZsBiIAAIymqH0SWL0HI3PmzDFLly41l19+uWkLqUp7xWpRylqtZNkOPrnUMxRJFZ3i+R1ivTpWV1t7XcKbUZt4Vzt42S5drE/T2t33Nb75Kin+smlKrkBm+SqunBjPXJYcy1K9c0nKVjbdjPb/aFvegxHb1MzeLO/OO+80xx577C4JrIsWLcry+AAAaE8RMyPSQw89ZF7wghfE///www/vcWY6AADYcwEdWLX//u//Hp0jAQAAbSnVjfLaKXFZ5hykyRmR61Xb99ArnyN+TOWTiPX9IkFD7btW1fuuVFUcX+SMBKPfZySqZpMLJHNJXDOCafJPRjtPIav+I/G2PHMhMs1XGf1cklL16Mio/0hh31+7igjTDHPGGWeYG2+80UycODH+f5dvfetbWR0bAADtK2IwMsykSZMGR9L2/wEAAJo6GLnhhhvMRz7yEfO+970v/v+2kmJGXZWyqrvw6hLeemalvfL5Yhq3U7SVrzqyoSryrr3Gb70M3wQZtoM3nmW3ctcyhCOn+X3v5pthCWimoYesSjcd39emlOR68j6HadrHl+1OvxgVQRslsO5x5zLbdXXr1q2jezQAAGB4ImOjSyslsJLUBABAE0XtkzPi1dOdPiIAACDX0t7nPe95ux2QPPPMM6a07Hsb8f50boFrO2rzImck09Jev5yRLpEbIvftKu2teJb2VlWbeJVrIXftn2ci28Gr7Tu+4TInRrxGnULfNvGuA/Yt9VSbd51z33yONHkQo92CvGT5Kv4t+P3zVfxzYjL6HsU7EZ9P9fOaZSv6AubpBG2UM+I1GLF5I1TTAADQBFH7hGm8BiNnnnmmmTx58ugdDQAAaDt7PBhp23wRzy6hsYrfXXtVya8q4VUlv2nCNH0i5CP3rUIxNtwkOrAGMhzThA6svuGbLO/am9Xz02yrGVPLvl1bfTu2xq8Z5dCAa9recx+ZlfzG++DOtjDxrEbDYZZWmxmhmgYAgCaKCNPsImSkDgAARgE3ygMAoIgiZkbaU8Wj84qz2lLkhlT82sGrXBJXXogq+62IT2SfuK2tKvl1lRXXfEt7fe+0myZnxDeXpOp/l+bM7tqb6i6/KkdidEt+4z1ndQfgLMstm1BmOuq5JGlKcrMq+XXtA00XtFFpr1fTMwAAgKwxGAEAALkiTAMAQBFF5Iy0JXsr+JG3g5e5BRm2g/dt++7q9aHySVTOiG4H77/vquqjIvqMhLL/iF+b+J2PqfUqd0JsSOaS6EnESPRk8c0lUccauD5sMn9BPN+3RN+RryJbyHvvI0XexmjnkriOK6NckrIZ9Tbx2AU5IwAAAE3CzAgAAEUVmbbAYGR3MrxrryztlW3fRfgmRTv4itqWZ2lvp1hv1cQdfdXdfOvifJgs28HL0l5VwqtCK3rf8njFttQdSE2YZSv60S35TTWdr75/WYZKsgrf7O64MuC6xYZ3C/msSn7T7CNLadr2t7KofXJGCNMAAIBcMTMCAEABBW2UwMpgBACAIoraJ0zDYGQoG14dEWKNUuWMqHbwYSalva6cka5Kn/HRLZ6v9tHpaAffId5H4JsbUvVsE58mZ0TtQ5b8psjbqGaYG+K7b9+SXyVN23CRj+CdS5KmjXtWuSQuTSj59S+jzS/PI1W7+6z2Lc5tRPlw6TAYAQCggII2CtOUKoH14x//eDwKv+iiiwbX9fT0mPPOO8/su+++Zvz48eZNb3qTWbduXa7HCQBAZmGaqMHF05IlS8yhhx5quru7zUknnWTuv//+PXrdV7/61fgaPWvWrNYdjDzwwAPm85//vDn22GOHrb/44ovNd77zHfP1r3/d3H333eapp54yZ5xxRm7HCQBAWS1dutTMmzfPXHHFFebBBx80xx13nJk5c6ZZv36983VPPPGEed/73mde9rKXtW6YZuvWreass84yX/jCF8xVV101uH7Tpk3mS1/6krnlllvMq171qnjdDTfcYI488khz3333mRe/+MWN71yFmlUehGOIpzICKqpNvMjbSNNnpCqSBUIR//ZtEx/vQ+SMVKsibq3awadowS/bvotzq9vE+7Vqdz3m2w7et018/JK6bz8RsSHf7aTJU/DMJUnVmySrXBJrtPedY48T5/se7VyPPN932UTNT2BdtGiRmTt3rjnnnHPir6+77jpz++23m+uvv95cdtllia+p1+vxNfrKK680P/jBD8zGjRtbc2bEhmFOP/10M2PGjGHrV61aZfr6+oatP+KII8zBBx9sVq5cKbe3Y8cOs3nz5mELAABFzBkJGlyskdc8ex0cqbe3N76uDr2mViqV+GvXNfUjH/mImTx5sjn33HNTv9fCD0ZsDMpOFS1cuHCXx9auXWs6OzvNXnvtNWz9lClT4scUu61JkyYNLgcddNCoHDsAAEXIGTnooIOGXfeSrqkbNmyIZznsNXRPr6n33ntvHKGwkYtGFDpMs2bNGnPhhReau+66K06kycr8+fPjmNgAO0q036iku/bKME2K0l4VxvANx3Q4WrL7hmnU81WYpssRplFlvzJMo+7OK+/m6z+lHoryWu87A7uG7Sq04xmO8W4T79iW9xR8lqWvGYVvMm0tn6bNuG+oK8t9q9CfPIVNKPlthTbxae4Q3SLWrFljJk6cOPh1V1dXw9vcsmWLedvb3hYPRPbbb7/WHYzY6SKbNPPCF75wcJ0dtd1zzz3mmmuuMXfeeWc8rWTjU0NnR2w1zdSpU+V27Tchi28EAABlyBmZOHHisMFIEjugqFaru1Skqmvqb3/72zhx9XWve93guvDPg9NarWYeffRR89znPrf8YZrTTjvNPPTQQ+ZnP/vZ4DJ9+vQ4UWbg/zs6Oszy5csHX2Pf/OrVq83JJ5+c67EDAFCUnJE9YdMeTjjhhGHXVDu4sF8nXVNtjubIa/TrX/96c+qpp8b/75MCUeiZkQkTJpijjz562Lpx48bFPUUG1tuEGRty2WeffeJR3wUXXBCftEwqaQAAaCPz5s0zc+bMif/YP/HEE83ixYvNtm3bBqtrzj77bHPAAQfEOSc2fWLkNXogSjFyfakHI3vi05/+dJzta5ud2exgWw/9uc99LrPtp2oHL+abqiJPoebbJt5R2tsZJOd6VETOSJeIA/vmksSvqda93kegckNStIMPPdu7+693lJ/KHBDjmXPg3yZelhWHWeVBGH9Z5i9k1VreN58j3pjnm/dt+57hvjNtyZ5R/lCebeJbRtT80t7Zs2ebp59+2ixYsCBOWj3++OPNsmXLBpNabeTBXnOzVrrByIoVK4Z9bUdmtlucXQAAaBVBTu3gzz///HjZk2vwSDfeeKP/DoueMwIAAFpf6WZGAABoC1HzwzR5YTAylA1xBnvaDt6xGZEbEsi27365IZm2gzfJOSDdlT7vdvCdqoW86DMSiPWyz0jVf47PNwdErne2DVd5GOq+AJ6tyauu3ALVL0Xswtkgx3PuNBzlXJIMW8t755LEG/NMpJHvzzOXxCWrbaU5577bStXLJMNz1Qqi9hmMEKYBAAC5YmYEAICSTNb7avT1zcJgZAg7gz1yFjtVaa9vO3gR+kgXpkkOlVTFXF3dZFfa26lKe8V679Jex52SVdt37/CNZ4lw/JjvLQNk+Mb/rrbe7eB9n++SZTlwTncGdn1f/UtyMwrfxJvK5g7A3u3jcyz53bmpbGIK6tYKUdnCPVH7hGkYjAAAUEBBTqW9eSBnBAAA5IqZEQAAiigiTIMBKXJGVGlvVcyXdYjAblWsVy3fdz5W92oHr3SJ0l5V8hvvW+STdIhcmYpYX09R2qse828TL2LNKifFEo9FoiQ3qIvvhdqHqxxXlf2KfXi3j29GLokrT0C2rx/dXJJsW8t75pI4S1w9c0kE9/uuFK/kV1Hn3LeVf5FFpi0QpgEAALliZgQAgAIK2iiBlcEIAABFFJEz0p5snHZErFa3B4+8w5g1lTshc0lGv8+IovJSuhz5Kl2qX4rqP1JLPh99IufG2evDu+27er7atyvGLvIwMuoz4mpFL2P/nutl+/g8c0lS7SO7PIUgr1ySeCeeVxC1D/E7J10r+mzydFKhTXzLYzACAEABBYRpAABAriLCNG0pqR28aUI7+A7vdvA6VNJhxF17Pefbu4PkEt4ORzt41Spevb+quGuvSVPa69ve3bftuzNE5HsHYONV2uu80656TIaV/KbanXenziq8kqolezD64Ruxj9EP38QvSl6d5u7DidtxhP6ybCHvSbbtb8K+pV2OyV4ocjqWFsZgBACAAgoI0wAAgFxFhGkAAECeIgYjbSrYJT4obw/vuJ29KtWtiWBszbOEV7V8dz1W8Qzwq313O0t7k/NMOlVpr8ihCVTOSE2fc9Wu3b9NvF/+h2vf3m3iU+RHqH0H3nW0/jkVTSkHli3yxbny3bfKJYm3FeaTS+Ii2+OrfTShXbpvPk6ac46Wx2AEAIACCsgZAQAAuYraJ0zDjfIAAECumBlJ2WfE2X+h4tlnxLOfSMURGFe5IZ2i/4h6f2rfKi9k52PJr+muip4lteRjCkSb+EjkkrjySWQ+h2dfkrCm8zYqfX55JoFvXop6D44eJCrXSbaPl59n//i+dy6Jq2eIb3+JLFvOu3IbEvchcqCM/++QzHI9ZBt1x85VLleO/Ueyon72rKgZ+TWegiiKl0a3UQYMRgAAKKKIMA0AAEBTMDOyG3Iq1TGzXBFhGlny6xm+cZb2Gs87/UZ+7eDV3XxdYZpOz7v5qvPX7yztNZmU9oaqHNdRyu1/x2AVjhElv46/bGRIRMQlIvH3RyDLMPW+daxL3X1YvBHHNPKot5zP8Y7Brob2uhzY843k2cI9TQv+it/n0/s85RhySSOgmgYAAOQqIkwDAADQFMyMAABQQAFhmjZlQ58ZlPZWRA5Ip8ip8C3tVevd2/KLlaq8FJVLEj8myn5lLonIGamKkt9+V5Wpb9t32ards0TYuS2/9UHoV6Ybv0a2S1d5KcYvl8SZcyA+UxmG5Ue95bxzbliVxfqWG/vnTgSjnUuSpqxY/F5L1dYeeyZqnzANgxEAAAooaKOZEXJGAABArpgZAQCgiCLCNO0pIWdExusdfSdUn4ys+onIniGO3JAOFTv2bAev8kJcreLHiHbwqv9ITbSD3yHWW1G16tnePZvcE+c+VG5IRv1H/rwX8Rqxb/XRUbkk+qNmApUL4dtPxJVzkFHPkkDtw5UTox7LqmeJq918Vq3lfXNJ4uPy3JZv+3i9Z5Q4zNIowjQAACBXzIwAAFBEUdR4F11ulFc+URDEy7B1au7IVdqr2r6rEIpnOKbqmGKtiknQTs850+4UZcWq7FeFb7pqYh+i5Deopbhrr7jbrm/7eLXeFY5R4Tp5TKK011nbK0tyxabEZ8c3fBNvS+zDEUVMliIKVbgS4WbdMXjUwze7ic1lIUV4yrtNfIsEgwKqaQAAAJqDmREAAIooopoGAADkKAgbDyVmGoocRQxGdtcOXt4eXg83q6LUrSZKWTtEu/SqZ47JzsdCr3icyiXpE4HuNO3gVWlvt1jfIdrBB67SXpEzEmaUS6LyQpyvEftQ3z7ZJt6VMxJ5bkt8ElQuiVF5LK54vcozEdtytpzPqkzY9xb0zWg5n2cuievP5RF5c/+379Et+d15XBlRZfKuXBkzyrkycGIwAgBAEUWEaQAAQI6CNqqmYTACAEARRfQZaUs2fjwyhizD9Y4wflXkk3R49xlJziXpTNFnpEOFUMV2OqIUOSPiMZVLonJGOkWfkarIJbH6OlRuiGfbd5lLon+g1bYqVb9tqT4jsv9IvBPfB9RtAUQfB8efVZHscaIakIj37UpfyKxniUr+cry/rFrOy94ZctfZtZaX+3Z8pnxbyFcyTMHwfR9oGQxGAAAooIAwDQAAyFVEAmt7Srprr2wHr7/DNRFm6Kr2+4VpxDynaje/c1veXb29Sn5dZcUqHDO20utV8qvaxKu7+Vp9IvShQigqfCPDOo6fFBXaCfvFdL54vpyad4Rp5Ey/7NrveaddR7wgECWgkZpST1Ha61ty7BsicsaI6mE2LedThIjkec8ofOM851ndATjwK/mN1aNswjp1/xiRvJs2Fb9NwWAEAIACCgjTAACAXEXtU03DjfIAAECumBkZIgqCeBlGhetd7eDFvFhN5FuokthOmUsSeo8uqyK+Lzt3i6wnV1mxeh9dnm3ix9T82sRbPR2i3bco+Q07PPM/VJ6Ho1RXvUbcFUC2UY8cPctD8f3wzSWRbcNV3D/euciJ8cxLcZb2ZrUtlWPiKhmtqjJTv/wTlffibDevciHUnLtnfoup6iyyQORbyI9hPbuW7KqUPPLMDZH5TGXJ5vwzwjQAACBfUftU0xCmAQAAuWJmBACAAgoI07SnxHbwMgnD0etD9Bnxbfuu1qucFKtTxEo7RFZAXczhqbfd5eozInJGxlV2ePUfGVtLXt/VIZtnmG0iZyRUOSMyN8Sv/4jrNUFd7EOdQtkiw/XbpJJNLolKOXD1WFBxefH5DEReQyDvueBoyS76UXi3ole5CPHxZtizJOnpjp9jda6881t8txPvXOTXeOcVqX07zpPKM5HfC0dbe5/tx/sQ63d5f/ZCYZojjHSOks82SoDBCAAARRSRMwIAANAUzIykbAcfOEp7O0XtZldF3IVXhm9Uaa/ed0VMplbEdKZ6vprmV23iXWGasSJMM766w+tuvt2iTbzrjr510UI+qlX82sGLUmDXYyqipcI06tSGqsd//P2LMgnfqFJI11179dS5eL6YznfftTcsfyv6FNPn8hF1x2AVjkkTvlFlv6rFum8Jr+N3p3qNLPltQpv43C9JUePbKAMGIwAAFFFEB1YAAICmKPRgZOHCheZFL3qRmTBhgpk8ebKZNWuWefTRR4c9p6enx5x33nlm3333NePHjzdvetObzLp163I7ZgAAsiztDRpcfC1ZssQceuihpru725x00knm/vvvl8/9whe+YF72speZvffeO15mzJjhfH4pwzR33313PNCwA5L+/n5z+eWXm1e/+tXmF7/4hRk3blz8nIsvvtjcfvvt5utf/7qZNGmSOf/8880ZZ5xhfvjDH3rvz1YY7lJlqHJGHKW9VXGLbJUzonJDqiIiWnUEAasiQqjWK6oUuMPxye4Wpcgyl0TkjIwXpb2qTXx8XB3J57BXlfZ2Jq+vdyZvv9Knz59s+14T+xYlv8724J5UxWMg8jYqKv/DWdor1qtSXVWO68qdUGWj6jXi+WozMsckflFy7kQgvlGyqtizpb2TON5I5IZ455JY6jUiDyPwzblxlHLLLBCVlxJlmBsiS5TrbVVNs3TpUjNv3jxz3XXXxQORxYsXm5kzZ8YTAXZSYKQVK1aYt771reYlL3lJPHj5xCc+EV+nH3nkEXPAAQe0xmBk2bJlw76+8cYb45OxatUq8/KXv9xs2rTJfOlLXzK33HKLedWrXhU/54YbbjBHHnmkue+++8yLX/zinI4cAIDyWbRokZk7d64555xz4q/toMT+wX/99debyy67bJfn33zzzcO+/uIXv2i++c1vmuXLl5uzzz67NcI0I9nBh7XPPvvE/9pBSV9fXzwtNOCII44wBx98sFm5cqXczo4dO8zmzZuHLQAAFEkQRZks1shrnr0OjtTb2xtfV4deUyuVSvy165o61Pbt2+Pr8sB1uuUGI2EYmosuusiccsop5uijj47XrV271nR2dpq99tpr2HOnTJkSP+bKRbEhnYHloIMOGvXjBwDAS5jRYkx8nRt63bPXwZE2bNhg6vV6fA31uaYOdemll5pp06YNG9CUPkwzlM0defjhh829997b8Lbmz58fx8QG2FGi/UZFlSBehopETXwlRZ8R/3bwyTFXR8sLRz8Rv3FnRcSzRQqG83h928GPE7kkrpyRro7kx57tTE4CiTqS8wEi0dNDtXyPHxPfkLrIDdG3oM+uI4DuPyLen8oxcbTPVrkeuo168urI8b69W7Krn0vPHJP4Ic8W8upYffuVxNsynkTCivwUuPqMyO+53+8Q1XdFt493ff88+4/IvjmOWw+UpVVpSmvWrDETJ04c/Lqrq8tk7eMf/7j56le/GueR2PyRlhuM2KTU7373u+aee+4xBx544OD6qVOnxtNKGzduHDY7Yqtp7GOK/SaMxjcCAICsBEPCLI1sw7IDkaGDkST77befqVaru1Sk7u6aan3qU5+KByPf+973zLHHHut9nIUO00RRFA9Ebr31VvP973/fHHbYYcMeP+GEE0xHR0ecKDPAZvyuXr3anHzyyTkcMQAAGVfTRA0ue8imPdjr6tBrqk2RsF+7rqlXX321+ehHPxoXnUyfPj3VW60VPTRjK2W+/e1vx71GBmJWNt41ZsyY+N9zzz03DrnYZBk76rvgggvik5aqkibprr2iM3Klqqc5O6uixLXS51X62iGmd6uOqUZZ2ut5d8tQTJ13OLbTLcJQvnfzVW3ix3ckr7fGiDv6bpUlv+ouv4F3S/aw068dvIjiqarN3VSABtmU/Kp9O6oa1WMqtOMd1okf9AvtZBbWsTyPV99hWIUM9O+QSPydKMMMrhLlxO1rjk+62JisI/e/c64M2bV2CKVIHVjt9XTOnDnxoOLEE0+MS3u3bds2WF1jK2Rsye5Azokt5V2wYEF8rba9SQau07bvl11aYjBy7bXXxv++8pWvHLbelu++/e1vj///05/+dJzta5ud2exgWw/9uc99LpfjBQCgzGbPnm2efvrpeIBhBxbHH398POMxkNRqIw/2mjv0Om3TJd785jcP284VV1xhPvzhD7fGYMSGaXbHJsnYbnF2AQCgVQQpO6iO3IYvmx5hlyQ2OXWoJ554wmSh0IMRAADaVtQ+N8pjMLLL/Zr3LGek5soZEUkBXSJnpFME3ztFTLniiOqqEl7v0l7Vil7FjR2t4lWbeJUzMqHak/z8ms4ZGdeRXCa8qTN5331dyR/9cEfyeQq79A902C9yApJ3beqqpFP+0nCUI6pNqXB9xTf/Q+5ah/5FrsXIsvkilA+781X8ckNUuazK84hcnejVvkVuiGw5n4L/p9BPimbw+mdD/gCo/v+O77d4LBixj/jrDG/dgJ0YjAAAUEBB2Pg9q7K859VoYjACAEARRe0Tpil0nxEAAND6mBkZwoYCd+kzIoZrVUfOyJiqZz8RkVxQ8ewlkqafiO92Ohzj1w4RBFf9R8YGqs9Ics7IxFryemuc6EEypjP5nPd0JDcH6e8U/Ud69Xmtyz4jIk9BtsJQ/Rr8+3CoHg/69gb+ORUyB0TkxOj8D7kL3f8kq14mrpYXvnkm4piiFO9bfs/VLQbEbe5zzSVRLfhV4pKzhby8X4Ffzo0pmSiDgy7Jm2YwAgBAi7eDLzrCNAAAIFfMjAyReNfeqrh7bVXPsXZVfNvBq7v2Jm+/w1VvKbjKgdUrktfqUbZqFa/CNKq0d2Ll2cT1k2rJ6+PHOpNDOP/bmVzyu60rObZS702u5Q77HFPLorQ3VB8RdQrlqXWV9qoy2uTnV8SxyudXUoRQPFvLuz7O3tvKKKyTKrSjIrfqc+B64yq04xt+UCdEhnv8S3ijLP8iV23tq9VsSn4dYWxZgm1yFLVPAiuDEQAAiihyDHJ9tlECDEYAACiggJwRAACA5mBmZETcfJfSXhGq7KzpnJEx1V7P0t7kebhOEcN0tXb3bfuutxN4lw6rst8ulTMizseEqsgZEevj14iy3wmdyXkpW7u6Etf39Sb/SPQ5ckZUO3jRHdxxm3TB8XRVkiu7YYvSXpWDEblyC2TehthHVXye05T2Vkc3xyQmj9evfDgQ51yWvlr9fq3o1adTtZwPHHP/kUk+ud5NA9T7dv2lLnJDsir5dSZB1V211nmW9kaNb6MEGIwAAFBEUfsksBKmAQAAuWJmBACAIgozuF0yN8orn7C6ayw6qiVPcXU6+oyMVTkjFZVLUvdrB+/I29C5Hn6TYHURbHblpHSIWHO3CMyPFf1YJkTJ+R+Tqtvkvvfu2J64fmPnmMT1W0TOSE9f8o9Evd+RM6LyKkLfiUf/3zq+/UEilQehchRc+RwyD8MvN0T18nFty7vPiMwxcfwsiXMiv60Z5ZjEj4nckKBf3K5AtUVP/hFz8u1los5gJMIDzuoOlUfj3WdE9Wlx9OxRPzS7nNvmBRQCqmkAAACag5kRAACKKGqfBFYGIyPKeKM9DNOMqSWXpVpjK56lvWICtEPNLTeBDOuoWsEUd/qVbeKD5PO3VzU5FGPtXUsO4fxvx9jE9ZtF+ObZro7E9X19+nvRW694Vm76TUiqu+PGj4mPoSpJV9P2KnzjvKOueEyFJWSZqat8OKt28GK9q6xYnkNxvL5hHdWiPn5MHHBQST6oiqojV2EJx77VyZLhGLUZz+fHr8ko7BKled9FFLXPYIQwDQAAyBUzIwAAFFHUPjMjDEYAACiikNLetpTUDt6IssOuWr93zojKhegQH7aq+BS6ymt9S3h9ubYfihG4b8nvhEpyIsTESnLJr7VPdWvi+k0iZ2SbKO19tl/kjIi8ECsU5aF9qgu42pA4t6p8N35MVTz2iRwQ9XzxmyBNzogqdVb5Gc4SV++cEb/cl8i5b89tZZRjEr9GlJnKc6VKe1WJsOsWA/qh5G355pI42uBHNb928PKkyxwax7vb0zwT39s5NCCgtBcAAKA5mBkBAKCIInJGAABAnsLIxlka30YJMBgZIqoF8TJU0JEcexxfS741vTVB3Oq+WzR56Az8ckNUy/e86Vb0yeu7xPsbK4Lye1WSz6u1rZacM7IlTO4nsj3sTFz/bD05Z6TfkbgRikYSqnl9v+oeH/j1AIkfG/F5HdyW+MkWHfhNJA7KmTPS75fnEcq+JI7Ps2d/EJVT4Zvf4t6H8Wqd75tjsvM14neCSESKKpFXzxdXu41Q/Lyqnh7qJ0PuwvXG1V/xqlW7eN9BVeRfOdr/y32gKRiMAABQRBFhGgAAkKsog8EEg5Fy3rV3xBmpiDDNuFpyma41QZSgdon52g4xoZlnO/gsy35Hu+TX2jdKDopsqyWX8O4Ik8MxO7pr/mEaUeqnyiq3i6nlvmryvkNR7mjV+0RJpyjtVSW/oQq5pGoHL85Hv1/4JsuQjywFduw7VCEOFfIRoS75fMe+ZThNRSvUttTtAhwlrhXxuVWvUKXqcg+Oi2sgQjjedwBWsVBHTbO8o++I9cUMkpcfgxEAAIooIkwDAADyFNqBRHtU05A+DAAAcsXMyIhyyJE5Ix2dycHbiTVdZjpBlKCOqyRHVztG7nQ3Rrvle7NKflVOTLeIQveppANjzKRKcqn15OqW5G11JJ/zPhGzVnkhrhh7TXy/a9Xk9dtryeXGvTX9+ejvEzH23uTPSL1f5Jio0l4Ve3eVy3qW/LryNiqeJccqD0PuW3+kZP6Jb36Navuu3puzzb9aL7YlS37FetdrVLKEqoj1ziWJd65yQzzbvqufmTD0T9TJUxTuXBrdRgkwGAEAoIgickYAAECeQnJGAAAAmoKZkSFs64lgRPuJ7s7kQv29O7bL7ahb3XcHfrkTRW377kvmuIhYpjofYx1x7rpJDtiHoil73fPcVlTSQXy8yfvuFDHormry+s217sT12zqSe6JYO/qSH+vtTT6H9X6RYyJySVTvjJjKP1Et1lU+R4q8FN9W7TInJkWvD50b4tl/xJWvovJM+vy2pVrzVBwtjKqqnY/4OVbpVGoXrgyGigopqBfVkh8IRG5I4Gj5LnuvjHyNo+dQ5iLCNAAAIE9RBoOJcoxFCNMAAIB8MTOymzDNuK7ktu9719Q9WW1pb/JrusQ0oLo7b9lKeLML3ySv7nZFVuSpUvPwyXf5rYqddzhqQNXdmMeI+e7x4lYCGzuS7zC8uS85fGNt6xN3Hxbhmx19yT/yvSJ80y/WW/W6Cu2I6Xy13nXXXlleq0JBKowRZRci8gyVqI+OO0yj7tqrjkmEdcRdndV7cJX2VsX6SN0CWKyvOFqyK6JKXraDj1SYxvF5NuJOv7u2kG9i+DwiTAMAAPIU2kFVg31CXL1VCqS1//QGAACFx8wIAABFFBGmaUtRZ2TCruHfuL26k1u7P6e2WW5ngqg77DCdLV3Cm1cuiTOfRGyqKnJJKiKXpDtQ9Y62zX9yK/oJ1eTPzjO18cnrO8Ylrt/cr3NGtojHtvR1Ja7f3p/8GdxRT/5V0NOvf0X09nvmn4gcE1deSqjyUmQuiWiD3yc+CI58FVkOrHJGxHrf3JP4seS0IkcJb/K2qmo7vfqHKRR5JqHYVq2STSmwi8wNUe3j1Weq5soZEY9R2tsUhGkAAECumBkBAKCIwvZpB89gBACAAoqiMF4a3UYZMBgZot4dmah7+Chy/zHJuSFTa5vkdsZ6tn1v9X4iWXGeJzH4Hyte06HyekRuyLhKcv6HNUEE0/eqJN8yYGNtbOL6LfXkPiMb68nPj18TJueMbK2L9f3JuSRb68nrn63rVvQ94jG1fofIMVH5Kjsfq3rlpag8FpWX0t/nylcRuRPiNaHKGRH5Kir3xKr0evYZEc+vi+dXd+h9qzyTSHyboqo4T9XIO21j154e6f7qr4TiYOu6/79sFT+i/0jQ7JyRkJwRAACAUcfMCAAARRRlkDNSkpkRBiND1MeGJhozPL52yJg/JT53alW3gx87sqf8bsI0GL0Qjjrjqpxa3jE40tO7E0S/731EmGZ7lLx+Wy35x3FLmFyOG78mFCW8UZfX8+V2HPveLkI7O8R8/va6aF0v1u98rMNrvSpd7pGly44wlAor9fmt7+ut+ZUb2/CRuOuyUWXFO8StJkQ4RoVi4sd6xGvUtpJvUm6q4tSGshbYhnBECW/gV/IbiOtv0O/In+gTddO9I05W2MTf42Fob0Hc2DZKkjNCmAYAAOSKmREAAIooIkwDAAByFIWhiRoM01DaW0Kde/WYyogqyqPH/CHxuc9Rt802xnQFnNZWyzFx5ft0iRyJ8eIvmj6RfxKKu3P2RT06r0Hkn6jm9T0i+N4nyhV7Iv2+e8T77ok6/NY7c2KSH9suc1z8cl9UHour3Fm14N8m8lW2qtb8fY733Svya3pF2XRP8vr+HVWv9Valp+KXS7I9eX1NPL8unr/zscirRb0qK+4QJcI1xx1sKypnZGQuV0nugls2XDUBACiiiDANAADIUxjp0qAWG4xQTQMAAHLFzMgQR0/7o+kYNzxW+8KutYnPnTgyuWQI2ru3lyzzT7JS90xaC1NMBYcmOfelHiXH3kOT3Junz3GsdZl3I9ZnlCtjbfPMiVGt+VUPl431cXLfm8StATb1J//eeaYveVvP9CY/f+OO5O3Hj/UkP7bl2eT30bNd9HbZlnyeqlv1Oe8Qj3VsSf7+dW5OXt+1KXk7XZ16350iz6Q6IpckCD1b1jcisp/zsC1mRhiMAABQQFEYmajBME3EYAQAAKQW2VmR9ujA2jKDkSVLlphPfvKTZu3atea4444zn/3sZ82JJ57otY0vH3q3mThh5DTe+EyPE2gG31BhusCReFUTZ7GLpcdzvb7zN4pr85bQ7P28vI+i9bREcsPSpUvNvHnzzBVXXGEefPDBeDAyc+ZMs379+rwPDQCA9GGasPGlDFpiMLJo0SIzd+5cc84555ijjjrKXHfddWbs2LHm+uuvz/vQAABIH2KJMlhKoPRhmt7eXrNq1Sozf/78wXWVSsXMmDHDrFy5MvE1O3bsiJcBmzbtnC7dvLUc3zQAQD4GrhPNSAztt/VhUQbbKIHSD0Y2bNhg6vW6mTJlyrD19utf/epXia9ZuHChufLKK3dZf8gLnxi14wQAtI4tW7aYSZMmjcq2Ozs7zdSpU829a+/IZHt2W3abRVb6wUgadhbF5pgMCMPQPPPMM2bfffc1gag1z8vmzZvNQQcdZNasWWMmTpyY9+GUDucvPc5depy71j1/dkbEDkSmTZs2avvo7u42jz/+eDzznwU7ELHbLLLSD0b2228/U61Wzbp164att1/b0WCSrq6ueBlqr732MkVmfyCL9kNZJpy/9Dh36XHuWvP8jdaMyFB28FD0AUSWSp/Aakd8J5xwglm+fPmwmQ779cknn5zrsQEAgDaYGbFsyGXOnDlm+vTpcW+RxYsXm23btsXVNQAAoNhaYjAye/Zs8/TTT5sFCxbETc+OP/54s2zZsl2SWsvIhpNs/5SRYSXsGc5fepy79Dh3jeH8tZ8gKkvjegAA0JJKnzMCAADKjcEIAADIFYMRAACQKwYjAAAgVwxGSsreW8dWDdmOsT/72c/yPpzCe+KJJ8y5555rDjvsMDNmzBjz3Oc+N87Wz6rDYStasmSJOfTQQ+PGSyeddJK5//778z6kwrO3mnjRi15kJkyYYCZPnmxmzZplHn300bwPq5Q+/vGPx7/fLrroorwPBU3AYKSkLrnkklFtR9xq7H2KbDO8z3/+8+aRRx4xn/70p+O7O19++eV5H1ohLV26NO7fYwdsDz74oDnuuOPMzJkzzfr16/M+tEK7++67zXnnnWfuu+8+c9ddd5m+vj7z6le/Ou57hD33wAMPxD+rxx57bN6Hgmaxpb0olzvuuCM64ogjokceecSWZUc//elP8z6kUrr66qujww47LO/DKKQTTzwxOu+88wa/rtfr0bRp06KFCxfmelxls379+vhn9O677877UEpjy5Yt0eGHHx7ddddd0Ste8YrowgsvzPuQ0ATMjJSMvefO3LlzzVe+8hUzduzYvA+n1DZt2mT22WefvA+jcGzoatWqVWbGjBmD6yqVSvz1ypUrcz22Mn7GLD5ne87OLJ1++unDPn9ofS3RgbVd2P50b3/728273/3uuPW9zYNAOo899pj57Gc/az71qU/lfSiFs2HDBlOv13fpYGy/tuEu7BkbFrT5Dqeccoo5+uij8z6cUvjqV78ahwVtmAbthZmRArjsssviRC3XYi8C9uJpb109f/78vA+5dOduqCeffNK85jWvMW95y1viWSZgtP7Cf/jhh+MLLHZvzZo15sILLzQ333xzW92tFjvRDr4A7H11/vSnPzmf8xd/8Rfmb//2b813vvOd+AI7wP4FW61WzVlnnWW+/OUvm3azp+fO3t3Zeuqpp8wrX/lK8+IXv9jceOONcfgBu4ZpbAjwG9/4RlwNMsDejHLjxo3m29/+dq7HVwbnn39+fJ7uueeeuIILu3fbbbeZN77xjfHvs6G/3+zvO/tzaisIhz6G1sJgpERWr15tNm/ePPi1vbDaCgd70bCllwceeGCux1d0dkbk1FNPNSeccIL5t3/7N36xOdjPk70Dtp2NGwg5HHzwwfFF1s5GIZn9dXrBBReYW2+91axYscIcfvjheR9SadhZ39///vfD1tk7rx9xxBHm0ksvJdTV4sgZKRF7MRhq/Pjx8b+2ZwYDkd0PROyMyCGHHBLnidgZlQFTp07N9diKyJb12pkQm5tkByWLFy+Oy1PtxQHu0Mwtt9wSz4rYXiP2LuLWpEmT4v420Oz5GjngGDdunNl3330ZiLQBBiNoC7bng01atcvIgRuTg7uaPXt2PGBbsGBBfEG1DfaWLVu2S1Irhrv22mvjf+3Ad6gbbrghTj4HkIwwDQAAyBXZewAAIFcMRgAAQK4YjAAAgFwxGAEAALliMAIAAHLFYAQAAOSKwQgAAMgVgxEAAJArBiMAACBXDEYAAECuGIwAGGTvR2NvHPixj31scN2PfvQj09nZaZYvX57rsQFoXdybBsAwd9xxh5k1a1Y8CHn+858f3yTvDW94g1m0aFHehwagRTEYAbCL8847z3zve98z06dPNw899JB54IEHTFdXV96HBaBFMRgBsItnn33WHH300WbNmjVm1apV5phjjsn7kAC0MHJGAOzit7/9rXnqqadMGIbmiSeeyPtwALQ4ZkYADNPb22tOPPHEOFfE5owsXrw4DtVMnjw570MD0KIYjAAY5v3vf7/5xje+YX7+85+b8ePHm1e84hVm0qRJ5rvf/W7ehwagRRGmATBoxYoV8UzIV77yFTNx4kRTqVTi///BD35grr322rwPD0CLYmYEAADkipkRAACQKwYjAAAgVwxGAABArhiMAACAXDEYAQAAuWIwAgAAcsVgBAAA5IrBCAAAyBWDEQAAkCsGIwAAIFcMRgAAQK4YjAAAAJOn/w9sXh8eNy2wJAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "py_pde.plot_kymograph(py_pde_result.extra[\"storage\"])" + ] + }, + { + "cell_type": "markdown", + "id": "9c2f4ecc", + "metadata": {}, + "source": [ + "## Our reimplementation of the example with PyMPDATA" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "51c60e1d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:root:Starting heterogeneous diffusion simulation...\n", + "INFO:root:Using native PyMPDATA implementation (should be ~3x faster than Strang splitting)\n", + "INFO:root:Diffusivity range: 0.010 to 2.010\n", + "INFO:root:Using balanced mu coefficient: 0.050000\n", + "INFO:root:At step 10000/100000\n", + "INFO:root:At step 30000/100000\n", + "INFO:root:At step 40000/100000\n", + "INFO:root:At step 50000/100000\n", + "INFO:root:At step 60000/100000\n", + "INFO:root:At step 70000/100000\n", + "INFO:root:At step 80000/100000\n", + "INFO:root:At step 90000/100000\n", + "INFO:root:At step 100000/100000\n", + "INFO:root:Simulation completed!\n", + "INFO:root:Mass conservation: initial=64.000000, final=4.414727\n", + "INFO:root:Relative mass change: 9.31e+01%\n" + ] + } + ], + "source": [ + "with Timer() as timer:\n", + " pympdata_result = solutions.pympdata_solution(original_simulation_args)\n", + " \n", + "pympdata_time = timer.time" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0ed9d76d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxwAAAKsCAYAAABmurvJAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYTlJREFUeJzt3QuYHFWd//9vVXX3TCY3bibhEgRZFJGbEkEWdUWzorIuEXWDywoi4qqAQla5KIIgKwo8McrVRbm5oKgruIoGFcUbIBjUBRUUueWPEohIrsytq/7PqTjzmwnp6c+kTnV1db9fPv3gTE7qVFdVd/r095xPBUmSJAYAAAAAOQjz2CgAAAAAOAw4AAAAAOSGAQcAAACA3DDgAAAAAJAbBhwAAAAAcsOAAwAAAEBuGHAAAAAAyA0DDgAAAAC5YcABAAAAIDcMOAAAAADkhgEHAAAA0AV+/OMf2xvf+EbbbrvtLAgCu/HGG5v+nVtvvdVe8pKXWE9Pj/3d3/2dXXXVVZPulwEHAAAA0AXWrVtne++9t1188cVS+4ceesgOOeQQO+igg+xXv/qVnXjiifaud73Lbr755kn1GyRJkmzmPgMAAAAooSAI7IYbbrAFCxY0bHPKKafYTTfdZPfee+/o7w4//HB7+umnbenSpXJfFSu4rHP++efbsmXL7M9//vOznrQbC5155pl2+eWXp0/swAMPtEsvvdR23XXX0TZPPfWUnXDCCfbNb37TwjC0N7/5zfaZz3zGpk2bJu9HHMf2pz/9yaZPn54efAAAALQX97lwzZo16XQg95mvnfT399vg4GBhxyXY6POrm/7kHlndfvvtNn/+/HG/O/jgg9NKx2RU2qGs8853vtMOO+ywZ/35eeedZ5/97Gft6quvtp133tk++tGPpk/yt7/9rfX29qZtjjjiiHSw8r3vfc+Ghobs6KOPtne/+9123XXXyfvhBhtz5871+twAAADg3/Lly22HHXawdhps7Pzcafb4E/VC+p82bZqtXbt23O/cF/Yf+9jHMm/78ccft9mzZ4/7nft59erV9swzz9iUKVPaf8Dx+te/Pn00Gq0tWbLETj/9dDv00EPT311zzTXpk3QLXFw553e/+11azrnrrrts3rx5aZsLL7zQ3vCGN9gFF1yQjoAVrrLhvGrLI6wS1Bo33GJDu2bimX1Su+GpNaGNdoqGe7TKTF1pF2rbSsRiUBCr7ZrP7guHtG1Fg1qn0UDzdlG/9gYS9g9r7Qaatwv6xSc6JH6bMiQ8h2Ft/xOxncXCOahrxzZRtpU29DhDVLgeJ6WA2auJ7+fQrhLx+kD3XRtF4HrMzbAN2U/t26Of29qFq2y4wcYjy3ayGdNbW3lZvSa25+77cDoImzFjxujvfVQ3fCp0wNFskYobVY0t48ycOdP233//tLzjBhzuv1tsscXoYMNx7V2Z7ec//7m96U1v2uS2BwYG0scIV55z3GCjEk4wCAi1kxdHG6ovTVWaDzisKp6iqvbpPxDaJVExA46wLgw4tE1ZJL7hR3VhwFERBxyROOCImg8mgkh8pnXxJITCvonl6UQtYyvnIBAHHOpFZB4/RAW+P5C1/kNI4v05tCs+4E1W91wbReB6zM3fLtt2nf4+bXqQPloptg39ucHG2AGHL3PmzLEVK1aM+5372fWlVjec9poAN4YbbDibKuOM/Jn776xZs8b9eaVSsa222mq0zaace+656eBl5MF0KgAAAGC8Aw44wG655ZZxv3PLGNzvJ6NtBxx5Ou2002zVqlWjD1eGAgAAADrZ2rVr03hb9xiZUeT+/6OPPjr6GfnII48cbf+e97zHHnzwQTv55JPtvvvus0suucS+8pWv2EknndQZU6pcCWekbLPtttuO/t79vM8++4y2eeKJJ8b9veHh4TS5auTvb4qvlfsAAACAU09iE2aHe+9zMn7xi1+k99QYsWjRovS/Rx11VHpDPxfENDL4cFxok4vFdQMMlwLrFut//vOfT0OcOmLA4Z6gGzS4Ms7IAMOtiHdrM9773vemP7tyjovLdbG6++67b/q7H/zgB2nMrVvr4Z3vOYOBv3US8r4J7fQ+tWaJxyn/6r75bCcfj66sF2bUpvNwUTKB8OJjIe84gRoOwuJyoKO86lWvSoOZGtnUXcTd3/nlL3+Zqd9K0WWdBx54YPTnkbKOW4Ox4447phm/55xzTnrfjZFYXJc8NXKvjhe+8IX2ute9zo499li77LLL0ljc448/Pl1QriZUAQAAAFnFlqSPVvdZBoUOOJqVddx8MXevDndfDVfJePnLX57G4I7cg8O59tpr00HGa17zmtEb/7l7dwAAAAAoXpBMVFfpEm6qlkurmr/V0RPH4m450+99OKY3j8UdmqaNCes9obf7cMSR3ylV6uA7HC7gPhz9/u7DEan34XhmyN99ONS7mg4Nt/4+HELksHSvDteneL+O9r4PRwGxuEyH+X+YUrVZuIY2A9daboaTIbvVvpEG/uQRAZv1c+Sf7t+hkPtwbPeC/6/tjsnGmHUOAAAAIDcMOAAAAADkpm1TqsosEZN3pHYFpDL57lOeeaWkpqh3x/WY2uWd0qeYICOl86h9igKxT7d0zluf6l3QxSlaXqdelTyJiCkzAOBHPUnSR6v7LAMqHAAAAAByQ4UDAAAAyIhY3MaocAAAAADIDQMOAAAAALlhShUAAADgYXpTnSlVm8SAYyyX6DJRqovvRKPQXxKUeWznu0/1paAc3iQsIrWrjROvfPK9/2U/HgAAwAsGHAAAAEBGLBpvjDUcAAAAAHJDhQMAAADIiBv/NUaFAwAAAEBuGHAAAAAAyA1TqvIgJykF3pJ+kkjtU2ijDkPV8KbYZ2KUti25ncdtSedTbBeoCU8TpaoB+H8C9Y1ZfMPqEoH4HpPE5ZjW0RJca13LndFWn9XYyoEKBwAAAIDcUOEAAAAAMqoXcOO/OrG4AAAAALodAw4AAAAAuWFKFQAAAJBRPdnwaHWfZcCAYzLURCA1YchXctNk2oWtT2WyMPGWZuX7eCjPVX6e7awTnkM3JNcUkFpDChEAIG8MOAAAAICMiMVtjDUcAAAAAHJDhQMAAADIKLbA6l7vPKz1WQZUOAAAAADkhgEHAAAAgNwwpapIShVMTltSE7Q8pjKpiVFiw0RJs/K8b1LymDosl/v0dw6Cdk5rq+e9I23yPElv6r40sYISxQC0N/fPQav/SYhL8k8QFQ4AAAAAuaHCAQAAAGRUL2DReJ1F4wAAAAC6HQMOAAAAALlhShUAAACQEVOqGmPAkQM1YSiREqPUPv21SzynMgVx6/fN6/GQk7E8t2v1tkLx4MZx6/uslz3yCuhsgZDqlpQlTgeAdww4AAAAgIziJEgfre6zDFjDAQAAACA3VDgAAACAjFjD0RgVDgAAAAC5YcABAAAAIDdMqQIAAAAyqluYPlrbZzkw4Ng4YnSimFE59nQS/floM6k+W7ytSUTZKvG5chiD73bmMU5Y4fv9Sois9P6uJfVJTOY4gZr77DGa2GPsqUP0KQBgYww4AAAAgIySAmJxE2JxAQAAAHQ7BhwAAAAAcsOUKgAAACAj7sPRGBUOAAAAALmhwlEgZZ2PuhZIbqckzXjuUx17a/uWeE2Mkp6D7y8P1OSxVm+rnfl+nsr2EtKWUM5EMQDFqCdh+mhtn1YKVDgAAAAA5IYKBwAAAJBRbIHFLf4uP7ZylDiocAAAAADIDQMOAAAAALlhShUAAACQEbG4jTHgmIRETcqR23lq4zmVyWvCU9pQbBd77NNjapfeZ+DtOgqKSGXyfX0XIAi1izeJSQ7KS6C8puJyzDkGckXSGboIAw4AAACglLG4iZUBazgAAAAA5IYBBwAAAIDcMKUKAAAA8HIfjtauc4xLsmicCgcAAACA3FDhyIG8XkhJc1G35TG9yXsSlLo5nwlawrHd0GniMX3K/OmAxKiuoV5rJDN1JyWJqEtSiJQEM4cUM5SVu8t4nTuNbxIVDgAAAAC5YcABAAAAIDdMqQIAAAAy4j4cjVHhAAAAAJAbKhwAAACAh0Xj7tHaPhMrAwYcGyf+TJT64/kaklKN1CQotZ0SmOI5GSsQA1ikfn0fD6+pXWLDLqkrBkI6T6KkhGHzko/aOP2ItCIA6C4MOAAAAICM6kmQPlrdZxl0yXetAAAAAIrAgAMAAABAbphSBQAAAGRUL+BO4/WSLBqnwgEAAAAgN1Q48qCmFXlNSPLYznOfauqVkmaVyMdWHPEr2/N+DgKPiVfq8Qj99QkAAJ4lTsL00do+EysDKhwAAAAAcsOAAwAAAEBumFIFAAAAZMSi8caocAAAAADIDRUOAAAAIKO4gDt/x1YODDgmQ0zx8XqtqX2GHvetgPQpdXtqn+o5kNrJx9Zvu7ZV9v33/TzbOSFESSdLyvLPVQdTzlMXnatAfc+N2/i1B2AcBhwAAABARrGF6aPVfZZBOfYSAAAAQCkx4AAAAACQG6ZUAQAAABnVkzB9tLrPMijHXgIAAAAoJSocbZ5m5TVtyXcSlO9hbdz6BC1ley1OuPtbn1qngZqkJKa+tK1QPKH1urUt5RyQujMOaUUAyiS2IH20us8yoMIBAAAAIDcMOAAAAADkhilVAAAAQEYsGm+sHHsJAAAAoJSocAAAAAAZ1S1MH63uswwYcGychDNRGo6aCKRStqd26bGd7/SpRNxg4DFBy2ualXpsfe5bEe8fvq9vJWHId6iUmu4lpF4lsRKbBrSQ8ibpJFy7ANoLAw4AAAAgozgJ0ker+yyDctRhAAAAAJQSAw4AAAAAuWFKFQAAAJBRXMCi8bgktYNy7CUAAACAUqLCkQc1ISlo01QmNQhF7FNdziRtz+OxTdspyVhyn+oB8bfAS+3T65IyIeEppaQ8KUlWTl3OTkMXJh8FwnWUxFxDKKkOeI12izgJ00er+yyDcuwlAAAAgFJiwAEAAAAgN0ypAgAAADKqW5A+Wt1nGVDhAAAAAJAbKhwAAABARiwab6wcewkAAACglKhwTIYYQarHoyrb0jblMz5X3Za6b6amUcYe902NW5WieP3m/0rPwWN0bi7bQz7U65aIV4A4ZLSdegFrKupWDlQ4AAAAAOSGAQcAAACA3DClCgAAAMiIReONlWMvAQAAAJQSFQ4AAAAgo3oSpo9W91kGDDjy4DPlSU0+8thOTp9Sn6eQPqUGKcn7VsDxkPfNZ6pUWEBCUlkiMVpFPVdJydNyAs8v+DZMNOqYVCPlXLXpeQLQmcoxLAIAAABQSlQ4AAAAgIwSCyxu8X04khb3t7mocAAAAABd5OKLL7addtrJent7bf/997c777xzwvZLliyxF7zgBTZlyhSbO3eunXTSSdbf3y/3R4UDAAAA6JJF49dff70tWrTILrvssnSw4QYTBx98sN1///02a9asZ7W/7rrr7NRTT7UrrrjC/v7v/95+//vf2zve8Q4LgsAWL15c/gpHvV63j370o7bzzjunI6pddtnFPv7xj1syZvGl+/9nnHGGbbvttmmb+fPn2x/+8IdC9xsAAABoR4sXL7Zjjz3Wjj76aNt9993TgUdfX186oNiU2267zQ488ED713/917Qq8trXvtbe9ra3Na2KlGbA8alPfcouvfRSu+iii+x3v/td+vN5551nF1544Wgb9/NnP/vZ9GD9/Oc/t6lTp6ajtMmUecalzUzwSMSHr/429GnaI9Qe6VS/Zo9Qe6j7Jm9P2X/f+yY89GMb+Ht4vIa6qk8AAAoSJ0EhD2f16tXjHgMDA7Ypg4ODtmzZsvQL+hFhGKY/33777Zv8O66q4f7OyADjwQcftG9/+9v2hje8wTpiSpUbUR166KF2yCGHpD+7UdWXvvSl0SfsqhuuDHT66aen7ZxrrrnGZs+ebTfeeKMdfvjhhe4/AAAAkDe3rmKsM8880z72sY89q93KlSvTGUTus/JY7uf77rtvk9t2lQ33917+8penn72Hh4ftPe95j334wx/ujAqHG1Hdcsst6Vwx59e//rX99Kc/tde//vXpzw899JA9/vjj40ZpM2fOTOejNRqlOW7Ut/FIEAAAACij5cuX26pVq0Yfp512mrdt33rrrfaJT3zCLrnkErv77rvt61//ut10003pMoeOqHC4BSpuMLDbbrtZFEXpiOw///M/7Ygjjkj/3A02nE2N0kb+bFPOPfdcO+uss3LeewAAAHSLuoXpo9V9OjNmzEgfzWyzzTbpZ+oVK1aM+737ec6cOZv8O2499dvf/nZ717velf6855572rp16+zd7363feQjH0mnZJW6wvGVr3zFrr322nR1vBtRXX311XbBBRek/83CjfrGjgLdqBAAAADoZLVazfbdd990BtGIOI7Tnw844IBN/p3169c/a1DhBi3O2CCn0lY4PvShD6VVjpG1GG5E9cgjj6QViqOOOmp0JOZGZS6laoT7eZ999mm43Z6envQBAAAA+DB2EXcr+5wsF4nrPkfPmzfP9ttvv3Q9tKtYuNQq58gjj7Ttt98+/bztvPGNb0yTrV784henyxYeeOCBtOrhfj8y8Cj1gKPRiMqNxBwXl+sGHW5UNjLAcFOwXFrVe9/7XiuKmlQlXSPqdSS2U+Ka5WtXrI+Jg19pe973TWnn83yK7dRryOvbWgEpT0GgnajE6tZqgVAidpK/vR+1VCieq1h98WFEIB7bhGMLoKQWLlxoTz75ZHpbCbcEwX2GXrp06egShUcffXTc528XzuTuueH++9hjj9lznvOcdLDhljmo2nrAMfJkdtxxR3vRi15kv/zlL9MR1jvf+c70z92TP/HEE+2cc86xXXfdNR2AuBHXdtttZwsWLCh69wEAAIC2c/zxx6ePRovEx6pUKmnqlXtsrrYecLj7bbgBxPve9z574okn0oHEv//7v6cjshEnn3zy6MKVp59+Oo3scqM0d6t2AAAAoBViC9NHq/ssg7YecEyfPj2dV+Yejbgqx9lnn50+AAAAALSXth5wAAAAAGVQT4L00eo+y6AcdRgAAAAApUSFI4/hmcdkqURNo/GYkOQ14cntmhriI6U3WQGJUb7Pe+DxWlOvj3J8A5KZmCxlSrKUHK+GcZTksaSAZC+MJybElf1ckTqGVipLLG4RqHAAAAAAyA0DDgAAAAC5YUoVAAAAkFGShBar88099lkG5dhLAAAAAKVEhQMAAADIqG5B+mh1n2XAgGOsoEmaj5j0Iyckha3dVkrpUw0vUa9xj/smp3H5TBSTn6ffRLG2RTLW5lGOB8lYpUH6EQDomFIFAAAAIDdUOAAAAICMXEGz9ffhsFKgwgEAAAAgN1Q4AAAAgIziAmJxY2JxAQAAAHQ7KhyFpvh4auOSUMxfspTv9Ck1eCfwmKDlM83Kd2pXolwfvpOglEQd5QSk6tZyagJYvSSTWdvpuBUxAVi91pI47z0BALQAAw4AAAAgo9iC9NHqPsuAKVUAAAAAckOFAwAAAMiongTpo9V9lgEVDgAAAAC5ocIBAAAAZEQsbmMMOCZDTQQSJVJykLix0GM7NUBG7TPxmKDled+UxKgkVGO2tGbK8ZWSrCbRrm0LrnL6VN47AmCTSBQrDynqkfOEYpRjWAQAAACglKhwAAAAAD5icVu8iDtu3zkM41DhAAAAAJAbKhwAAABARkkBN/5LqHAAAAAA6HZUOHKgTt/zmsqk9hm2vk917C31q27MZzs5Mcr8JUv5/sJC6VNNjPKc1lZ2Qai9YJI49ndsEzE5TaGe99hjn12UkBQIxzcp4tgCQAsx4AAAAAAycgvGW75oPCnHl4BMqQIAAACQGyocAAAAQEbcabyxcuwlAAAAgFKiwgEAAABkxBqOxhhwbJwQM0FKjJQulG5H7a+16VPq9uRr13OAjBJIIz9Pj+3k4+Hz+lC3JZ/35tvz/palpDcpyU2TIR83j/vmMzEKQNumiTkkigGbhylVAAAAAHJDhQMAAADIKC7gTuMxdxoHAAAA0O2ocAAAAAAZsWi8MSocAAAAAHJDhSMPatqFlFYk9ukzWcpzEpS6a1LYj8c0rpTHc+AzKcx7KpPPbYnXt9X99RkoEWbu2EqdYrOo572IFB8p4s5zIppHHZGQVPJzACBfDDgAAACAjJhS1RhTqgAAAADkhgoHAAAAkBEVjsaocAAAAADIDRUOAAAAICMqHI1R4QAAAACQGyock1FAJKscteqxnbr/8vNUh7Wxv+fpM8rWe9ytEAUrP892/mrBZ2RvBwjC5ichiWO/x1bKmgYAIF8MOAAAAICM3Fc8sXz3MT/K8rUSU6oAAAAA5IYKBwAAAJARi8Ybo8IBAAAAIDcMOAAAAADkhilVY4XBhkfWZBifKU8eE6/UPuWEpFBbqpSI5b7AZ4KWx2Qpn+lT8vbka81jKZVUKXQy5Q3GScSksAIEE/37NEYSl2UZKdBZmFLVGBUOAAAAALmhwgEAAABkRIWjMSocAAAAAHJDhQMAAADIiApHY1Q4AAAAAOSGCkcO9FQjYVtqsIo6dAw8pk+pfSbq9oSd83w8lHY+E69SHpOxEjFZKuiWNCsxxcfqSeuPh/g68ErZN9/7pZwDUpS6U5ckhZESBjwbAw4AAAAgI3cbAPVWAL60ur/NxZQqAAAAALmhwgEAAABkFFuQPlrdZxlQ4QAAAACQGwYcAAAAAHLDlKpJUBOB1NQaZZ2PmnVRSCqT2C4Qn0RSRGqX0s5j+tSGPoWG6rUmp5N57NMK6FNOn9KaSf2G4sGN/SXqBGKficc+0XlJSgCKwX04GqPCAQAAACA3VDgAAACAjIjFbYwKBwAAAIDcUOEAAAAAMmINR2NUOAAAAADkhgrHxsk1vpN6JpBIaUXixoLWp1Spw9VETKkKwsRjUpjHZCw1dSzSnqj0ZUTQASk+cmQUuo6aOharOX0YKxCOb8KxBdBCDDgAAACAjFg03hhTqgAAAADkhgoHAAAA4KHa0OpF3AkVDgAAAADdjgEHAAAAgNwwpWoyPCYfqdtTE6P0ZCkhmUTuU0s5CcQwlCQSDojn4yGlVHncVspjMpb5bKcmB6GzqNeQGjfXLWlWalpbEue9J52HY5sfjm2ukgLeKhMrByocAAAAAHJDhQMAAADIKLYg/V+r+ywDKhwAAAAAckOFAwAAAMiIG/81RoUDAAAAQG6ocEyGnAikNZMGpR6Tj9I+Q3/pU3KfHoe//lO7fJ6DwN95l5OxAm/tAvX6Dn0mY6lPVExEExNYEqtbyynHQ32e4nFLYpJmsGmB+DpOikgAA9BxGHAAAAAAGbm7jActnuIUM6UKAAAAQLejwgEAAABk5GbFtvzGf4mVAhUOAAAAALlhwAEAAAAgN0ypGssl3IgpNxOR1+8ooTVh6/vUE68SrzsXCHXBRE1I8njcvCdjCWlFavpUSW4w2n6U66guXt9q0lbZE6PUa7KI+r5yPotKW1L+TUlKfm1gHBLAuhf34WiMCgcAAACA3FDhAAAAADKiwtEYFQ4AAAAAuWHAAQAAACA3TKkCAAAAMuJO440x4JgEnylE8vbU68hjkpKcPhVpzdR0mCQOvO2bmmalHQ+/SWFSOzl1zF9ql5qMFch9KslBbfxG2c6pTKJASNBKyp6ehe5FAhhQGgw4AAAAgIy403hjrOEAAAAAkBsqHAAAAICXCkerY3GtFKhwAAAAAMgNAw4AAAAAuWFK1WSo6VNywpCwLY/pUykl5cnnthw17EdJLPKcGCVtT91/n0lhnvuUE5falc9kLKdu7akDkrGk51DE/qvXhpiq1/K0pYISlwI18a+I4wa0Ge403hgVDgAAAAC5ocIBAAAAZOTqfK2u9SVWDlQ4AAAAAOSGAQcAAACA3DClCgAAAMiIReONUeEAAAAAkBsqHGO5+D81OnEiarJlUEAka+Av7jZRY3HF0XcgbC9Rz4/PiFo5elZtF7Q+xlbZnu+I3bJH8SI/nRD/CwAbY9V4Q1Q4AAAAAOSGCgcAAACQVQFrOIw1HAAAAAC6HQMOAAAAAN074Hjsscfs3/7t32zrrbe2KVOm2J577mm/+MUvRv88SRI744wzbNttt03/fP78+faHP/yh0H0GAABAd3E5F0U8NsfFF19sO+20k/X29tr+++9vd95554Ttn376aTvuuOPSz9s9PT32/Oc/37797W93xhqOv/71r3bggQfaQQcdZN/5znfsOc95TjqY2HLLLUfbnHfeefbZz37Wrr76att5553tox/9qB188MH229/+Nj2IRUyT85lqpG9LTZby12egJkGprwYlgUpO0Apafjx8JoXJUzJ9JkEVkSpVUJJVIFy8idXVjWntQuECiWO/fQqvvUDZL7cpdd/KTk3CiwuIhpHfdFt/rgLhuCVFHDMAz3L99dfbokWL7LLLLksHG0uWLEk/O99///02a9asZ7UfHBy0f/zHf0z/7Gtf+5ptv/329sgjj9gWW2xhHTHg+NSnPmVz5861K6+8cvR3blAx9oOsO0inn366HXrooenvrrnmGps9e7bdeOONdvjhhxey3wAAAOguRd74b/Xq1eN+76oQ7rEpixcvtmOPPdaOPvro9Gc38LjpppvsiiuusFNPPfVZ7d3vn3rqKbvtttusWq2mv3PVkY6ZUvW///u/Nm/ePHvrW9+ajqpe/OIX2+WXXz765w899JA9/vjj6TSqETNnzkxHa7fffnvD7Q4MDKQnZuwDAAAAKKO5c+emn4FHHueee+4m27lqxbJly8Z9dg7DMP250Wdn93n8gAMOSKdUuS/199hjD/vEJz5h9Xq9MyocDz74oF166aVp2efDH/6w3XXXXfb+97/farWaHXXU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QLu5/vrrbdGiRXbmmWfa3XffnQ44Dj74YHviiScm/HsPP/ywffCDH7RXvOIVk+6zFAMON2XqkEMOsfnz54/7/bJly2xoaGjc73fbbTfbcccd7fbbb2+4vYGBAVu9evW4BwAAAJA1FrfVD2fjz7Xus24j7ov6Y4891o4++mjbfffd7bLLLrO+vj674oorGv6der2efvl/1lln2fOe9zzruAGHK9240de55577rD9zZaBarWZbbLHFuN/Pnj07/bNG3Lbc9KuRx9y5c3PZdwAAACBv7rPs2M+2m/rc7AwODqZf2I/9sj4Mw/Tnib6sP/vss23WrFl2zDHHdN4ajuXLl9sHPvAB+973vme9vb3etnvaaaelpaQRbiTIoAMAAABljMVdvny5zZgxY/TXPT09m2y+cuXKtFrhvpwfy/183333bfLv/PSnP02XMPzqV7/a7N1s6wGHG4G5+WQveclLRn/nDtKPf/xju+iii+zmm29OR2pPP/30uCqHS6maM2dOw+26k9DoRAAAAABlMmPGjHEDDl/WrFljb3/729N11Ntss01nDjhe85rX2D333DPud26+mVunccopp6RViWq1arfccksah+vcf//99uijj9oBBxzgfX+EEKVJJgc1bxOIKVWR3K55wkYtHJa21SO201OqQm/JWGqaVSgkUCVySpXaLmjpNSS383x9e02p8t5OeBLia8rqib99E5OD5FQjJYFKTgozb4lRSpKV9zQrNRGonVPHCkgn85pm5fvY+jzvQJfYZpttLIqiZ91CotGX9X/84x/TxeJvfOMbR38X/+31XqlU0s/du+yyS7kHHNOnT7c99thj3O+mTp2a3nNj5PduLpmbHrXVVlulI7sTTjghHWy87GUvK2ivAQAA0HVKcKfxWq2Wprq6L+sXLFgwOoBwP7tbS2zMfcm/8Zf/p59+elr5+MxnPiMvSWjrAYfi05/+dLrYxVU43Ip8F+t1ySWXFL1bAAAAQNtxX9QfddRRNm/evPTeG0uWLLF169als4icI4880rbffvt04blbQ73xl/8jyxg2/n1HDThuvfXWcT+7A+FuXuIeAAAAQBHGxtS2ss/JWrhwoT355JN2xhlnpKmu++yzjy1dunR0IblbmuC+zPepdAMOAAAAAJvPTZ/a1BSqTX25v7Grrrqq8+7DAQAAAKC8qHBsnKAxUYqGGLCh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UAEAAABoja5MqQIAAADQGgw4uphL6jrzzDPHJXahc3G+uwvnu7twvrsL5xtlEyTtmi0GAAAAoPSocAAAAADIDQMOAAAAALlhwAEAAAAgNww4AAAAAOSGAQfGGRgYSG+c6O64/qtf/aro3UEOHn74YTvmmGNs5513tilTptguu+ySpp0UdYdU+HfxxRfbTjvtlN6Eav/997c777yz6F1CDs4991x76UtfatOnT7dZs2bZggUL7P777y96t9Ain/zkJ9N/q0888cSidwVoigEHxjn55JNtu+22K3o3kKP77rvP4ji2z33uc/ab3/zGPv3pT9tll11mH/7wh4veNXhw/fXX26JFi9JB5N1332177723HXzwwfbEE08UvWvw7Ec/+pEdd9xxdscdd9j3vvc9Gxoaste+9rW2bt26oncNObvrrrvS9/C99tqr6F0BJMTiYtR3vvOd9IPK//zP/9iLXvQi++Uvf5lWO9D5zj//fLv00kvtwQcfLHpXkJGraLhvvS+66KL0Zze4nDt3rp1wwgl26qmnFr17yNGTTz6ZVjrcQOSVr3xl0buDnKxdu9Ze8pKX2CWXXGLnnHNO+u/0kiVLit4tYEJUOJBasWKFHXvssfbFL37R+vr6it4dtNiqVatsq622Kno3kJGbFrds2TKbP3/+6O/CMEx/vv322wvdN7TmdezwWu5srqp1yCGHjHudA+2uUvQOoHiuyPWOd7zD3vOe99i8efPSOf7oHg888IBdeOGFdsEFFxS9K8ho5cqVVq/Xbfbs2eN+7352U+nQuVwly83lP/DAA22PPfYoeneQky9/+cvpVEk3pQooEyocHcxNn3ALyiZ6uA8h7sPmmjVr7LTTTit6l9GC8z3WY489Zq973evsrW99a1rhAlDeb73vvffe9AMpOtPy5cvtAx/4gF177bVpIARQJqzh6PD5vH/5y18mbPO85z3P/uVf/sW++c1vph9IR7hvSaMosiOOOMKuvvrqFuwtWnW+a7Va+v//9Kc/2ate9Sp72cteZldddVU69Qbln1LlpkR+7WtfSxOLRhx11FH29NNP2ze+8Y1C9w/5OP7449Nz++Mf/zhNn0NnuvHGG+1Nb3pT+m/z2H+r3b/d7v3bpUyO/TOgnTDggD366KO2evXq0Z/dB1GXauM+tLgFqDvssEOh+wf/XGXjoIMOsn333df++7//m3+kOoh7ze63335p5XJkqs2OO+6Yfihl0Xhncf98uzCAG264wW699Vbbddddi94l5MjNRHjkkUfG/e7oo4+23XbbzU455RSm0qGtsYYD6YeRsaZNm5b+192fgcFGZw42XGXjuc99brpuw1VGRsyZM6fQfUN2LmnOVTTceiw38HDpNS4m1X0wQedNo7ruuuvS6oa7F8fjjz+e/n7mzJnpPXbQWdw53nhQMXXqVNt6660ZbKDtMeAAuozL63cLxd1j4wElBc/yW7hwYTqIPOOMM9IPoC4yc+nSpc9aSI7yc1HWjvsCYawrr7wyDQIBgHbBlCoAAAAAuWGVKAAAAIDcMOAAAAAAkBsGHAAAAAByw4ADAAAAQG4YcAAAAADIDQMOAAAAALlhwAEAAAAgNww4AAAAAOSGAQcAAACA3DDgAAAAAJAbBhwAAAAAcsOAAwA6xJNPPmlz5syxT3ziE6O/u+2226xWq9ktt9xS6L4BALpXkCRJUvROAAD8+Pa3v20LFixIBxoveMELbJ999rFDDz3UFi9eXPSuAQC6FAMOAOgwxx13nH3/+9+3efPm2T333GN33XWX9fT0FL1bAIAuxYADADrMM888Y3vssYctX77cli1bZnvuuWfRuwQA6GKs4QCADvPHP/7R/vSnP1kcx/bwww8XvTsAgC5HhQMAOsjg4KDtt99+6doNt4ZjyZIl6bSqWbNmFb1rAIAuxYADADrIhz70Ifva175mv/71r23atGn2D//wDzZz5kz71re+VfSuAQC6FFOqAKBD3HrrrWlF44tf/KLNmDHDwjBM//9PfvITu/TSS4vePQBAl6LCAQAAACA3VDgAAAAA5IYBBwAAAIDcMOAAAAAAkBsGHAAAAAByw4ADAAAAQG4YcAAAAADIDQMOAAAAALlhwAEAAAAgNww4AAAAAOSGAQcAAACA3DDgAAAAAGB5+f8B1FR+3Dn6PhAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1cAAAIjCAYAAADvBuGTAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAXiJJREFUeJzt3QmcVfP/x/H3zNS0ad/TKhSlopQIRWRL/Swt/LT8CBGRRP0o/UT2XyilLBEpQv6WCpEshcoW8quUaK9f+15z/4/POb87c+8sNffOnTnn3nk9H49jvufcM2c+d+7X7X7m+z2fb1IgEAgIAAAAAJAnyXn7dgAAAACAIbkCAAAAgBgguQIAAACAGCC5AgAAAIAYILkCAAAAgBgguQIAAACAGCC5AgAAAIAYILkCAAAAgBgguQIAAACAGCC5AgAgzsyZM0dJSUnO11CTJk1Sw4YNVbRoUZUrVy79+KOPPqpjjjlGKSkpatasWczj6dWrl+rWrRvx961cudJ5HhMnTox5TADgBZIrAChg9kHSPlAuWLAg28fbtm2rxo0bR3XtyZMna9SoUXmMEAUpmGAEN0uMKlWqpNNPP11DhgzRqlWrcnWdJUuWOElO/fr1NWHCBI0fP945/uGHH2rQoEE644wz9OKLL+rBBx+Un33wwQe67777vA4DAKJSJLpvAwD4kSVXixcv1m233eZ1KIhQ9+7dddFFFyktLU1btmzRt99+6yTKTz75pJ5//nl169Yt/dyzzjpLe/bsUWpqavoxG8Wy77Xzjz322PTjn3zyiZKTk51rhJ4fS5bM2c+OVJ06dZznYQllaHI1ZswYEiwAcYnkCgBwWPahef/+/SpevLjXoSS0U045RX//+9/Djv3xxx86//zz1bNnT51wwglq2rSpc9ySpcyvx4YNG5yvodMBg8dLlCiRb4mVCU2OImEjdfQrAImEaYEAECdeeeUVNW/e3PmgXKFCBWck488//wybTvj+++87H8iDU8xC74PZt2+fhg0b5oxqFCtWTLVq1XKmi9nxUPZ9/fr106uvvqpGjRo5586cOdN57LvvvtOFF16oMmXK6KijjtK5556r+fPnZ4n1xx9/1Nlnn+3EWrNmTY0YMcKZkmbXtmlwoWbMmKEzzzxTpUqVUunSpXXxxRfr559/DjvHprvZz1u9erU6d+7stCtXrqyBAwfq0KFDWZJBG/Gx2O2De9WqVXXDDTc4o0GZPfPMM+nPsUaNGrr55pu1devWsHPsd2g/PzP7fdsW6umnn3auV7JkSZUvX14tWrRwRhOjZSM7No3UkttHHnkkx3uuLEZ7bY39XuwxG/mxr/Z737VrV3qfsOsd7l6n4PcG7dixwxkJtZ9hv6cqVarovPPO06JFi7K95+rAgQNO/+zdu3eWa2/fvt15Tex1M5njsOvYqFUwjuAWCASc63fq1CnLNffu3auyZcs6rzEAeI2RKwDwyLZt27Rp06Ysx+3DaWYPPPCA7r33XnXp0kXXXXedNm7c6HyQt+lhlvDYaMU///lP55p//fWX/v3vfzvfZ0lIMOG49NJL9cUXX+j66693RkF++ukn57z//Oc/mj59etjPs6lkr7/+upNk2f0/9sHWEh5LgiyxsqTMRiueffZZJ8H47LPP1KpVK+d7LQFq166d86F48ODBTtL03HPPOR/MM7MCDDYq06FDBz388MPavXu3xo4dqzZt2jjPKzQ5tCTKzrOf89hjj+njjz/W448/7txj1Ldv3/Tz7EO2fVi3D/e33nqrVqxYodGjRzvX+/LLL9NHWSyBGD58uNq3b+98/2+//eb8bJuOF3peJFPj7OddccUV6t+/v/Oh35LMr7/+WldddZWi1bp1a+c5fvTRRzmeY8nkyy+/rLffftt5Dva6N2nSxEmk7d6rb775xnkNjN3LFYkbb7xR06ZNc/rCiSeeqM2bNzv96Ndff3VG2zKz39vf/vY3vfXWW07/CB0xs35myXzoFMdQ9tqtWbPGea7WN4KsL9moniWY//3vf53kLejdd991krbMo34A4IkAAKBAvfjiiwF7+z3c1qhRo/TzV65cGUhJSQk88MADYdf56aefAkWKFAk7fvHFFwfq1KmT5WdOmjQpkJycHPj888/Djo8bN875eV9++WX6Mdu3c3/++eewczt37hxITU0NLF++PP3YmjVrAqVLlw6cddZZ6cduueWWQFJSUuC7775LP7Z58+ZAhQoVnGuvWLHCObZjx45AuXLlAn369An7OevWrQuULVs27HjPnj2d7/3Xv/4Vdu7JJ58caN68efq+PT8779VXXw07b+bMmWHHN2zY4DyX888/P3Do0KH080aPHu2c98ILL6Qfs9+n/fzMzj77bGcL6tSpU9jrllv2+7Cf+eijj+Z4jl3b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2T6JFQC/YeQKAAD4rmCFlVW3an/r1mUcb95cmjBBOvlkL6MDgJwxcgUAAHxjzx7p739376UKJlalSrn3VX39NYkVAH9j5AoAAPjC6tVS587SggUZxzp2lEaPlmrX9jIyAMgdkisAAOC5b75xE6u1azNGq55/3h3BSkryOjoAyB2SKwAA4KlXX5WuvTajxLpVAvy//5OaNPE6MgCIDPdcAQAAT6SlSYMHu/dYBROrM8+Uvv2WxApAfGLkCgAAFLgdO6Srr5befTfj2HXXSWPGSKmpXkYGANEjuQIAAAXq99+lSy/NWLsqJUX697+lfv24vwpAfCO5AgAABWbOHOmKK6TNm939cuWk11+XzjvP68gAIO+45woAABSIZ591k6hgYtWggbt2FYkVgERBcgUAAPJVICDdcYd0443SwYPusQsukObPl44/3uvoACB2SK4AAEC+uuce6YknMvYHDJDee8+dEggAiYR7rgAAQL555BHpwQcz9sePl/r08TIiAMg/jFwBAIB8YYnUXXdl7I8eTWIFILGRXAEAgJibMsW9xyrogQekm2/2MiIAyH8kVwAAIKbef1+65hq3kIW5805p8GCvowKA/EdyBQAAYuazz9x1rIJVAW0a4MMPszgwgMKB5AoAAMTEggVSx47S3r3ufteu0tixJFYACg+SKwAAkGc//yx16CDt2OHuX3SR9PLLUkqK15EBQMEhuQIAAHny++/SeedJ//2vu3/WWdIbb0ipqV5HBgAFi+QKAABEbc0aN7Fau9bdb95cevddqWRJryMDgIJHcgUAAKKyebN0/vnuyJU54QRp5kypTBmvIwMAb5BcAQCAiFnRCruvyu61MnXrSh99JFWq5HVkAOAdkisAABCxgQOlb75x29WquYnV0Ud7HRUAeIvkCgAAROStt6QxY9x28eLSjBnSscd6HRUAFPLkau7cuerYsaNq1KihpKQkTZ8+/bDn9+rVyzkv89aoUaP0c+67774sjzds2LAAng0AAIlv5Urp2msz9keNkpo18zIiAPAPT5OrXbt2qWnTphoT/PPXETz55JNau3Zt+vbnn3+qQoUKuvLKK8POs2Qr9Lwvvvgin54BAACFx4EDUvfu0tat7r7983v99V5HBQD+UcTLH37hhRc6W26VLVvW2YJspGvLli3q3bt32HlFihRRNZsADgAAYubee6X58912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xmZt2JC3a9J/EC36DqJF3/GfHTt2xM89V3lhSdVJJ52kli1bhh23kawge7xJkyaqX7++M5p17rnnZrmOjZzZfV+hI1e1atVS5cqVVaZMmXx+FsjtG40VJrHXhDcaRIK+U3iMGuWOWJlrr01R1apZ79uNFP0H0aLvIFr0Hf+xontxkVxVqlTJGUlav3592HHbt/ukDmfXrl2aMmWK/vWvfx3x5xxzzDHOz1q2bFm2yZXdn5VdwQvr0HRq/7A3Gl4TRIO+U7jWtipSRPr73+31js216T+IFn0H0aLv+Eskr4Onr1hqaqqaN2+u2bYoSUi2bvutW7c+7Pe+8cYbzn1Sf//734/4c/766y+nqmD16tVjEjcAwF8++khasyZjbatsis0CAJDvPE+HbTrehAkT9NJLL+nXX39V3759nVEpqx5oevToEVbwInRKYOfOnbMUqdi5c6fuvPNOzZ8/XytXrnQStU6dOunYY491SrwDABJ7bav//fMBAECB8/yeq65duzqFI4YOHap169apWbNmmjlzZnqRi1WrVmUZirM1sL744gt9+OGHWa5n0wx//PFHJ1nbunWratSoofPPP1/3338/a10BQALaskWaPt1tV6rkjlwBAFAokyvTr18/Z8uOFaHIrEGDBk4FleyUKFFCs2bNinmMAAD/rm0VXE3j6qtZ2woAUIinBQIAEKspgb16eRkJAKCwI7kCAMStX3+Vvv7abTdtKjVr5nVEAIDCjOQKABC3KGQBAPATkisAQFw6eDB8baurrvI6IgBAYUdyBQCI27Wt1q5125dcIlWu7HVEAIDCjuQKABCXKGQBAPAbkisAQFyvbWUjVqxtBQDwA5IrAEDcee01af9+t/33v0tFi3odEQAAJFcAgDjElEAAgB+RXAEA4srPP0vffuu2Tz5ZatLE64gAAHCRXAEA4spLL2W0GbUCAPgJyRUAIC7XtrL7rFjbCgDgJyRXAIC4MWuWtG5dxtpWlSp5HREAABlIrgAAcVnIondvLyMBACArkisAQFzYvFn6v/9z21WqSBdc4HVEAACEI7kCAMSFKVNY2woA4G8kVwAA3wsEpOefz9jv2dPLaAAAyB7JFQDA9+bPl777zm23aMHaVgAAfyK5AgD43ujRGe1+/byMBACAnJFcAQB8zUqvv/GG265YUera1euIAADIHskVAMDXJkyQDhxw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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA04AAAIjCAYAAAA0vUuxAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAS4tJREFUeJzt3Ql0FFXaxvEnCSQhYkBZZVFEUVAQlE0ExQUFF5RxQ0A2HVxwQXEDFRhEQFARRkAERRgR2RwZF8QPGXEZGFEQxQVcEGFgWBXCmkCS77xV0zEJSSrdJKnu9P93Tp10V6o7l+6bop/ce9+KyczMzBQAAAAAIF+x+X8LAAAAAGAITgAAAADggeAEAAAAAB4ITgAAAADggeAEAAAAAB4ITgAAAADggeAEAAAAAB4ITgAAAADggeAEAAAAAB4ITgCAYhMTE6O//OUvhTq2Tp066tWrV9A/Y/369c7PmTZtmsJZSbUz1NcRAFAwghMAIF/2Id8+7H/xxRdF8nxLly51gtSuXbtUWl+rvLYBAwb43TwAwFEqc7RPAABAfg4cOKAyZcrkCE5Dhw51RkQqVqyY49i1a9cqNjby/573xBNP6OSTT86xr2HDhjrppJOc16Ns2bK+tQ0AEDqCEwCg2CQmJhb62ISEBJUGl19+uZo1a3bUrwcAILxE/p/2AAAlykaLypcvr02bNqlTp07O7SpVqujBBx9Uenp6vmuc7OtDDz3k3LYRmcA0Nlv7k9fanN9++815zkaNGjk/Izk52QklX331VdBttqmG9rOmT59+xPfef/9953vvvPOOc3/Pnj267777nPZYmKtataouvfRSrVy5UkW9ximY1/KZZ57Reeedp0qVKqlcuXJq2rSp5s2bd1RtAgAUHsEJABA0+1Dfvn1750O8faBv27atnn32WU2ePDnfx1x77bXq0qWLc/u5557Tq6++6mwWFPKybt06zZ8/X1dddZXGjBnjhK7Vq1c7P2vz5s1BtddGgOrWras5c+Yc8b3Zs2fruOOOc/495o477tALL7yg6667ThMnTnRCjAWV77//vlA/a/fu3dqxY0eOrShey3Hjxunss892pgKOGDHCmQJ5ww036N133w3qtQAAhIapegCAoB08eFCdO3fWoEGDssLGOeeco5dffll33nlnno8566yznGNef/11Z3TFRnQKYiNNP/zwQ451T927d1f9+vWdnxP42YVl7bVg8vvvvztByaSlpenNN990Ql1g7ZEFkT59+jjhJeDhhx8u9M9p167dEfsyMzOP+rW018ICXMDdd9/tHGeh8sorryx0+wAAoWHECQAQEvuAn93555/vjBIVFZsmFwhNNiqzc+dOZyrb6aefHtK0OQsnhw4d0t///vesff/3f//nVPiz7wVY0YrPPvss6FGtgAkTJmjRokU5tqJ4LbOHJgt/NrJlxx3tFEIAQOEw4gQACJoVOcg9xc5GcewDfVHJyMhwpqfZdLlffvklx5ofm9YWrMaNGzujVTY179Zbb3X22e3KlSvr4osvzjpu9OjR6tmzp2rXru2sI7riiivUo0cPZ6pfYbRo0SLf4hBH81raGqwnn3xSq1atUmpqatZ+WzcFACh+jDgBAIIWFxdX7D/D1vH0799fF1xwgWbMmOEUcbDRmzPPPNMJVaGwkaUPP/zQWXdk4eOtt95y1jJlL5l+4403OqM9zz//vGrUqKGnn37a+Znvvfee/HotP/nkE1199dVOyLIguWDBAue16Nq1a4HTAAEARYcRJwBAiQlmdMQqxl100UXOWp/sbGqdjRKFGpzsOlJvvPGGqlWrppSUFN10001HHHfCCSeob9++zrZt2zZnLdHw4cOdqn5+sPZaaLLwmL1s+yuvvOJLewAgGhGcAAAl5phjjskKP4UZick9mjJ37lyndPepp54a0s9v0KCBU3TCpuhZcLKAZCNaATYdcO/evapQoULWPitHbiNP2afHlTR7LSx0Zp+uaOXNreogAKBkEJwAACXG1gyZxx57zBnpsUp2HTt2zApU2VkZciu93bt3b+f6RVaK/LXXXiv0WqOCRp0GDx7sjODYWqfsVfvsGk61atXS9ddf76yJsmIUH3zwgT7//PMcVfZKmlXNs+p5HTp0cKbn2SiYFaGwAPn111/71i4AiCYEJwBAiWnevLmGDRumSZMmaeHChc5aJSv8kFdwevTRR7Vv3z7NnDnTGSGy6XJWKnzAgAFHHZwef/xx7d+/P0c1PZOUlORMz7Nqe1Z9z9pn4cTWFeVXZr0kWPEKm7L41FNPORfntQsIjxo1yhl1IjgBQMmIyWRVKQAAAAAUiKp6AAAAAOCB4AQAAAAAHghOAAAAAOCB4AQAAAAAHghOAAAAAOCB4AQAAAAAHqLuOk52TY7Nmzfr2GOPda7CDgAAACA6ZWZmOhc/r1GjRo4Loucl6oKThabatWv73QwAAAAAYWLjxo2qVatWgcdEXXCykabAi5OcnOx3c/C/UcDt27erSpUqnkkfyI3+g1DRdxAq+g5CRd8JPykpKc6gSiAjFCTqglNgep6FJoJT+JxEDh486LwfnEQQLPoPQkXfQajoOwgVfSd8FWYJD+8YAAAAAHggOAEAAACAB4ITAAAAAHggOAEAAACAB4ITAAAAAHggOAEAAACAB4ITAAAAAHggOAEAAACAB4ITAAAAAHggOAEAAACAB4ITAAAAAHggOAEAAACAB4ITAAAAAHggOAEAAABAOAenjz/+WB07dlSNGjUUExOj+fPnez5myZIlOuecc5SQkKBTTz1V06ZNK5G2AgAAAIhevganffv2qXHjxpowYUKhjv/ll1905ZVX6qKLLtKqVat033336c9//rPef//9Ym8rAAAAgOhVxs8ffvnllztbYU2aNEknn3yynn32Wed+gwYN9Omnn+q5555T+/btFakOHjyY7/diY2MVHx9f7MempqYqMzMzz2NtNNBG+EI5Ni0tTRkZGfm2IzExMcexBcl9bDDPW9Cx1l5rtzl06JDS09OL/NjDhw87W1Eca++bvX9FfWzZsmUVFxcX9LH2GthrkZ8yZco4W7DH2ntWUJ/Ifaz198C/taBjre9aHy7M83oda6+BvRZFfWxJ/d5H4jmiuI4tCOeI0nGOKOyxhTlHBF4zO7ag3yPOEaXnHFFUnyMC73Fhjo2Wc0Qk8TU4BWvZsmVq165djn0WmGzkKT/2y5n95JOSkuJ8tV+Agn4JStL111+f7/eaNWumwYMHZ93v1q1bvifThg0basSIEVn3b7nllqx/b2716tXLCqDmzjvv1LZt2/I8tnbt2jlGBe313rhxY57HVq1aVS+99FLW/UceeUQ//vhjnscmJydrxowZzvtgJ9AhQ4bo22+/zfeEMHfu3Kz79u/84osvlJ+33nor67b9O//1r3/le+ycOXOyTpDjx4/X4sWL8z321VdfVYUKFZzbkydP1nvvvZfvsfY62OthbEppQVNR7eeeeOKJzu1Zs2Y5W37s32Pvn7HnLGi66vDhw9WoUSPntrX1xRdfzPfYQYMGqXnz5s7tDz/8UOPGjcv32Icfflht2rRxbttrO3r06HyP7devny655BLntr1n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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for fig in pympdata_result.figures.values():\n", + " display(fig)" + ] + }, + { + "cell_type": "markdown", + "id": "9028e89d", + "metadata": {}, + "source": [ + "## Comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0ab14f07", + "metadata": {}, + "outputs": [], + "source": [ + "assert (\n", + " py_pde_result.kymograph_result.shape == pympdata_result.kymograph_result.shape\n", + "), \"Kymograph results do not match in shape.\"" + ] + }, + { + "cell_type": "markdown", + "id": "43005389", + "metadata": {}, + "source": [ + "The calculated absolute difference between the results and Root Mean Square Error (RMSE):" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "24f2295e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Max difference: 0.12297365531933913\n", + "RMSE: 0.04884992568588479\n" + ] + } + ], + "source": [ + "difference = np.abs(pympdata_result.kymograph_result - py_pde_result.kymograph_result)\n", + "print(\"Max difference:\", np.max(difference))\n", + "\n", + "rmse = np.sqrt(np.mean(difference**2))\n", + "print(\"RMSE:\", rmse)" + ] + }, + { + "cell_type": "markdown", + "id": "99d598f1", + "metadata": {}, + "source": [ + "Similarity comparison:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "f2ac8a37", + "metadata": {}, + "outputs": [], + "source": [ + "assert np.allclose(\n", + " pympdata_result.kymograph_result, py_pde_result.kymograph_result, atol=0.2\n", + "), \"Kymograph results do not match.\"" + ] + }, + { + "cell_type": "markdown", + "id": "6ed7e1cd", + "metadata": {}, + "source": [ + "Time comparison:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "29c34574", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "py-pde time: 10.2355 seconds\n", + "PyMPDATA time: 746.6280 seconds\n" + ] + } + ], + "source": [ + "print(f\"py-pde time: {py_pde_time:.4f} seconds\")\n", + "print(f\"PyMPDATA time: {pympdata_time:.4f} seconds\")" + ] + }, + { + "cell_type": "markdown", + "id": "6a6f3732", + "metadata": {}, + "source": [ + "## Comparison for a smaller grid and fewer time steps" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8cf9e1e9", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:pde.tools.numba:Compile `dot_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `laplace` in PDE for `c`\n", + "INFO:pde.tools.numba:Compile `laplace` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid_bcs` with parallel=True\n", + "INFO:pde.tools.numba:Compile `apply_op_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `gradient` in PDE for `c`\n", + "INFO:pde.tools.numba:Compile `gradient` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `virtual_point` with parallel=True\n", + "INFO:pde.tools.numba:Compile `set_valid_bcs` with parallel=True\n", + "INFO:pde.tools.numba:Compile `apply_op_compiled` with parallel=True\n", + "INFO:pde.pdes.PDE:RHS for `c` has signature ('c', 't', 'none', 'bc_args', 'x')\n", + "INFO:pde.tools.numba:Compile `_heaviside_implemention` with parallel=True\n", + "INFO:pde.tools.numba:Compile `` with parallel=True\n", + "INFO:pde.tools.expressions.ScalarExpression:Parse sympy expression `(tanh(x) + 1.01)*laplace(c, none, bc_args) + dot(gradient(tanh(x) + 1.01, none, bc_args), gradient(c, none, bc_args))`\n", + "INFO:pde.tools.numba:Compile `_lambdifygenerated` with parallel=True\n", + "INFO:pde.tools.numba:Compile `rhs_func` with parallel=True\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `laplace` in PDE for `c`\n", + "INFO:pde.pdes.PDE:Using boundary condition `{'value': 0}` for operator `gradient` in PDE for `c`\n", + "INFO:pde.pdes.PDE:RHS for `c` has signature ('c', 't', 'none', 'bc_args', 'x')\n", + "INFO:pde.tools.expressions.ScalarExpression:Parse sympy expression `(tanh(x) + 1.01)*laplace(c, none, bc_args) + dot(gradient(tanh(x) + 1.01, none, bc_args), gradient(c, none, bc_args))`\n", + "INFO:pde.solvers.ExplicitSolver:Init explicit Euler stepper with dt=0.001\n", + "INFO:pde.solvers.controller:Simulation finished at t=10.0.\n", + "INFO:root:Starting heterogeneous diffusion simulation...\n", + "INFO:root:Using native PyMPDATA implementation (should be ~3x faster than Strang splitting)\n", + "INFO:root:Diffusivity range: 0.010 to 0.932\n", + "INFO:root:Using balanced mu coefficient: 0.050000\n", + "INFO:root:At step 10000/10000\n", + "INFO:root:Simulation completed!\n", + "INFO:root:Mass conservation: initial=32.000000, final=17.044883\n", + "INFO:root:Relative mass change: 4.67e+01%\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "py-pde time: 11.9268 seconds\n", + "PyMPDATA time: 93.0077 seconds\n" + ] + } + ], + "source": [ + "quicker_simulation_args = SimulationArgs(\n", + " grid_bounds= (-5.0, 0), # (-0.5, 0.5) -> (-5.0, 0)\n", + " grid_points=32, # 64 -> 32\n", + " initial_value=1.0,\n", + " sim_time=10.0, # 100.0 -> 10.0\n", + " dt=1e-3,\n", + ")\n", + "\n", + "with Timer() as timer:\n", + " py_pde_quick_result = solutions.py_pde_solution(quicker_simulation_args)\n", + "py_pde_quick_time = timer.time\n", + "\n", + "with Timer() as timer:\n", + " pympdata_quick_result = solutions.pympdata_solution(quicker_simulation_args)\n", + "pympdata_quick_time = timer.time\n", + "\n", + "print(f\"py-pde time: {py_pde_quick_time:.4f} seconds\")\n", + "print(f\"PyMPDATA time: {pympdata_quick_time:.4f} seconds\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "7c8c6cb5", + "metadata": {}, + "outputs": [], + "source": [ + "assert np.allclose(\n", + " pympdata_quick_result.kymograph_result, py_pde_quick_result.kymograph_result, atol=0.2\n", + "), \"Kymograph results do not match.\"" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/solutions.py b/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/solutions.py new file mode 100644 index 00000000..118f3e7e --- /dev/null +++ b/examples/PyMPDATA_examples/comparisons_against_pypde/diffusion_equation_with_spatial_dependence/solutions.py @@ -0,0 +1,181 @@ +""" +Helper functions to run two different implementations of the diffusion equation with spatial dependence. +""" + +import dataclasses +import logging +from typing import Any, Dict, Tuple + +import matplotlib.figure +import matplotlib.pyplot as plt +import numpy as np + +# from pde import PDE, CartesianGrid, MemoryStorage, ScalarField, plot_kymograph +import pde as py_pde + +from PyMPDATA import Options, ScalarField, Solver, Stepper, VectorField +from PyMPDATA.boundary_conditions import Constant + + +@dataclasses.dataclass(frozen=True) +class SimulationArgs: + """Dataclass to hold simulation arguments.""" + + grid_bounds: Tuple[float, float] + grid_points: int + initial_value: float + sim_time: float + dt: float + + +@dataclasses.dataclass(frozen=True) +class SimulationResult: + """Dataclass to hold simulation results, and additional produced plots.""" + + kymograph_result: np.ndarray + figures: Dict[str, matplotlib.figure.Figure] = dataclasses.field( + default_factory=dict + ) + extra: Dict[str, Any] = dataclasses.field(default_factory=dict) + + +def py_pde_solution(args: SimulationArgs): + """Runs the simulation using pyPDE.""" + + term_1 = "(1.01 + tanh(x)) * laplace(c)" + term_2 = "dot(gradient(1.01 + tanh(x)), gradient(c))" + eq = py_pde.PDE({"c": f"{term_1} + {term_2}"}, bc={"value": 0}) + + grid = py_pde.CartesianGrid([args.grid_bounds], args.grid_points) + field = py_pde.ScalarField(grid, args.initial_value) + + storage = py_pde.MemoryStorage() + result = eq.solve(field, args.sim_time, dt=args.dt, tracker=storage.tracker(1)) + + return SimulationResult( + kymograph_result=np.array(storage.data), + extra={"final_result": result, "storage": storage}, + ) + + +def pympdata_solution(args: SimulationArgs) -> SimulationResult: + """Runs the simulation using PyMPDATA.""" + + xmin, xmax = args.grid_bounds + dx = (xmax - xmin) / (args.grid_points - 1) + x = np.linspace(xmin + dx / 2, xmax - dx / 2, args.grid_points) + + n_steps = int(args.sim_time / args.dt) + + D_field = 1.01 + np.tanh(x) + + # initial condition - uniform field (to match py-pde reference exactly) + c0 = np.full( + args.grid_points, args.initial_value + ) # Uniform concentration everywhere + + # ── build a Solver with native heterogeneous diffusion ─────────────────────────── + opts = Options( + n_iters=3, # more MPDATA iterations → sharper features + non_zero_mu_coeff=True, + heterogeneous_diffusion=True, # Enable native heterogeneous diffusion + ) + + # Set up fields with proper boundary conditions + advectee = ScalarField( + data=c0, halo=opts.n_halo, boundary_conditions=(Constant(0.0),) + ) + advector = VectorField( + data=(np.zeros(args.grid_points + 1),), + halo=opts.n_halo, + boundary_conditions=(Constant(0.0),), + ) + diffusivity_field = ScalarField( + data=D_field, halo=opts.n_halo, boundary_conditions=(Constant(0.0),) + ) + + stepper = Stepper(options=opts, grid=(args.grid_points,)) + solver = Solver( + stepper=stepper, + advectee=advectee, + advector=advector, + diffusivity_field=diffusivity_field, + ) + + # ── march & record for kymograph ────────────────────────────────────────────── + logging.info("Starting heterogeneous diffusion simulation...") + logging.info( + "Using native PyMPDATA implementation (should be ~3x faster than Strang splitting)" + ) + + kymo = np.empty((n_steps + 1, args.grid_points)) + kymo[0] = solver.advectee.get() + + # Use stronger mu_coeff for more realistic long-time evolution + mu_coeff = 0.05 # Increased to get more decay over time + + logging.info(f"Diffusivity range: {D_field.min():.3f} to {D_field.max():.3f}") + logging.info(f"Using balanced mu coefficient: {mu_coeff:.6f}") + + for i in range(1, n_steps + 1): + if i % 10000 == 0: + logging.info(f"At step {i}/{n_steps}") + + # Single call per timestep (vs 3 calls in Strang splitting!) + solver.advance(n_steps=1, mu_coeff=(mu_coeff,)) + kymo[i] = solver.advectee.get() + + logging.info("Simulation completed!") + + res_kymo = np.empty((int(args.sim_time), args.grid_points)) + interval = int(1 / args.dt) + + for i in range(int(args.sim_time)): + step_data = kymo[i * interval + 1 : (i + 1) * interval + 1] + res_kymo[i] = step_data[step_data.shape[0] // 2] + + res_kymo = np.concat((kymo[0:1], res_kymo), axis=0) + + # ── plot ─────────────────────────────────────────────────────────────────────── + T = np.linspace(0, args.sim_time, int(args.sim_time) + 1) + X, Tgrid = np.meshgrid(x, T) + + figs = {} + + fig1, ax1 = plt.subplots(figsize=(10, 8)) + pcm = ax1.pcolormesh(X, Tgrid, res_kymo, shading="auto") + ax1.set_xlabel("x") + ax1.set_ylabel("Time") + figs["kymograph"] = fig1 + fig1.colorbar(pcm, ax=ax1) + plt.close(fig1) + + fig2, ax2 = plt.subplots(figsize=(10, 6)) + ax2.plot(x, D_field, "b-", linewidth=2) + ax2.set_xlabel("x") + ax2.set_ylabel("D(x)") + ax2.set_title("Heterogeneous Diffusivity") + ax2.grid(True, alpha=0.3) + figs["diffusivity_profile"] = fig2 + plt.close(fig2) + + fig3, ax3 = plt.subplots(figsize=(10, 6)) + ax3.plot(x, kymo[0], "k--", alpha=0.7, label="t=0") + ax3.plot(x, kymo[-1], "r-", label=f"t={args.sim_time}") + ax3.set_xlabel("x") + ax3.set_ylabel("c(x)") + ax3.set_title("Initial vs Final") + ax3.legend() + ax3.grid(True, alpha=0.3) + figs["initial_vs_final"] = fig3 + plt.close(fig3) + + # ── Summary statistics ───────────────────────────────────────────────────────── + logging.info( + f"Mass conservation: initial={kymo[0].sum():.6f}, final={kymo[-1].sum():.6f}" + ) + logging.info( + f"Relative mass change: {abs(kymo[-1].sum() - kymo[0].sum()) / kymo[0].sum() * 100:.2e}%" + ) + + return SimulationResult(kymograph_result=res_kymo, figures=figs) diff --git a/examples/docs/pympdata_examples_landing.md b/examples/docs/pympdata_examples_landing.md index c203e24c..52d4f3f6 100644 --- a/examples/docs/pympdata_examples_landing.md +++ b/examples/docs/pympdata_examples_landing.md @@ -19,7 +19,8 @@ The examples are grouped by the dimensionality of the computational grid. | Black-Scholes equation, option pricing
$$ \frac{\partial f}{\partial t} + rS \frac{\partial f}{\partial S} + \frac{\sigma^2}{2} S^2 \frac{\partial^2 f}{\partial S^2} - rf = 0$$ | `PyMPDATA_examples.Arabas_and_Farhat_2020`* | | advection equation, homogeneous, several algorithm variants comparison: infinite-gauge, flux-corrected,.. | `PyMPDATA_examples.Smolarkiewicz_2006_Figs_3_4_10_11_12` | | Size-spectral advection, particle population condensational growth, coordinate transformation
$$ \partial_t (G \psi) + \nabla \cdot (Gu \psi) = 0 $$ | `PyMPDATA_examples.Olesik_et_al_2022`* | -| advection equation, [double-pass donor-cell option](https://osti.gov/biblio/7049237) | `PyMPDATA_examples.DPDC` | +| advection equation, [double-pass donor-cell option](https://osti.gov/biblio/7049237) | `PyMPDATA_examples.DPDC` | +| diffusion equation with spatial dependence, heterogeneous diffusivity $$ \partial_t c = \nabla (D(r) \nabla c) $$ | `PyMPDATA_examples.comparison_against_py_pde.diffusion_equation_with_spatial_dependence`* | ## in 2D | tags | link | diff --git a/examples/setup.py b/examples/setup.py index e1ed3658..87fc885f 100644 --- a/examples/setup.py +++ b/examples/setup.py @@ -38,6 +38,7 @@ def get_long_description(): "meshio", "numdifftools", "pandas", + "py-pde" + ("==0.32.2" if CI else ""), ], author="https://github.com/open-atmos/PyMPDATA/graphs/contributors", license="GPL-3.0", diff --git a/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/__init__,py b/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/__init__,py new file mode 100644 index 00000000..e69de29b diff --git a/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/test_heterogeneous_laplacian_coverage.py b/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/test_heterogeneous_laplacian_coverage.py new file mode 100644 index 00000000..9f44a7b6 --- /dev/null +++ b/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/test_heterogeneous_laplacian_coverage.py @@ -0,0 +1,379 @@ +""" +Comprehensive tests for heterogeneous Laplacian functionality to improve code coverage. +Tests error conditions, edge cases, and the actual computation logic. +""" + +import pytest +import numpy as np + +from PyMPDATA import Options, ScalarField, Solver, Stepper, VectorField +from PyMPDATA.boundary_conditions import Constant +from PyMPDATA.impl.formulae_laplacian import ( + make_heterogeneous_laplacian, + __make_heterogeneous_laplacian as _make_heterogeneous_laplacian, +) +from PyMPDATA.impl.traversals import Traversals +from PyMPDATA.impl.indexers import make_indexers +from PyMPDATA.impl.enumerations import META_AND_DATA_META, MAX_DIM_NUM + + +class TestHeterogeneousLaplacianErrorConditions: + """Test error conditions that should raise NotImplementedError""" + + def test_make_heterogeneous_laplacian_without_non_zero_mu_coeff(self): + """Test that make_heterogeneous_laplacian raises error when non_zero_mu_coeff is False""" + options = Options(non_zero_mu_coeff=False, heterogeneous_diffusion=True) + traversals = Traversals( + grid=(10,), + halo=options.n_halo, + jit_flags=options.jit_flags, + n_threads=1, + left_first=tuple([True] * MAX_DIM_NUM), + buffer_size=0, + ) + + with pytest.raises( + NotImplementedError, + match="requires options.non_zero_mu_coeff to be enabled", + ): + make_heterogeneous_laplacian(False, options, traversals) + + def test_make_heterogeneous_laplacian_without_heterogeneous_diffusion(self): + """Test that make_heterogeneous_laplacian raises error when heterogeneous_diffusion is False""" + options = Options(non_zero_mu_coeff=True, heterogeneous_diffusion=False) + traversals = Traversals( + grid=(10,), + halo=options.n_halo, + jit_flags=options.jit_flags, + n_threads=1, + left_first=tuple([True] * MAX_DIM_NUM), + buffer_size=0, + ) + + with pytest.raises( + NotImplementedError, + match="requires options.heterogeneous_diffusion to be enabled", + ): + make_heterogeneous_laplacian(False, options, traversals) + + def test_make_heterogeneous_laplacian_with_non_unit_g_factor(self): + """Test that __make_heterogeneous_laplacian raises error when non_unit_g_factor is True""" + options = Options(non_zero_mu_coeff=True, heterogeneous_diffusion=True) + traversals = Traversals( + grid=(10,), + halo=options.n_halo, + jit_flags=options.jit_flags, + n_threads=1, + left_first=tuple([True] * MAX_DIM_NUM), + buffer_size=0, + ) + + with pytest.raises(NotImplementedError): + make_heterogeneous_laplacian(True, options, traversals) + + +class TestHeterogeneousLaplacianFunctionality: + """Test the actual heterogeneous diffusion functionality""" + + def test_heterogeneous_diffusion_1d_basic(self): + """Test basic 1D heterogeneous diffusion with varying diffusivity""" + grid_size = 10 + dx = 1.0 + + # Set up initial condition - Gaussian pulse + x = np.linspace(0, (grid_size - 1) * dx, grid_size) + x_center = x[grid_size // 2] + sigma = 1.0 + c0 = np.exp(-0.5 * ((x - x_center) / sigma) ** 2) + + # Set up spatially varying diffusivity - higher in the center + D_field = 0.1 + 0.9 * np.exp(-0.5 * ((x - x_center) / (2 * sigma)) ** 2) + + # Create options and fields + options = Options( + n_iters=3, non_zero_mu_coeff=True, heterogeneous_diffusion=True + ) + + advectee = ScalarField( + data=c0, halo=options.n_halo, boundary_conditions=(Constant(0.0),) + ) + advector = VectorField( + data=(np.zeros(grid_size + 1),), + halo=options.n_halo, + boundary_conditions=(Constant(0.0),), + ) + diffusivity_field = ScalarField( + data=D_field, halo=options.n_halo, boundary_conditions=(Constant(0.1),) + ) + + # Create solver + stepper = Stepper(options=options, grid=(grid_size,)) + solver = Solver( + stepper=stepper, + advectee=advectee, + advector=advector, + diffusivity_field=diffusivity_field, + ) + + # Store initial state + initial_sum = solver.advectee.get().sum() + initial_max = solver.advectee.get().max() + + # Advance one step + solver.advance(n_steps=1, mu_coeff=(0.01,)) + + # Check results + final_state = solver.advectee.get() + final_sum = final_state.sum() + final_max = final_state.max() + + # Mass should be conserved + np.testing.assert_almost_equal(final_sum, initial_sum, decimal=6) + # Maximum should decrease due to diffusion + assert final_max < initial_max + # No negative values should appear + assert np.all(final_state >= 0) + + def test_heterogeneous_diffusion_with_zero_diffusivity(self): + """Test handling of zero diffusivity values""" + grid_size = 5 + + # Initial condition + c0 = np.array([0.0, 0.0, 1.0, 0.0, 0.0]) + + # Diffusivity with zeros + D_field = np.array([0.0, 0.1, 0.0, 0.1, 0.0]) + + options = Options( + n_iters=2, non_zero_mu_coeff=True, heterogeneous_diffusion=True + ) + + advectee = ScalarField( + data=c0, halo=options.n_halo, boundary_conditions=(Constant(0.0),) + ) + advector = VectorField( + data=(np.zeros(grid_size + 1),), + halo=options.n_halo, + boundary_conditions=(Constant(0.0),), + ) + diffusivity_field = ScalarField( + data=D_field, halo=options.n_halo, boundary_conditions=(Constant(0.0),) + ) + + stepper = Stepper(options=options, grid=(grid_size,)) + solver = Solver( + stepper=stepper, + advectee=advectee, + advector=advector, + diffusivity_field=diffusivity_field, + ) + + # Should not crash with zero diffusivity + solver.advance(n_steps=1, mu_coeff=(0.01,)) + + # Mass should still be conserved + final_state = solver.advectee.get() + np.testing.assert_almost_equal(final_state.sum(), c0.sum(), decimal=6) + + def test_heterogeneous_diffusion_2d_basic(self): + """Test 2D heterogeneous diffusion""" + grid_shape = (5, 5) + + # Initial condition - point source in center + c0 = np.zeros(grid_shape) + c0[2, 2] = 1.0 + + # Spatially varying diffusivity + D_field = np.ones(grid_shape) * 0.1 + D_field[2, 2] = 0.5 # Higher diffusivity at center + + options = Options( + n_iters=3, non_zero_mu_coeff=True, heterogeneous_diffusion=True + ) + + boundary_conditions = tuple([Constant(0.0)] * 2) + + advectee = ScalarField( + data=c0, halo=options.n_halo, boundary_conditions=boundary_conditions + ) + advector = VectorField( + data=( + np.zeros((grid_shape[0] + 1, grid_shape[1])), + np.zeros((grid_shape[0], grid_shape[1] + 1)), + ), + halo=options.n_halo, + boundary_conditions=boundary_conditions, + ) + diffusivity_field = ScalarField( + data=D_field, halo=options.n_halo, boundary_conditions=boundary_conditions + ) + + stepper = Stepper(options=options, grid=grid_shape) + solver = Solver( + stepper=stepper, + advectee=advectee, + advector=advector, + diffusivity_field=diffusivity_field, + ) + + initial_sum = solver.advectee.get().sum() + + # Advance multiple steps + solver.advance(n_steps=2, mu_coeff=(0.01, 0.01)) + + final_state = solver.advectee.get() + final_sum = final_state.sum() + + # Mass conservation + np.testing.assert_almost_equal(final_sum, initial_sum, decimal=6) + # Diffusion should spread the mass + assert final_state[2, 2] < 1.0 + assert np.sum(final_state > 0) > 1 + + def test_heterogeneous_diffusion_high_contrast(self): + """Test with high contrast in diffusivity values""" + grid_size = 10 + + # Initial condition + c0 = np.zeros(grid_size) + c0[5] = 1.0 + + # High contrast diffusivity + D_field = np.ones(grid_size) * 1e-6 # Very low diffusivity + D_field[4:7] = 1.0 # High diffusivity region + + options = Options( + n_iters=5, non_zero_mu_coeff=True, heterogeneous_diffusion=True + ) + + advectee = ScalarField( + data=c0, halo=options.n_halo, boundary_conditions=(Constant(0.0),) + ) + advector = VectorField( + data=(np.zeros(grid_size + 1),), + halo=options.n_halo, + boundary_conditions=(Constant(0.0),), + ) + diffusivity_field = ScalarField( + data=D_field, halo=options.n_halo, boundary_conditions=(Constant(1e-6),) + ) + + stepper = Stepper(options=options, grid=(grid_size,)) + solver = Solver( + stepper=stepper, + advectee=advectee, + advector=advector, + diffusivity_field=diffusivity_field, + ) + + solver.advance(n_steps=1, mu_coeff=(0.1,)) + + final_state = solver.advectee.get() + + # Should handle high contrast without numerical issues + assert np.all(final_state >= 0) + assert not np.any(np.isnan(final_state)) + assert not np.any(np.isinf(final_state)) + + def test_heterogeneous_diffusion_mass_conservation_precision(self): + """Test mass conservation with various diffusivity patterns""" + grid_size = 20 + + # Different diffusivity patterns to test + x = np.linspace(0, 2 * np.pi, grid_size) + patterns = [ + np.ones(grid_size) * 0.1, # Uniform + 0.1 + 0.9 * np.sin(x) ** 2, # Sinusoidal + np.exp(-0.1 * (x - np.pi) ** 2), # Gaussian + np.where(x < np.pi, 0.01, 1.0), # Step function + ] + + for i, D_field in enumerate(patterns): + # Initial condition - smooth profile + c0 = np.exp(-0.5 * ((x - np.pi) / 0.5) ** 2) + + options = Options( + n_iters=4, non_zero_mu_coeff=True, heterogeneous_diffusion=True + ) + + advectee = ScalarField( + data=c0, halo=options.n_halo, boundary_conditions=(Constant(0.0),) + ) + advector = VectorField( + data=(np.zeros(grid_size + 1),), + halo=options.n_halo, + boundary_conditions=(Constant(0.0),), + ) + diffusivity_field = ScalarField( + data=D_field, + halo=options.n_halo, + boundary_conditions=(Constant(D_field[0]),), + ) + + stepper = Stepper(options=options, grid=(grid_size,)) + solver = Solver( + stepper=stepper, + advectee=advectee, + advector=advector, + diffusivity_field=diffusivity_field, + ) + + initial_mass = solver.advectee.get().sum() + + # Run for multiple steps + for step in range(5): + solver.advance(n_steps=1, mu_coeff=(0.02,)) + + current_mass = solver.advectee.get().sum() + + # Mass should be conserved to high precision + np.testing.assert_almost_equal( + current_mass, + initial_mass, + decimal=8, + err_msg=f"Mass not conserved for pattern {i} at step {step}", + ) + + +class TestHeterogeneousLaplacianDirectUnitTests: + """Direct unit tests for __make_heterogeneous_laplacian function creation. + + Note: The internal computation lines (128-148) are covered through the integration + tests in TestHeterogeneousLaplacianFunctionality, as direct testing requires + complex Numba-compatible data structures that are difficult to mock properly. + """ + + def test_make_heterogeneous_laplacian_direct_with_non_unit_g_factor_error(self): + """Test direct call to __make_heterogeneous_laplacian with non_unit_g_factor=True (line 123)""" + options = Options() + indexers = make_indexers(options.jit_flags) + + # This should raise NotImplementedError for non_unit_g_factor=True (line 123) + with pytest.raises(NotImplementedError): + _make_heterogeneous_laplacian( + jit_flags=options.jit_flags, + ats=indexers[1].ats[2], # 1D, inner dimension + epsilon=options.epsilon, + non_unit_g_factor=True, + ) + + def test_make_heterogeneous_laplacian_function_creation_success(self): + """Test that __make_heterogeneous_laplacian creates function successfully""" + options = Options() + indexers = make_indexers(options.jit_flags) + + # This should successfully create a function + het_laplacian_func = _make_heterogeneous_laplacian( + jit_flags=options.jit_flags, + ats=indexers[1].ats[2], # 1D, inner dimension + epsilon=options.epsilon, + non_unit_g_factor=False, + ) + + # Verify it's a callable function + assert callable(het_laplacian_func) + + # Verify it has Numba compilation attributes + assert hasattr( + het_laplacian_func, "py_func" + ) # Numba compiled function attribute diff --git a/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/test_similarity.py b/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/test_similarity.py new file mode 100644 index 00000000..f80bddea --- /dev/null +++ b/tests/smoke_tests/comparison_against_pypde/diffusion_equation_with_spatial_dependence/test_similarity.py @@ -0,0 +1,99 @@ +""" +Tests for comparing the results of PyMPDATA and py-pde for a diffusion equation with spatial dependence. +""" + +import numpy as np +import pde as py_pde +import pytest +from PyMPDATA_examples.comparisons_against_pypde.diffusion_equation_with_spatial_dependence import ( + solutions, +) + +from PyMPDATA import Options + + +@pytest.fixture +def original_simulation_args() -> solutions.SimulationArgs: + """Fixture with the simulation arguments.""" + + return solutions.SimulationArgs( + grid_bounds=(-5.0, 5.0), + grid_points=64, + initial_value=1.0, + sim_time=100.0, + dt=1e-3, + ) + + +@pytest.fixture +def quicker_simulation_args() -> solutions.SimulationArgs: + """Fixture with the simulation arguments.""" + + return solutions.SimulationArgs( + grid_bounds=(-5.0, 0), # (-0.5, 0.5) -> (-5.0, 0) + grid_points=32, # 64 -> 32 + initial_value=1.0, + sim_time=10.0, # 100.0 -> 10.0 + dt=1e-3, + ) + + +def test_similarity(original_simulation_args: solutions.SimulationArgs): + """Tests that the results of the two implementations (py-pde and PyMPDATA) are similar.""" + + assert hasattr( + Options, "heterogeneous_diffusion" + ), "Options should have heterogeneous_diffusion field" + + py_pde_result = solutions.py_pde_solution(original_simulation_args) + + pympdata_result = solutions.pympdata_solution(original_simulation_args) + + difference = np.abs( + pympdata_result.kymograph_result - py_pde_result.kymograph_result + ) + rmse = np.sqrt(np.mean(difference**2)) + + assert ( + pympdata_result.kymograph_result.shape == py_pde_result.kymograph_result.shape + ), "Kymograph results from both implementations should have the same shape." + assert np.allclose( + pympdata_result.kymograph_result, py_pde_result.kymograph_result, atol=0.2 + ), "Kymograph results from both implementations should be similar within the tolerance." + + assert rmse < 0.05 + + +def test_consistency_across_runs( + quicker_simulation_args: solutions.SimulationArgs, +): + """Tests that the results of the two implementations (py-pde and PyMPDATA) are similar.""" + + assert hasattr( + Options, "heterogeneous_diffusion" + ), "Options should have heterogeneous_diffusion field" + + py_pde_result_1 = solutions.py_pde_solution(quicker_simulation_args) + py_pde_result_2 = solutions.py_pde_solution(quicker_simulation_args) + + assert ( + py_pde_result_1.kymograph_result.shape == py_pde_result_2.kymograph_result.shape + ), "Kymograph results from both runs should have the same shape." + assert np.allclose( + py_pde_result_1.kymograph_result, + py_pde_result_2.kymograph_result, + atol=0.2, + ), "Kymograph results from both runs should be similar within the tolerance." + + pympdata_result_1 = solutions.pympdata_solution(quicker_simulation_args) + pympdata_result_2 = solutions.pympdata_solution(quicker_simulation_args) + + assert ( + pympdata_result_1.kymograph_result.shape + == pympdata_result_2.kymograph_result.shape + ), "Kymograph results from both runs should have the same shape." + assert np.allclose( + pympdata_result_1.kymograph_result, + pympdata_result_2.kymograph_result, + atol=0.2, + ), "Kymograph results from both runs should be similar within the tolerance."