diff --git a/.github/workflows/make_radas_data.sh b/.github/workflows/make_radas_data.sh new file mode 100644 index 00000000..4e93bce6 --- /dev/null +++ b/.github/workflows/make_radas_data.sh @@ -0,0 +1,15 @@ +set -ex + +git clone https://github.com/cfs-energy/radas.git + +pushd radas + +git checkout d9e23824f2edc46ef35e2fd54cf26438a3180733 + +poetry install --only main + +poetry run python adas_data/fetch_adas_data.py + +poetry run python run_radas.py all + +popd diff --git a/.github/workflows/workflow_actions.yml b/.github/workflows/workflow_actions.yml new file mode 100644 index 00000000..3d372376 --- /dev/null +++ b/.github/workflows/workflow_actions.yml @@ -0,0 +1,113 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: workflow_actions + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "main" branch + pull_request: [] + push: + branches: + - 'main' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + tag: "Manual run" + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + radas: + runs-on: ubuntu-22.04 + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Install Poetry + run: curl -sSL https://install.python-poetry.org | python - --version 1.6.1 + + - name: Set up Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: '3.11' + cache: 'poetry' + + - name: Cache radas results + id: radas + uses: actions/cache@v3 + with: + path: radas + key: radas-${{ hashFiles('.github/workflows/make_radas_data.sh')}} + + - name: Make radas data + if: steps.radas.outputs.cache-hit != 'true' + run: bash .github/workflows/make_radas_data.sh + + build: + needs: radas + # The type of runner that the job will run on + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + python-version: ['3.9', '3.10', '3.11'] # should test the versions we allow for in pyproject.toml + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Install pandoc + run: sudo apt-get update && sudo apt-get install pandoc + + - name: Install Poetry + run: curl -sSL https://install.python-poetry.org | python - --version 1.6.1 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + + - name: Setup + run: poetry install + + - uses: actions/cache/restore@v3 + id: radas + with: + path: radas + key: radas-${{ hashFiles('.github/workflows/make_radas_data.sh')}} + + - name: Check cache hit + if: steps.radas.outputs.cache-hit != 'true' + run: exit 1 + + - name: Copy radas data + run: cp ./radas/cases/*/output/*.nc cfspopcon/atomic_data/ + + - name: Tests + run: MPLBACKEND=Agg poetry run pytest tests --nbmake example_cases + + - name: Test package + run: | + poetry build -f wheel + python -m venv test_env + source ./test_env/bin/activate + pip install $(find ./dist -name "*.whl") + # enter tempdir so import cfspopcon doesn't find the cfspopcon directory + mkdir tmp_dir && cd tmp_dir + echo $(python -c 'from cfspopcon import atomic_data;from pathlib import Path; print(Path(atomic_data.__file__).parent)') + cp ../radas/cases/*/output/*.nc $(python -c 'from cfspopcon import atomic_data;from pathlib import Path; print(Path(atomic_data.__file__).parent)') + MPLBACKEND=Agg popcon ../example_cases/SPARC_PRD/input.yaml -p ../example_cases/SPARC_PRD/plot_popcon.yaml --show + + - name: Run pre-commit checks + run: poetry run pre-commit run --show-diff-on-failure --color=always --all-files + + - name: Test docs + # instead of make html we use sphinx-build directly to add more options + run: | + cd docs + poetry run sphinx-build --keep-going -Wnb html . _build/ + poetry run make doctest + poetry run make linkcheck + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..30980908 --- /dev/null +++ b/.gitignore @@ -0,0 +1,140 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_* + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# vscode +*.vscode + +#macOS metadata +.DS_Store + +# Mess +example_cases/SPARC_PRD/output/* +# avoid committing nc files +*.nc diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..1a17c1e8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,33 @@ +# per default we only run over the files in the python package +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-added-large-files + # but no large files anywhere ;) + files: '' + exclude: ".*getting_started.ipynb" +- repo: local + hooks: + - id: black + name: Black + entry: poetry run black + language: system + types: [python] +- repo: local + hooks: + - id: ruff + name: ruff + entry: poetry run ruff + language: system + types: [python] + files: '^cfspopcon/' +- repo: local + hooks: + - id: mypy + name: mypy + entry: poetry run mypy + language: system + types: [python] + files: '^cfspopcon/' + exclude: ^cfspopcon/plotting diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..9e53666a --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,18 @@ +version: 2 + +build: + os: "ubuntu-20.04" + tools: + python: "3.10" + jobs: + post_create_environment: + # Install poetry + # https://python-poetry.org/docs/#installing-manually + - pip install poetry + # Tell poetry to not use a virtual environment + - poetry config virtualenvs.create false + post_install: + - poetry install + +sphinx: + configuration: docs/conf.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..2cb0261b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please make sure to check out our [Developer's Guide](docs/doc_sources/dev_guide.rst). +It will show you how to setup a development environment for this project and covers our contributing guidelines. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..ca440437 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2023 Commonwealth Fusion Systems + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..3bc2161d --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +cfspopcon: 0D Plasma Calculations & Plasma OPerating CONtours +-------------------------------------------------------------- + +[![Build Status](https://github.com/cfs-energy/cfspopcon/actions/workflows/workflow_actions.yml/badge.svg)](https://github.com/cfs-energy/cfspopcon/actions) +[![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/) +[![Documentation Status](https://readthedocs.org/projects/cfspopcon/badge/?version=latest)](https://cfspopcon.readthedocs.io/en/latest/?badge=latest) + +For more information please have a look at our [documentation](https://cfspopcon.readthedocs.io/en/latest/). diff --git a/cfspopcon/__init__.py b/cfspopcon/__init__.py new file mode 100644 index 00000000..28e90179 --- /dev/null +++ b/cfspopcon/__init__.py @@ -0,0 +1,49 @@ +"""Physics calculations & lumped-parameter models.""" +from importlib.metadata import metadata + +__version__ = metadata(__package__)["Version"] +__author__ = metadata(__package__)["Author"] + +from . import algorithms, file_io, formulas, helpers, named_options, unit_handling +from .algorithms.algorithm_class import Algorithm, CompositeAlgorithm +from .input_file_handling import read_case +from .plotting import read_plot_style +from .point_selection import find_coords_of_maximum, find_coords_of_minimum +from .unit_handling import ( + Quantity, + Unit, + convert_to_default_units, + convert_units, + default_unit, + magnitude, + magnitude_in_default_units, + set_default_units, + ureg, + wraps_ufunc, +) + +# export main classes users should need as well as the option enums +__all__ = [ + "helpers", + "named_options", + "algorithms", + "formulas", + "unit_handling", + "ureg", + "Quantity", + "Unit", + "wraps_ufunc", + "magnitude_in_default_units", + "set_default_units", + "default_unit", + "convert_to_default_units", + "convert_units", + "magnitude", + "read_case", + "read_plot_style", + "find_coords_of_maximum", + "find_coords_of_minimum", + "Algorithm", + "CompositeAlgorithm", + "file_io", +] diff --git a/cfspopcon/algorithms/__init__.py b/cfspopcon/algorithms/__init__.py new file mode 100644 index 00000000..8a915b7d --- /dev/null +++ b/cfspopcon/algorithms/__init__.py @@ -0,0 +1,74 @@ +"""POPCON algorithms.""" +from typing import Union + +from ..named_options import Algorithms +from .algorithm_class import Algorithm, CompositeAlgorithm +from .beta import calc_beta +from .composite_algorithm import predictive_popcon +from .core_radiated_power import calc_core_radiated_power +from .extrinsic_core_radiator import calc_extrinsic_core_radiator +from .fusion_gain import calc_fusion_gain +from .geometry import calc_geometry +from .heat_exhaust import calc_heat_exhaust +from .ohmic_power import calc_ohmic_power +from .peaked_profiles import calc_peaked_profiles +from .plasma_current_from_q_star import calc_plasma_current_from_q_star +from .power_balance_from_tau_e import calc_power_balance_from_tau_e +from .q_star_from_plasma_current import calc_q_star_from_plasma_current +from .single_functions import SINGLE_FUNCTIONS +from .two_point_model_fixed_fpow import two_point_model_fixed_fpow +from .two_point_model_fixed_qpart import two_point_model_fixed_qpart +from .two_point_model_fixed_tet import two_point_model_fixed_tet +from .use_LOC_tau_e_below_threshold import use_LOC_tau_e_below_threshold +from .zeff_and_dilution_from_impurities import calc_zeff_and_dilution_from_impurities + +ALGORITHMS: dict[Algorithms, Union[Algorithm, CompositeAlgorithm]] = { + Algorithms["calc_beta"]: calc_beta, + Algorithms["calc_core_radiated_power"]: calc_core_radiated_power, + Algorithms["calc_extrinsic_core_radiator"]: calc_extrinsic_core_radiator, + Algorithms["calc_fusion_gain"]: calc_fusion_gain, + Algorithms["calc_geometry"]: calc_geometry, + Algorithms["calc_heat_exhaust"]: calc_heat_exhaust, + Algorithms["calc_ohmic_power"]: calc_ohmic_power, + Algorithms["calc_peaked_profiles"]: calc_peaked_profiles, + Algorithms["calc_plasma_current_from_q_star"]: calc_plasma_current_from_q_star, + Algorithms["calc_power_balance_from_tau_e"]: calc_power_balance_from_tau_e, + Algorithms["predictive_popcon"]: predictive_popcon, + Algorithms["calc_q_star_from_plasma_current"]: calc_q_star_from_plasma_current, + Algorithms["two_point_model_fixed_fpow"]: two_point_model_fixed_fpow, + Algorithms["two_point_model_fixed_qpart"]: two_point_model_fixed_qpart, + Algorithms["two_point_model_fixed_tet"]: two_point_model_fixed_tet, + Algorithms["calc_zeff_and_dilution_from_impurities"]: calc_zeff_and_dilution_from_impurities, + Algorithms["use_LOC_tau_e_below_threshold"]: use_LOC_tau_e_below_threshold, + **SINGLE_FUNCTIONS, +} + + +def get_algorithm(algorithm: Union[Algorithms, str]) -> Union[Algorithm, CompositeAlgorithm]: + """Accessor for algorithms.""" + if isinstance(algorithm, str): + algorithm = Algorithms[algorithm] + + return ALGORITHMS[algorithm] + + +__all__ = [ + "calc_beta", + "calc_core_radiated_power", + "calc_extrinsic_core_radiator", + "calc_fusion_gain", + "calc_geometry", + "calc_heat_exhaust", + "calc_ohmic_power", + "calc_peaked_profiles", + "calc_plasma_current_from_q_star", + "calc_power_balance_from_tau_e", + "predictive_popcon", + "calc_q_star_from_plasma_current", + "two_point_model_fixed_fpow", + "two_point_model_fixed_qpart", + "two_point_model_fixed_tet", + "calc_zeff_and_dilution_from_impurities", + "ALGORITHMS", + "get_algorithm", +] diff --git a/cfspopcon/algorithms/algorithm_class.py b/cfspopcon/algorithms/algorithm_class.py new file mode 100644 index 00000000..480e29ce --- /dev/null +++ b/cfspopcon/algorithms/algorithm_class.py @@ -0,0 +1,413 @@ +"""Defines a class for different POPCON algorithms.""" +from __future__ import annotations + +import inspect +from collections.abc import Callable, Sequence +from functools import wraps +from typing import Any, Optional, Union +from warnings import warn + +import xarray as xr + +from ..unit_handling import convert_to_default_units + +FunctionType = Callable[..., dict[str, Any]] + + +class Algorithm: + """A class which handles the input and output of POPCON algorithms.""" + + def __init__(self, function: FunctionType, return_keys: list[str], name: Optional[str] = None): + """Initialise an Algorithm. + + Args: + function: a callable function + return_keys: the arguments which are returned from the function + name: Descriptive name for algorithm + """ + self._function = function + self._name = self._function.__name__ if name is None else name + + self._signature = inspect.signature(function) + for p in self._signature.parameters.values(): + if p.kind not in ( + inspect.Parameter.POSITIONAL_OR_KEYWORD, + inspect.Parameter.KEYWORD_ONLY, + inspect.Parameter.VAR_KEYWORD, + ): + raise ValueError( + f"Algorithm only supports functions with keyword arguments, but {function}, has {p.kind} parameter {p.name}" + ) + self.input_keys = list(self._signature.parameters.keys()) + self.return_keys = return_keys + + self.default_values = { + key: val.default for key, val in self._signature.parameters.items() if val.default is not inspect.Parameter.empty + } + self.default_keys = list(self.default_values.keys()) + + self.required_input_keys = [key for key in self.input_keys if key not in self.default_keys] + + self.__doc__ = self._make_docstring() + + self.run = self._make_run(self._function) + + def _make_docstring(self) -> str: + """Makes a doc-string detailing the function inputs and outputs.""" + return_string = ( + f"Algorithm: {self._name}\n" + "Inputs:\n" + ", ".join(self.input_keys) + "\n" + "Outputs:\n" + ", ".join(self.return_keys) + ) + return return_string + + def __repr__(self) -> str: + """Return a simple string description of the Algorithm.""" + return f"Algorithm: {self._name}" + + @classmethod + def _make_run(cls, func: FunctionType) -> Callable[..., xr.Dataset]: + """Helper to create the `run()` function with correct doc string. + + Args: + func: function to be wrapped + + Returns: a xarray DataSet of the result + """ + + @wraps(func) + def run(**kwargs: Any) -> xr.Dataset: + result = func(**kwargs) + dataset = xr.Dataset(result) + return dataset + + return run + + def update_dataset(self, dataset: xr.Dataset, in_place: bool = False) -> Optional[xr.Dataset]: + """Retrieve inputs from passed dataset and return a new dataset combining input and output quantities. + + Specifying in_place=True modifies the dataset in place (changing the input), whereas in_place=False will + return a copy of the dataset with the outputs appended. + + Args: + dataset: input dataset + in_place: modify the dataset in place, otherwise return a modified dataset keeping the input unchanged. + + Returns: modified dataset + """ + if not in_place: + dataset = dataset.copy(deep=True) + + input_values = {} + for key in self.input_keys: + if key in dataset.keys(): + input_values[key] = dataset[key] + elif key in self.default_keys: + input_values[key] = self.default_values[key] + else: + sorted_dataset_keys = ", ".join(sorted(dataset.keys())) # type:ignore[arg-type] + sorted_default_keys = ", ".join(sorted(self.default_keys)) + raise KeyError(f"Key '{key}' not in dataset keys [{sorted_dataset_keys}] or default values [{sorted_default_keys}]") + + result = self._function(**input_values) + + for key, val in result.items(): + dataset[key] = val + + if not in_place: + return dataset + else: + return None + + def __add__(self, other: Union[Algorithm, CompositeAlgorithm]) -> CompositeAlgorithm: + """Build a CompositeAlgorithm composed of this Algorithm and another Algorithm or CompositeAlgorithm.""" + if isinstance(other, CompositeAlgorithm): + return CompositeAlgorithm(algorithms=[self, *other.algorithms]) + else: + return CompositeAlgorithm(algorithms=[self, other]) + + @classmethod + def from_single_function( + cls, func: Callable, return_keys: list[str], name: Optional[str] = None, skip_unit_conversion: bool = False + ) -> Algorithm: + """Build an Algorithm which wraps a single function.""" + + @wraps(func) + def wrapped_function(**kwargs: Any) -> dict: + result = func(**kwargs) + + if not isinstance(result, tuple): + result = (result,) + + result_dict = {} + for i, key in enumerate(return_keys): + if skip_unit_conversion: + result_dict[key] = result[i] + else: + result_dict[key] = convert_to_default_units(result[i], key) + + return result_dict + + return cls(wrapped_function, return_keys, name=name) + + def validate_inputs( + self, configuration: Union[dict, xr.Dataset], quiet: bool = False, raise_error_on_missing_inputs: bool = False + ) -> bool: + """Check that all required inputs are defined, and warn if inputs are unused.""" + return _validate_inputs(self, configuration, quiet=quiet, raise_error_on_missing_inputs=raise_error_on_missing_inputs) + + +class CompositeAlgorithm: + """A class which combined multiple Algorithms into a single object which behaves like an Algorithm.""" + + def __init__(self, algorithms: Sequence[Union[Algorithm, CompositeAlgorithm]], name: Optional[str] = None): + """Initialise a CompositeAlgorithm, combining several other Algorithms. + + Args: + algorithms: a list of Algorithms, in the order that they should be executed. + name: a name used to refer to the composite algorithm. + """ + if not (isinstance(algorithms, Sequence) and all(isinstance(alg, (Algorithm, CompositeAlgorithm)) for alg in algorithms)): + raise TypeError("Should pass a list of algorithms or composites to CompositeAlgorithm.") + + self.algorithms: list[Algorithm] = [] + + # flattens composite algorithms into their respective list of plain Algorithms + for alg in algorithms: + if isinstance(alg, Algorithm): + self.algorithms.append(alg) + else: + self.algorithms.extend(alg.algorithms) + + self.input_keys: list[str] = [] + self.required_input_keys: list[str] = [] + self.return_keys: list[str] = [] + pars: list[inspect.Parameter] = [] + + # traverse list of algorithms in order. + # If an ouput from the set of previous algorithms provides an input to a following algorithm + # the input is not turned into an input to the CompositeAlgorithm + for alg in self.algorithms: + alg_sig = inspect.signature(alg.run) + for key in alg.default_keys: + if key not in self.return_keys: + self.input_keys.append(key) + pars.append(alg_sig.parameters[key]) + for key in alg.required_input_keys: + if key not in self.return_keys: + self.input_keys.append(key) + self.required_input_keys.append(key) + pars.append(alg_sig.parameters[key]) + + for key in alg.return_keys: + if key not in self.return_keys: + self.return_keys.append(key) + + # create a signature for the run() function + # This is a purely aesthetic change, that ensures the run() function + # has a helpful tooltip in editors and in the documentation + + # 1. make sure the list of pars doesn't have any duplicates, if there are duplicates + # we pick the first one. We don't assert that the types of two parameters are compatible + # that's not easy to do. + seen_pars: dict[str, int] = {} + pars = [p for i, p in enumerate(pars) if seen_pars.setdefault(p.name, i) == i] + + # ensure POSITIONAL_OR_KEYWORD are before kw only + pars = sorted(pars, key=lambda p: p.kind) + + def_pars = [p for p in pars if p.default != inspect.Parameter.empty] + non_def_pars = [p for p in pars if p.default == inspect.Parameter.empty] + + # methods are immutable and we don't want to set a signature on the class' run() method + # thus we wrap the original run method and then assign the __signature__ to the wrapped + # wrapper function + def _wrap(f: Callable[..., xr.Dataset]) -> Callable[..., xr.Dataset]: + def wrapper(**kwargs: Any) -> xr.Dataset: + return f(**kwargs) + + wrapper.__doc__ = f.__doc__ + + return wrapper + + self.run = _wrap(self._run) + # ignore due to mypy bug/missing feature https://github.com/python/mypy/issues/3482 + self.run.__signature__ = inspect.Signature( # type:ignore[attr-defined] + non_def_pars + def_pars, return_annotation=xr.Dataset + ) + self._name = name + self.__doc__ = self._make_docstring() + + def _make_docstring(self) -> str: + """Makes a doc-string detailing the function inputs and outputs.""" + components = f"[{', '.join(alg._name for alg in self.algorithms)}]" + + return_string = ( + f"CompositeAlgorithm: {self._name}\n" + if self._name is not None + else "CompositeAlgorithm\n" + f"Composed of {components}\n" + f"Inputs:\n{', '.join(self.input_keys)}\n" + f"Outputs:\n{', '.join(self.return_keys)}" + ) + return return_string + + def __repr__(self) -> str: + """Return a simple string description of the CompositeAlgorithm.""" + return f"CompositeAlgorithm: {self._name}" + + def _run(self, **kwargs: Any) -> xr.Dataset: + """Run the sub-Algorithms, one after the other and return a xarray.Dataset of the results. + + Will throw a warning if parameters are not used by any sub-Algorithm. + """ + result = kwargs + + parameters_extra = set(kwargs) - set(self.required_input_keys) + parameters_missing = set(self.required_input_keys) - set(kwargs) + if parameters_missing: + raise TypeError(f"CompositeAlgorithm.run() missing arguments: {', '.join(parameters_missing)}") + if parameters_extra: + warn(f"Not all input parameters were used. Unused parameters: [{', '.join(parameters_extra)}]", stacklevel=3) + + for alg in self.algorithms: + + alg_kwargs = {key: result[key] for key in result.keys() if key in alg.input_keys} + + alg_result = alg.run(**alg_kwargs) + result.update(alg_result) # type:ignore[arg-type] # dict.update() doesn't like KeysView[Hashable] + + return xr.Dataset(result) + + def update_dataset(self, dataset: xr.Dataset, in_place: bool = False) -> Optional[xr.Dataset]: + """Retrieve inputs from passed dataset and return a new dataset combining input and output quantities. + + Specifying in_place=True modifies the dataset in place (changing the input), whereas in_place=False will + return a copy of the dataset with the outputs appended. + + N.b. will not throw a warning if the dataset contains unused elements. + + Args: + dataset: input dataset + in_place: modify the dataset in place, otherwise return a modified dataset keeping the input unchanged. + + Returns: modified dataset + """ + if not in_place: + dataset = dataset.copy(deep=True) + + for alg in self.algorithms: + # We've already used copy on the dataset, so can now call update_dataset with + # in_place = True for each of the algorithms. + alg.update_dataset(dataset, in_place=True) + + if not in_place: + return dataset + else: + return None + + def __add__(self, other: Union[Algorithm, CompositeAlgorithm]) -> CompositeAlgorithm: + """Build a CompositeAlgorithm composed of this CompositeAlgorithm and another Algorithm or CompositeAlgorithm.""" + if isinstance(other, Algorithm): + return CompositeAlgorithm(algorithms=[*self.algorithms, other]) + else: + return CompositeAlgorithm(algorithms=[*self.algorithms, *other.algorithms]) + + def validate_inputs( # noqa: PLR0912 + self, + configuration: Union[dict, xr.Dataset], + quiet: bool = False, + raise_error_on_missing_inputs: bool = True, + warn_for_overridden_variables: bool = False, + ) -> bool: + """Check that all required inputs are defined, and warn if inputs are unused.""" + # Check if variables are being silently internally overwritten + config_keys = list(configuration.keys()) + key_setter = {key: ["INPUT"] for key in config_keys} + + for algorithm in self.algorithms: + for key in algorithm.return_keys: + if key not in key_setter.keys(): + key_setter[key] = [algorithm._name] + else: + key_setter[key].append(algorithm._name) + + overridden_variables = [] + for variable, algs in key_setter.items(): + if len(algs) > 1: + overridden_variables.append(f"{variable}: ({', '.join(algs)})") + + if warn_for_overridden_variables and len(overridden_variables) > 0: + warn( + f"The following variables were overridden internally (given as variable: (list of algorithms setting variable)): {', '.join(overridden_variables)}", + stacklevel=3, + ) + + # Check that algorithms are ordered such that dependent algorithms follow those setting their required input keys + available_parameters = config_keys.copy() + out_of_order_parameters = {} + for algorithm in self.algorithms: + for key in algorithm.required_input_keys: + if key not in available_parameters: + out_of_order_parameters[key] = algorithm + for key in algorithm.return_keys: + available_parameters.append(key) + + if len(out_of_order_parameters) > 0: + message = "" + for key, algorithm in out_of_order_parameters.items(): + if key in key_setter and len(key_setter.get(key, [])) > 0: + message += f"{key} needed by {algorithm} defined by output of {key_setter[key]}." + if len(message) > 0: + message = f"Algorithms out of order. {message}. Rearrange the list of algorithms so that dependent algorithm are after algorithms setting their inputs." + if raise_error_on_missing_inputs: + raise RuntimeError(message) + if not quiet: + warn(message, stacklevel=3) + + _validate_inputs(self, configuration, quiet=quiet, raise_error_on_missing_inputs=raise_error_on_missing_inputs) + + return False + else: + return _validate_inputs(self, configuration, quiet=quiet, raise_error_on_missing_inputs=raise_error_on_missing_inputs) + + +def _validate_inputs( + algorithm: Union[Algorithm, CompositeAlgorithm], + configuration: Union[dict, xr.Dataset], + quiet: bool = False, + raise_error_on_missing_inputs: bool = False, +) -> bool: + """Check that all required inputs are defined, and warn if inputs are unused.""" + config_keys = list(configuration.keys()) + + unused_config_keys = config_keys.copy() + missing_input_keys = set(algorithm.required_input_keys) + + for key in config_keys: + if key in missing_input_keys: + missing_input_keys.remove(key) + + if key in algorithm.input_keys: + # required_input_keys gives the list of keys which must + # be provided, while input_puts gives the list of keys + # which can be provided (but which might have default values). + unused_config_keys.remove(key) + + if len(missing_input_keys) == 0 and len(unused_config_keys) == 0: + return True + + elif len(missing_input_keys) > 0 and len(unused_config_keys) > 0: + message = f"Missing input parameters [{', '.join(missing_input_keys)}]. Also had unused input parameters [{', '.join(unused_config_keys)}]." + if raise_error_on_missing_inputs: + raise RuntimeError(message) + + elif len(missing_input_keys) > 0: + message = f"Missing input parameters [{', '.join(missing_input_keys)}]." + if raise_error_on_missing_inputs: + raise RuntimeError(message) + + else: + message = f"Unused input parameters [{', '.join(unused_config_keys)}]." + + if not quiet: + warn(message, stacklevel=3) + return False diff --git a/cfspopcon/algorithms/beta.py b/cfspopcon/algorithms/beta.py new file mode 100644 index 00000000..cfbd730a --- /dev/null +++ b/cfspopcon/algorithms/beta.py @@ -0,0 +1,50 @@ +"""Calculate toroidal, poloidal, total and normalized beta.""" +from .. import formulas +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "beta_toroidal", + "beta_poloidal", + "beta", + "normalized_beta", +] + + +def run_calc_beta( + average_electron_density: Unitfull, + average_electron_temp: Unitfull, + average_ion_temp: Unitfull, + magnetic_field_on_axis: Unitfull, + plasma_current: Unitfull, + minor_radius: Unitfull, +) -> dict[str, Unitfull]: + """Calculate toroidal, poloidal, total and normalized beta. + + Args: + average_electron_density: :term:`glossary link` + average_electron_temp: :term:`glossary link` + average_ion_temp: :term:`glossary link` + magnetic_field_on_axis: :term:`glossary link` + plasma_current: :term:`glossary link` + minor_radius: :term:`glossary link` + + Returns: + :term:`beta_toroidal`, :term:`beta_poloidal`, :term:`beta_total`, :term:`beta_N` + """ + beta_toroidal = formulas.calc_beta_toroidal(average_electron_density, average_electron_temp, average_ion_temp, magnetic_field_on_axis) + beta_poloidal = formulas.calc_beta_poloidal( + average_electron_density, average_electron_temp, average_ion_temp, plasma_current, minor_radius + ) + + beta = formulas.calc_beta_total(beta_toroidal=beta_toroidal, beta_poloidal=beta_poloidal) + normalized_beta = formulas.calc_beta_normalised(beta, minor_radius, magnetic_field_on_axis, plasma_current) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_beta = Algorithm( + function=run_calc_beta, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/composite_algorithm.py b/cfspopcon/algorithms/composite_algorithm.py new file mode 100644 index 00000000..25224087 --- /dev/null +++ b/cfspopcon/algorithms/composite_algorithm.py @@ -0,0 +1,67 @@ +"""Algorithms constructed by combining several smaller algorithms.""" +from .algorithm_class import CompositeAlgorithm +from .beta import calc_beta +from .core_radiated_power import calc_core_radiated_power +from .extrinsic_core_radiator import calc_extrinsic_core_radiator +from .fusion_gain import calc_fusion_gain +from .geometry import calc_geometry +from .heat_exhaust import calc_heat_exhaust +from .ohmic_power import calc_ohmic_power +from .peaked_profiles import calc_peaked_profiles +from .power_balance_from_tau_e import calc_power_balance_from_tau_e +from .q_star_from_plasma_current import calc_q_star_from_plasma_current +from .single_functions import ( + calc_auxillary_power, + calc_average_ion_temp, + calc_average_total_pressure, + calc_bootstrap_fraction, + calc_confinement_transition_threshold_power, + calc_current_relaxation_time, + calc_f_rad_core, + calc_fuel_average_mass_number, + calc_greenwald_fraction, + calc_normalised_collisionality, + calc_P_SOL, + calc_peak_pressure, + calc_ratio_P_LH, + calc_rho_star, + calc_triple_product, + require_P_rad_less_than_P_in, +) +from .two_point_model_fixed_tet import two_point_model_fixed_tet +from .zeff_and_dilution_from_impurities import calc_zeff_and_dilution_from_impurities + +predictive_popcon = CompositeAlgorithm( + [ + calc_geometry, + calc_q_star_from_plasma_current, + calc_fuel_average_mass_number, + calc_average_ion_temp, + calc_zeff_and_dilution_from_impurities, + calc_power_balance_from_tau_e, + calc_beta, + calc_peaked_profiles, + calc_core_radiated_power, + require_P_rad_less_than_P_in, + calc_extrinsic_core_radiator, + calc_peaked_profiles, + calc_fusion_gain, + calc_bootstrap_fraction, + calc_ohmic_power, + calc_auxillary_power, + calc_P_SOL, + calc_average_total_pressure, + calc_heat_exhaust, + two_point_model_fixed_tet, + calc_greenwald_fraction, + calc_confinement_transition_threshold_power, + calc_ratio_P_LH, + calc_f_rad_core, + calc_normalised_collisionality, + calc_rho_star, + calc_triple_product, + calc_peak_pressure, + calc_current_relaxation_time, + ], + name="predictive_popcon", +) diff --git a/cfspopcon/algorithms/core_radiated_power.py b/cfspopcon/algorithms/core_radiated_power.py new file mode 100644 index 00000000..fe71921b --- /dev/null +++ b/cfspopcon/algorithms/core_radiated_power.py @@ -0,0 +1,90 @@ +"""Calculate the power radiated from the confined region due to the fuel and impurity species.""" +import xarray as xr + +from .. import formulas, named_options +from ..atomic_data import read_atomic_data +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = ["P_radiation"] + + +def run_calc_core_radiated_power( + rho: Unitfull, + electron_density_profile: Unitfull, + electron_temp_profile: Unitfull, + z_effective: Unitfull, + plasma_volume: Unitfull, + major_radius: Unitfull, + minor_radius: Unitfull, + magnetic_field_on_axis: Unitfull, + separatrix_elongation: Unitfull, + radiated_power_method: named_options.RadiationMethod, + radiated_power_scalar: Unitfull, + impurities: xr.DataArray, +) -> dict[str, Unitfull]: + """Calculate the power radiated from the confined region due to the fuel and impurity species. + + Args: + rho: :term:`glossary link` + electron_density_profile: :term:`glossary link` + electron_temp_profile: :term:`glossary link` + z_effective: :term:`glossary link` + plasma_volume: :term:`glossary link` + major_radius: :term:`glossary link` + minor_radius: :term:`glossary link` + magnetic_field_on_axis: :term:`glossary link` + separatrix_elongation: :term:`glossary link` + radiated_power_method: :term:`glossary link` + radiated_power_scalar: :term:`glossary link` + impurities: :term:`glossary link` + + Returns: + :term:`P_radiation` + + """ + P_rad_bremsstrahlung = formulas.calc_bremsstrahlung_radiation( + rho, electron_density_profile, electron_temp_profile, z_effective, plasma_volume + ) + P_rad_bremsstrahlung_from_hydrogen = formulas.calc_bremsstrahlung_radiation( + rho, electron_density_profile, electron_temp_profile, 1.0, plasma_volume + ) + P_rad_synchrotron = formulas.calc_synchrotron_radiation( + rho, + electron_density_profile, + electron_temp_profile, + major_radius, + minor_radius, + magnetic_field_on_axis, + separatrix_elongation, + plasma_volume, + ) + + # Calculate radiated power due to Bremsstrahlung, Synchrotron and impurities + if radiated_power_method == named_options.RadiationMethod.Inherent: + P_radiation = radiated_power_scalar * (P_rad_bremsstrahlung + P_rad_synchrotron) + else: + atomic_data = read_atomic_data() + + P_rad_impurity = formulas.calc_impurity_radiated_power( + radiated_power_method=radiated_power_method, + rho=rho, + electron_temp_profile=electron_temp_profile, + electron_density_profile=electron_density_profile, + impurities=impurities, + plasma_volume=plasma_volume, + atomic_data=atomic_data, + ) + + P_radiation = radiated_power_scalar * ( + P_rad_bremsstrahlung_from_hydrogen + P_rad_synchrotron + P_rad_impurity.sum(dim="dim_species") + ) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_core_radiated_power = Algorithm( + function=run_calc_core_radiated_power, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/extrinsic_core_radiator.py b/cfspopcon/algorithms/extrinsic_core_radiator.py new file mode 100644 index 00000000..7931d97e --- /dev/null +++ b/cfspopcon/algorithms/extrinsic_core_radiator.py @@ -0,0 +1,99 @@ +"""Calculate the concentration and effect of a core radiator required to achieve above a defined core radiative fraction.""" +import numpy as np +import xarray as xr + +from .. import formulas, named_options +from ..atomic_data import read_atomic_data +from ..helpers import make_impurities_array +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "core_radiator_concentration", + "P_radiated_by_core_radiator", + "P_radiation", + "core_radiator_concentration", + "core_radiator_charge_state", + "zeff_change_from_core_rad", + "dilution_change_from_core_rad", + "z_effective", + "dilution", +] + + +def run_calc_extrinsic_core_radiator( + minimum_core_radiated_fraction: Unitfull, + P_in: Unitfull, + P_radiation: Unitfull, + average_electron_density: Unitfull, + average_electron_temp: Unitfull, + z_effective: Unitfull, + dilution: Unitfull, + rho: Unitfull, + electron_density_profile: Unitfull, + electron_temp_profile: Unitfull, + plasma_volume: Unitfull, + radiated_power_method: named_options.RadiationMethod, + radiated_power_scalar: Unitfull, + core_radiator: named_options.Impurity, +) -> dict[str, Unitfull]: + """Calculate the concentration and effect of a core radiator required to achieve above a defined core radiative fraction. + + Args: + minimum_core_radiated_fraction: :term:`glossary link` + P_in: :term:`glossary link` + P_radiation: :term:`glossary link` + average_electron_density: :term:`glossary link` + average_electron_temp: :term:`glossary link` + z_effective: :term:`glossary link` + dilution: :term:`dilution` + rho: :term:`glossary link` + electron_density_profile: :term:`glossary link` + electron_temp_profile: :term:`glossary link` + plasma_volume: :term:`glossary link` + radiated_power_method: :term:`glossary link` + radiated_power_scalar: :term:`radiated_power_scalar` + core_radiator: :term:`glossary link` + + Returns: + :term:`core_radiator_concentration`, :term:`P_radiated_by_core_radiator`, :term:`P_radiation`, :term:`core_radiator_concentration`, :term:`core_radiator_charge_state`, :term:`zeff_change_from_core_rad` :term:`dilution_change_from_core_rad`, :term:`z_effective`, :term:`dilution` + + """ + atomic_data = read_atomic_data() + + # Force P_radiated_by_core_radiator to be >= 0.0 (core radiator cannot reduce radiated power) + P_radiated_by_core_radiator = np.maximum(minimum_core_radiated_fraction * P_in - P_radiation, 0.0) + P_radiation = np.maximum(minimum_core_radiated_fraction * P_in, P_radiation) + + P_rad_per_core_radiator = radiated_power_scalar * formulas.calc_impurity_radiated_power( + radiated_power_method=named_options.RadiationMethod.Radas + if radiated_power_method == named_options.RadiationMethod.Inherent + else radiated_power_method, + rho=rho, + electron_temp_profile=electron_temp_profile, + electron_density_profile=electron_density_profile, + impurities=make_impurities_array(core_radiator, 1.0), + plasma_volume=plasma_volume, + atomic_data=atomic_data, + ).sum(dim="dim_species") + core_radiator_concentration = xr.where( # type:ignore[no-untyped-call] + P_radiated_by_core_radiator > 0, P_radiated_by_core_radiator / P_rad_per_core_radiator, 0.0 + ) + + core_radiator_charge_state = formulas.calc_impurity_charge_state( + average_electron_density, average_electron_temp, core_radiator, atomic_data + ) + zeff_change_from_core_rad = formulas.calc_change_in_zeff(core_radiator_charge_state, core_radiator_concentration) + dilution_change_from_core_rad = formulas.calc_change_in_dilution(core_radiator_charge_state, core_radiator_concentration) + + z_effective = z_effective + zeff_change_from_core_rad + dilution = (dilution - dilution_change_from_core_rad).clip(min=0.0) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_extrinsic_core_radiator = Algorithm( + function=run_calc_extrinsic_core_radiator, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/fusion_gain.py b/cfspopcon/algorithms/fusion_gain.py new file mode 100644 index 00000000..e99a2f7a --- /dev/null +++ b/cfspopcon/algorithms/fusion_gain.py @@ -0,0 +1,64 @@ +"""Calculate the fusion power and thermal gain (Q).""" +from .. import formulas, named_options +from ..unit_handling import Unitfull, convert_to_default_units, ureg +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "P_fusion", + "P_neutron", + "P_alpha", + "P_external", + "P_launched", + "Q", + "neutron_power_flux_to_walls", + "neutron_rate", +] + + +def run_calc_fusion_gain( + fusion_reaction: named_options.ReactionType, + ion_temp_profile: Unitfull, + heavier_fuel_species_fraction: Unitfull, + fuel_ion_density_profile: Unitfull, + rho: Unitfull, + plasma_volume: Unitfull, + surface_area: Unitfull, + P_in: Unitfull, + fraction_of_external_power_coupled: Unitfull, +) -> dict[str, Unitfull]: + """Calculate the fusion power and thermal gain (Q). + + Args: + fusion_reaction: :term:`glossary link` + ion_temp_profile: :term:`glossary link` + heavier_fuel_species_fraction: :term:`glossary link` + fuel_ion_density_profile: :term:`glossary link` + rho: :term:`glossary link` + plasma_volume: :term:`glossary link` + surface_area: :term:`glossary link` + P_in: :term:`glossary link` + fraction_of_external_power_coupled: :term:`glossary link` + + Returns: + :term:`P_fusion`, :term:`P_neutron`, :term:`P_alpha`, :term:`P_external`, :term:`P_launched`, :term:`Q`, :term:`neutron_power_flux_to_walls` :term:`neutron_rate` + """ + P_fusion, P_neutron, P_alpha = formulas.calc_fusion_power( + fusion_reaction, ion_temp_profile, heavier_fuel_species_fraction, fuel_ion_density_profile, rho, plasma_volume + ) + + P_external = (P_in - P_alpha).clip(min=0.0 * ureg.MW) + P_launched = P_external / fraction_of_external_power_coupled + Q = formulas.thermal_calc_gain_factor(P_fusion, P_launched) + + neutron_power_flux_to_walls, neutron_rate = formulas.calc_neutron_flux_to_walls( + P_neutron, surface_area, fusion_reaction, ion_temp_profile, heavier_fuel_species_fraction + ) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_fusion_gain = Algorithm( + function=run_calc_fusion_gain, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/geometry.py b/cfspopcon/algorithms/geometry.py new file mode 100644 index 00000000..b472be98 --- /dev/null +++ b/cfspopcon/algorithms/geometry.py @@ -0,0 +1,54 @@ +"""Calculate dependent geometry parameters.""" +from .. import formulas +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "separatrix_elongation", + "separatrix_triangularity", + "minor_radius", + "vertical_minor_radius", + "plasma_volume", + "surface_area", +] + + +def run_calc_geometry( + major_radius: Unitfull, + inverse_aspect_ratio: Unitfull, + areal_elongation: Unitfull, + triangularity_psi95: Unitfull, + elongation_ratio_sep_to_areal: Unitfull, + triangularity_ratio_sep_to_psi95: Unitfull, +) -> dict[str, Unitfull]: + """Calculate dependent geometry parameters. + + Args: + major_radius: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + areal_elongation: :term:`glossary link` + triangularity_psi95: :term:`glossary link` + elongation_ratio_sep_to_areal: :term:`glossary link` + triangularity_ratio_sep_to_psi95: :term:`glossary link` + + Returns: + :term:`separatrix_elongation`, :term:`separatrix_triangularity`, :term:`minor_radius`, :term:`vertical_minor_radius`, :term:`plasma_volume`, :term:`surface_area` + """ + separatrix_elongation = areal_elongation * elongation_ratio_sep_to_areal + + separatrix_triangularity = triangularity_psi95 * triangularity_ratio_sep_to_psi95 + + minor_radius = major_radius * inverse_aspect_ratio + vertical_minor_radius = minor_radius * separatrix_elongation + + plasma_volume = formulas.calc_plasma_volume(major_radius, inverse_aspect_ratio, areal_elongation) + surface_area = formulas.calc_plasma_surface_area(major_radius, inverse_aspect_ratio, areal_elongation) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_geometry = Algorithm( + function=run_calc_geometry, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/heat_exhaust.py b/cfspopcon/algorithms/heat_exhaust.py new file mode 100644 index 00000000..ca3d69a0 --- /dev/null +++ b/cfspopcon/algorithms/heat_exhaust.py @@ -0,0 +1,78 @@ +"""Calculate the parallel heat flux density upstream and related metrics.""" +import numpy as np + +from .. import formulas, named_options +from ..unit_handling import Unitfull, convert_to_default_units, ureg +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "PB_over_R", + "PBpRnSq", + "B_pol_out_mid", + "B_t_out_mid", + "fieldline_pitch_at_omp", + "lambda_q", + "q_parallel", + "q_perp", +] + + +def run_calc_heat_exhaust( + P_sol: Unitfull, + magnetic_field_on_axis: Unitfull, + major_radius: Unitfull, + inverse_aspect_ratio: Unitfull, + plasma_current: Unitfull, + minor_radius: Unitfull, + q_star: Unitfull, + average_electron_density: Unitfull, + average_total_pressure: Unitfull, + fraction_of_P_SOL_to_divertor: Unitfull, + lambda_q_scaling: named_options.LambdaQScaling, + lambda_q_factor: Unitfull = 1.0 * ureg.dimensionless, +) -> dict[str, Unitfull]: + """Calculate the parallel heat flux density upstream and related metrics. + + Args: + P_sol: :term:`glossary link` + magnetic_field_on_axis: :term:`glossary link` + major_radius: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + plasma_current: :term:`glossary link` + minor_radius: :term:`glossary link` + q_star: :term:`glossary link` + average_electron_density: :term:`glossary link` + average_total_pressure: :term:`glossary link ` + fraction_of_P_SOL_to_divertor: :term:`glossary link ` + lambda_q_scaling: :term:`glossary link` + lambda_q_factor: :term:`glossary link` + + Returns: + :term:`PB_over_R`, :term:`PBpRnSq`, :term:`B_pol_out_mid`, :term:`B_t_out_mid`, :term:`fieldline_pitch_at_omp`, :term:`lambda_q`, :term:`q_parallel`, :term:`q_perp` + + """ + PB_over_R = P_sol * magnetic_field_on_axis / major_radius + PBpRnSq = (P_sol * (magnetic_field_on_axis / q_star) / major_radius) / (average_electron_density**2.0) + + B_pol_out_mid = formulas.calc_B_pol_omp(plasma_current=plasma_current, minor_radius=minor_radius) + B_t_out_mid = formulas.calc_B_tor_omp(magnetic_field_on_axis, major_radius, minor_radius) + + fieldline_pitch_at_omp = np.sqrt(B_t_out_mid**2 + B_pol_out_mid**2) / B_pol_out_mid + + lambda_q = lambda_q_factor * formulas.scrape_off_layer_model.calc_lambda_q( + lambda_q_scaling, average_total_pressure, P_sol, major_radius, B_pol_out_mid, inverse_aspect_ratio + ) + + q_parallel = formulas.scrape_off_layer_model.calc_parallel_heat_flux_density( + P_sol, fraction_of_P_SOL_to_divertor, major_radius + minor_radius, lambda_q, fieldline_pitch_at_omp + ) + q_perp = P_sol / (2.0 * np.pi * (major_radius + minor_radius) * lambda_q) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_heat_exhaust = Algorithm( + function=run_calc_heat_exhaust, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/ohmic_power.py b/cfspopcon/algorithms/ohmic_power.py new file mode 100644 index 00000000..b030e406 --- /dev/null +++ b/cfspopcon/algorithms/ohmic_power.py @@ -0,0 +1,56 @@ +"""Calculate the power due to Ohmic resistive heating.""" +from .. import formulas +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "spitzer_resistivity", + "trapped_particle_fraction", + "neoclassical_loop_resistivity", + "loop_voltage", + "P_ohmic", +] + + +def run_calc_ohmic_power( + bootstrap_fraction: Unitfull, + average_electron_temp: Unitfull, + inverse_aspect_ratio: Unitfull, + z_effective: Unitfull, + major_radius: Unitfull, + minor_radius: Unitfull, + areal_elongation: Unitfull, + plasma_current: Unitfull, +) -> dict[str, Unitfull]: + """Calculate the power due to Ohmic resistive heating. + + Args: + bootstrap_fraction: :term:`glossary link` + average_electron_temp: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + z_effective: :term:`glossary link` + major_radius: :term:`glossary link` + minor_radius: :term:`glossary link` + areal_elongation: :term:`glossary link` + plasma_current: :term:`glossary link` + + Returns: + :term:`spitzer_resistivity`, :term:`trapped_particle_fraction`, :term:`neoclassical_loop_resistivity`, :term:`loop_voltage`, :term:`P_ohmic` + """ + inductive_plasma_current = plasma_current * (1.0 - bootstrap_fraction) + spitzer_resistivity = formulas.calc_Spitzer_loop_resistivity(average_electron_temp) + trapped_particle_fraction = formulas.calc_resistivity_trapped_enhancement(inverse_aspect_ratio) + neoclassical_loop_resistivity = formulas.calc_neoclassical_loop_resistivity(spitzer_resistivity, z_effective, trapped_particle_fraction) + loop_voltage = formulas.calc_loop_voltage( + major_radius, minor_radius, inductive_plasma_current, areal_elongation, neoclassical_loop_resistivity + ) + P_ohmic = formulas.calc_ohmic_power(inductive_plasma_current, loop_voltage) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_ohmic_power = Algorithm( + function=run_calc_ohmic_power, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/peaked_profiles.py b/cfspopcon/algorithms/peaked_profiles.py new file mode 100644 index 00000000..ee85876f --- /dev/null +++ b/cfspopcon/algorithms/peaked_profiles.py @@ -0,0 +1,91 @@ +"""Calculate density peaking and the corresponding density and temperature profiles.""" +from .. import formulas +from ..named_options import ProfileForm +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "effective_collisionality", + "ion_density_peaking", + "electron_density_peaking", + "peak_electron_density", + "peak_fuel_ion_density", + "peak_electron_temp", + "peak_ion_temp", + "rho", + "electron_density_profile", + "fuel_ion_density_profile", + "electron_temp_profile", + "ion_temp_profile", +] + + +def run_calc_peaked_profiles( + profile_form: ProfileForm, + average_electron_density: Unitfull, + average_electron_temp: Unitfull, + average_ion_temp: Unitfull, + ion_density_peaking_offset: Unitfull, + electron_density_peaking_offset: Unitfull, + temperature_peaking: Unitfull, + major_radius: Unitfull, + z_effective: Unitfull, + dilution: Unitfull, + beta_toroidal: Unitfull, + normalized_inverse_temp_scale_length: Unitfull, +) -> dict[str, Unitfull]: + """Calculate density peaking and the corresponding density and temperature profiles. + + Args: + profile_form: :term:`glossary link` + average_electron_density: :term:`glossary link` + average_electron_temp: :term:`glossary link` + average_ion_temp: :term:`glossary link` + ion_density_peaking_offset: :term:`glossary link` + electron_density_peaking_offset: :term:`glossary link` + temperature_peaking: :term:`glossary link` + major_radius: :term:`glossary link` + z_effective: :term:`glossary link` + dilution: :term:`glossary link` + beta_toroidal: :term:`glossary link` + normalized_inverse_temp_scale_length: :term:`glossary link` + + Returns: + `effective_collisionality`, :term:`ion_density_peaking`, :term:`electron_density_peaking`, :term:`peak_electron_density`, :term:`peak_electron_temp`, :term:`peak_ion_temp`, :term:`rho`, :term:`electron_density_profile`, :term:`fuel_ion_density_profile`, :term:`electron_temp_profile`, :term:`ion_temp_profile` + + """ + effective_collisionality = formulas.calc_effective_collisionality( + average_electron_density, average_electron_temp, major_radius, z_effective + ) + ion_density_peaking = formulas.calc_density_peaking(effective_collisionality, beta_toroidal, nu_noffset=ion_density_peaking_offset) + electron_density_peaking = formulas.calc_density_peaking( + effective_collisionality, beta_toroidal, nu_noffset=electron_density_peaking_offset + ) + + peak_electron_density = average_electron_density * electron_density_peaking + peak_fuel_ion_density = average_electron_density * dilution * ion_density_peaking + peak_electron_temp = average_electron_temp * temperature_peaking + peak_ion_temp = average_ion_temp * temperature_peaking + + # Calculate the total fusion power by estimating density and temperature profiles and + # using this to calculate fusion power profiles. + (rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile,) = formulas.calc_1D_plasma_profiles( + profile_form, + average_electron_density, + average_electron_temp, + average_ion_temp, + electron_density_peaking, + ion_density_peaking, + temperature_peaking, + dilution, + normalized_inverse_temp_scale_length, + ) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_peaked_profiles = Algorithm( + function=run_calc_peaked_profiles, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/plasma_current_from_q_star.py b/cfspopcon/algorithms/plasma_current_from_q_star.py new file mode 100644 index 00000000..542e40a0 --- /dev/null +++ b/cfspopcon/algorithms/plasma_current_from_q_star.py @@ -0,0 +1,44 @@ +"""Calculate plasma current from edge safety factor.""" +from .. import formulas +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "f_shaping", + "plasma_current", +] + + +def run_calc_plasma_current_from_q_star( + magnetic_field_on_axis: Unitfull, + major_radius: Unitfull, + q_star: Unitfull, + inverse_aspect_ratio: Unitfull, + areal_elongation: Unitfull, + triangularity_psi95: Unitfull, +) -> dict[str, Unitfull]: + """Calculate plasma current from edge safety factor. + + Args: + magnetic_field_on_axis: :term:`glossary link` + major_radius: :term:`glossary link` + q_star: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + areal_elongation: :term:`glossary link` + triangularity_psi95: :term:`glossary link` + + Returns: + term:`f_shaping`, term:`plasma_current`, + + """ + f_shaping = formulas.calc_f_shaping(inverse_aspect_ratio, areal_elongation, triangularity_psi95) + plasma_current = formulas.calc_plasma_current(magnetic_field_on_axis, major_radius, inverse_aspect_ratio, q_star, f_shaping) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_plasma_current_from_q_star = Algorithm( + function=run_calc_plasma_current_from_q_star, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/power_balance_from_tau_e.py b/cfspopcon/algorithms/power_balance_from_tau_e.py new file mode 100644 index 00000000..f52f6c38 --- /dev/null +++ b/cfspopcon/algorithms/power_balance_from_tau_e.py @@ -0,0 +1,74 @@ +"""Calculate the input power required to maintain the stored energy, given a tau_e scaling.""" +from .. import formulas, named_options +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "energy_confinement_time", + "P_in", +] + + +def run_calc_power_balance_from_tau_e( + plasma_stored_energy: Unitfull, + average_electron_density: Unitfull, + confinement_time_scalar: Unitfull, + plasma_current: Unitfull, + magnetic_field_on_axis: Unitfull, + major_radius: Unitfull, + areal_elongation: Unitfull, + separatrix_elongation: Unitfull, + inverse_aspect_ratio: Unitfull, + fuel_average_mass_number: Unitfull, + triangularity_psi95: Unitfull, + separatrix_triangularity: Unitfull, + q_star: Unitfull, + energy_confinement_scaling: named_options.ConfinementScaling, +) -> dict[str, Unitfull]: + """Calculate the input power required to maintain the stored energy, given a tau_e scaling. + + Args: + plasma_stored_energy: :term:`glossary link` + average_electron_density: :term:`glossary link` + confinement_time_scalar: :term:`glossary link` + plasma_current: :term:`glossary link` + magnetic_field_on_axis: :term:`glossary link` + major_radius: :term:`glossary link` + areal_elongation: :term:`glossary link` + separatrix_elongation: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + fuel_average_mass_number: :term:`glossary link` + triangularity_psi95: :term:`glossary link` + separatrix_triangularity: :term:`glossary link` + q_star: :term:`glossary link` + energy_confinement_scaling: :term:`glossary link` + + Returns: + :term:`energy_confinement_time`, :term:`P_in` + + """ + energy_confinement_time, P_in = formulas.calc_tau_e_and_P_in_from_scaling( + confinement_time_scalar=confinement_time_scalar, + plasma_current=plasma_current, + magnetic_field_on_axis=magnetic_field_on_axis, + average_electron_density=average_electron_density, + major_radius=major_radius, + areal_elongation=areal_elongation, + separatrix_elongation=separatrix_elongation, + inverse_aspect_ratio=inverse_aspect_ratio, + fuel_average_mass_number=fuel_average_mass_number, + triangularity_psi95=triangularity_psi95, + separatrix_triangularity=separatrix_triangularity, + plasma_stored_energy=plasma_stored_energy, + q_star=q_star, + tau_e_scaling=energy_confinement_scaling, + ) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_power_balance_from_tau_e = Algorithm( + function=run_calc_power_balance_from_tau_e, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/q_star_from_plasma_current.py b/cfspopcon/algorithms/q_star_from_plasma_current.py new file mode 100644 index 00000000..164b1eb4 --- /dev/null +++ b/cfspopcon/algorithms/q_star_from_plasma_current.py @@ -0,0 +1,43 @@ +"""Calculate plasma current from edge safety factor.""" +from .. import formulas +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "f_shaping", + "q_star", +] + + +def run_calc_q_star_from_plasma_current( + magnetic_field_on_axis: Unitfull, + major_radius: Unitfull, + plasma_current: Unitfull, + inverse_aspect_ratio: Unitfull, + areal_elongation: Unitfull, + triangularity_psi95: Unitfull, +) -> dict[str, Unitfull]: + """Calculate plasma current from edge safety factor. + + Args: + magnetic_field_on_axis: :term:`glossary link` + major_radius: :term:`glossary link` + plasma_current: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + areal_elongation: :term:`glossary link` + triangularity_psi95: :term:`glossary link` + + Returns: + :term:`f_shaping`, :term:`q_star`, + """ + f_shaping = formulas.calc_f_shaping(inverse_aspect_ratio, areal_elongation, triangularity_psi95) + q_star = formulas.calc_q_star(magnetic_field_on_axis, major_radius, inverse_aspect_ratio, plasma_current, f_shaping) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_q_star_from_plasma_current = Algorithm( + function=run_calc_q_star_from_plasma_current, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/single_functions.py b/cfspopcon/algorithms/single_functions.py new file mode 100644 index 00000000..364b6f19 --- /dev/null +++ b/cfspopcon/algorithms/single_functions.py @@ -0,0 +1,75 @@ +"""Algorithm wrappers for single functions which don't fit into larger algorithms.""" +import numpy as np + +from .. import formulas +from ..named_options import Algorithms +from ..unit_handling import ureg +from .algorithm_class import Algorithm + +calc_confinement_transition_threshold_power = Algorithm.from_single_function( + formulas.calc_confinement_transition_threshold_power, return_keys=["P_LH_thresh"], name="calc_confinement_transition_threshold_power" +) +calc_ratio_P_LH = Algorithm.from_single_function( + func=lambda P_sol, P_LH_thresh: P_sol / P_LH_thresh, return_keys=["ratio_of_P_SOL_to_P_LH"], name="calc_ratio_P_LH" +) +calc_f_rad_core = Algorithm.from_single_function( + func=lambda P_radiation, P_in: P_radiation / P_in, return_keys=["core_radiated_power_fraction"], name="calc_f_rad_core" +) +calc_normalised_collisionality = Algorithm.from_single_function( + func=formulas.calc_normalised_collisionality, return_keys=["nu_star"], name="calc_normalised_collisionality" +) +calc_rho_star = Algorithm.from_single_function(func=formulas.calc_rho_star, return_keys=["rho_star"], name="calc_rho_star") +calc_triple_product = Algorithm.from_single_function( + func=formulas.calc_triple_product, return_keys=["fusion_triple_product"], name="calc_triple_product" +) +calc_greenwald_fraction = Algorithm.from_single_function( + func=formulas.calc_greenwald_fraction, return_keys=["greenwald_fraction"], name="calc_greenwald_fraction" +) +calc_current_relaxation_time = Algorithm.from_single_function( + func=formulas.calc_current_relaxation_time, return_keys=["current_relaxation_time"], name="calc_current_relaxation_time" +) +calc_peak_pressure = Algorithm.from_single_function( + func=formulas.calc_peak_pressure, return_keys=["peak_pressure"], name="calc_peak_pressure" +) +calc_average_total_pressure = Algorithm.from_single_function( + lambda average_electron_density, average_electron_temp, average_ion_temp: average_electron_density + * (average_electron_temp + average_ion_temp), + return_keys=["average_total_pressure"], + name="calc_average_total_pressure", +) +calc_bootstrap_fraction = Algorithm.from_single_function( + formulas.calc_bootstrap_fraction, return_keys=["bootstrap_fraction"], name="calc_bootstrap_fraction" +) +calc_auxillary_power = Algorithm.from_single_function( + lambda P_external, P_ohmic: (P_external - P_ohmic).clip(min=0.0 * ureg.MW), return_keys=["P_auxillary"], name="calc_auxillary_power" +) +calc_average_ion_temp = Algorithm.from_single_function( + lambda average_electron_temp, ion_to_electron_temp_ratio: average_electron_temp * ion_to_electron_temp_ratio, + return_keys=["average_ion_temp"], + name="calc_average_ion_temp", +) +calc_fuel_average_mass_number = Algorithm.from_single_function( + formulas.calc_fuel_average_mass_number, return_keys=["fuel_average_mass_number"], name="calc_fuel_average_mass_number" +) +calc_magnetic_field_on_axis = Algorithm.from_single_function( + lambda product_of_magnetic_field_and_radius, major_radius: product_of_magnetic_field_and_radius / major_radius, + return_keys=["magnetic_field_on_axis"], + name="calc_magnetic_field_on_axis", +) +require_P_rad_less_than_P_in = Algorithm.from_single_function( + lambda P_in, P_radiation: np.minimum(P_radiation, P_in), return_keys=["P_radiation"], name="require_P_rad_less_than_P_in" +) +calc_P_SOL = Algorithm.from_single_function( + lambda P_in, P_radiation: np.maximum(P_in - P_radiation, 0.0), return_keys=["P_sol"], name="calc_P_SOL" +) +calc_plasma_stored_energy = Algorithm.from_single_function( + lambda average_electron_density, average_electron_temp, average_ion_density, summed_impurity_density, average_ion_temp, plasma_volume: ( + (3.0 / 2.0) + * ((average_electron_density * average_electron_temp) + ((average_ion_density + summed_impurity_density) * average_ion_temp)) + * plasma_volume + ).pint.to(ureg.MJ), + return_keys=["plasma_stored_energy"], + name="calc_plasma_stored_energy", +) + +SINGLE_FUNCTIONS = {Algorithms[key]: val for key, val in locals().items() if isinstance(val, Algorithm)} diff --git a/cfspopcon/algorithms/two_point_model_fixed_fpow.py b/cfspopcon/algorithms/two_point_model_fixed_fpow.py new file mode 100644 index 00000000..0bf663cd --- /dev/null +++ b/cfspopcon/algorithms/two_point_model_fixed_fpow.py @@ -0,0 +1,70 @@ +"""Run the two point model with a fixed power loss fraction in the SOL.""" +from typing import Union + +import xarray as xr + +from ..formulas.scrape_off_layer_model import solve_two_point_model +from ..named_options import MomentumLossFunction +from ..unit_handling import Quantity, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "upstream_electron_temp", + "target_electron_density", + "target_electron_temp", + "target_electron_flux", + "target_q_parallel", +] + + +def run_two_point_model_fixed_fpow( + SOL_power_loss_fraction: Union[float, xr.DataArray], + q_parallel: Union[Quantity, xr.DataArray], + parallel_connection_length: Union[Quantity, xr.DataArray], + average_electron_density: Union[Quantity, xr.DataArray], + nesep_over_nebar: Union[float, xr.DataArray], + toroidal_flux_expansion: Union[float, xr.DataArray], + fuel_average_mass_number: Union[Quantity, xr.DataArray], + kappa_e0: Union[Quantity, xr.DataArray], + SOL_momentum_loss_function: Union[MomentumLossFunction, xr.DataArray], + raise_error_if_not_converged: bool = False, +) -> dict[str, Union[float, Quantity, xr.DataArray]]: + """Run the two point model with a fixed power loss fraction in the SOL. + + Args: + SOL_power_loss_fraction: :term:`glossary link` + q_parallel: :term:`glossary link` + parallel_connection_length: :term:`glossary link` + average_electron_density: :term:`glossary link` + nesep_over_nebar: :term:`glossary link` + toroidal_flux_expansion: :term:`glossary link` + fuel_average_mass_number: :term:`glossary link` + kappa_e0: :term:`glossary link` + SOL_momentum_loss_function: :term:`glossary link` + raise_error_if_not_converged: Raise an error if solve does not converge + + Returns: + :term:`upstream_electron_temp`, :term:`target_electron_density`, :term:`target_electron_temp`, :term:`target_electron_flux`, :term:`target_q_parallel`, + """ + (upstream_electron_temp, target_electron_density, target_electron_temp, target_electron_flux,) = solve_two_point_model( + SOL_power_loss_fraction=SOL_power_loss_fraction, + parallel_heat_flux_density=q_parallel, + parallel_connection_length=parallel_connection_length, + upstream_electron_density=nesep_over_nebar * average_electron_density, + toroidal_flux_expansion=toroidal_flux_expansion, + fuel_average_mass_number=fuel_average_mass_number, + kappa_e0=kappa_e0, + SOL_momentum_loss_function=SOL_momentum_loss_function, + raise_error_if_not_converged=raise_error_if_not_converged, + ) + + target_q_parallel = q_parallel * (1.0 - SOL_power_loss_fraction) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +two_point_model_fixed_fpow = Algorithm( + function=run_two_point_model_fixed_fpow, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/two_point_model_fixed_qpart.py b/cfspopcon/algorithms/two_point_model_fixed_qpart.py new file mode 100644 index 00000000..0f86bf8a --- /dev/null +++ b/cfspopcon/algorithms/two_point_model_fixed_qpart.py @@ -0,0 +1,71 @@ +"""Run the two point model with a fixed parallel heat flux density reaching the target.""" +from typing import Union + +import xarray as xr + +from ..formulas.scrape_off_layer_model import solve_two_point_model +from ..named_options import MomentumLossFunction +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "upstream_electron_temp", + "target_electron_density", + "target_electron_temp", + "target_electron_flux", + "SOL_power_loss_fraction", +] + + +def run_two_point_model_fixed_qpart( + target_q_parallel: Unitfull, + q_parallel: Unitfull, + parallel_connection_length: Unitfull, + average_electron_density: Unitfull, + nesep_over_nebar: Unitfull, + toroidal_flux_expansion: Unitfull, + fuel_average_mass_number: Unitfull, + kappa_e0: Unitfull, + SOL_momentum_loss_function: Union[MomentumLossFunction, xr.DataArray], + raise_error_if_not_converged: bool = False, +) -> dict[str, Unitfull]: + """Run the two point model with a fixed parallel heat flux density reaching the target. + + Args: + target_q_parallel: :term:`glossary link` + q_parallel: :term:`glossary link` + parallel_connection_length: :term:`glossary link` + average_electron_density: :term:`glossary link` + nesep_over_nebar: :term:`glossary link` + toroidal_flux_expansion: :term:`glossary link` + fuel_average_mass_number: :term:`glossary link` + kappa_e0: :term:`glossary link` + SOL_momentum_loss_function: :term:`glossary link` + raise_error_if_not_converged: Raise an error if solve does not converge + + Returns: + :term:`upstream_electron_temp`, :term:`target_electron_density`, :term:`target_electron_temp`, :term:`target_electron_flux`, :term:`SOL_power_loss_fraction`, + + """ + SOL_power_loss_fraction = (1.0 - target_q_parallel / q_parallel).clip(min=0.0, max=1.0) + + (upstream_electron_temp, target_electron_density, target_electron_temp, target_electron_flux,) = solve_two_point_model( + SOL_power_loss_fraction=SOL_power_loss_fraction, + parallel_heat_flux_density=q_parallel, + parallel_connection_length=parallel_connection_length, + upstream_electron_density=nesep_over_nebar * average_electron_density, + toroidal_flux_expansion=toroidal_flux_expansion, + fuel_average_mass_number=fuel_average_mass_number, + kappa_e0=kappa_e0, + SOL_momentum_loss_function=SOL_momentum_loss_function, + raise_error_if_not_converged=raise_error_if_not_converged, + ) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +two_point_model_fixed_qpart = Algorithm( + function=run_two_point_model_fixed_qpart, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/two_point_model_fixed_tet.py b/cfspopcon/algorithms/two_point_model_fixed_tet.py new file mode 100644 index 00000000..587c2a80 --- /dev/null +++ b/cfspopcon/algorithms/two_point_model_fixed_tet.py @@ -0,0 +1,67 @@ +"""Run the two point model with a fixed sheath entrance temperature.""" +from typing import Union + +import xarray as xr + +from ..formulas.scrape_off_layer_model import solve_target_first_two_point_model +from ..named_options import MomentumLossFunction +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "upstream_electron_temp", + "target_electron_density", + "SOL_power_loss_fraction", + "target_electron_flux", + "target_q_parallel", +] + + +def run_two_point_model_fixed_tet( + target_electron_temp: Unitfull, + q_parallel: Unitfull, + parallel_connection_length: Unitfull, + average_electron_density: Unitfull, + nesep_over_nebar: Unitfull, + toroidal_flux_expansion: Unitfull, + fuel_average_mass_number: Unitfull, + kappa_e0: Unitfull, + SOL_momentum_loss_function: Union[MomentumLossFunction, xr.DataArray], +) -> dict[str, Unitfull]: + """Run the two point model with a fixed sheath entrance temperature. + + Args: + target_electron_temp: :term:`glossary link` + q_parallel: :term:`glossary link` + parallel_connection_length: :term:`glossary link` + average_electron_density: :term:`glossary link` + nesep_over_nebar: :term:`glossary link` + toroidal_flux_expansion: :term:`glossary link` + fuel_average_mass_number: :term:`glossary link` + kappa_e0: :term:`glossary link` + SOL_momentum_loss_function: :term:`glossary link` + + Returns: + :term:`upstream_electron_temp`, :term:`target_electron_density`, :term:`SOL_power_loss_fraction`, :term:`target_electron_flux`, :term:`target_q_parallel`, + """ + (SOL_power_loss_fraction, upstream_electron_temp, target_electron_density, target_electron_flux,) = solve_target_first_two_point_model( + target_electron_temp=target_electron_temp, + parallel_heat_flux_density=q_parallel, + parallel_connection_length=parallel_connection_length, + upstream_electron_density=nesep_over_nebar * average_electron_density, + toroidal_flux_expansion=toroidal_flux_expansion, + fuel_average_mass_number=fuel_average_mass_number, + kappa_e0=kappa_e0, + SOL_momentum_loss_function=SOL_momentum_loss_function, + ) + + target_q_parallel = q_parallel * (1.0 - SOL_power_loss_fraction) + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +two_point_model_fixed_tet = Algorithm( + function=run_two_point_model_fixed_tet, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/use_LOC_tau_e_below_threshold.py b/cfspopcon/algorithms/use_LOC_tau_e_below_threshold.py new file mode 100644 index 00000000..70ee87be --- /dev/null +++ b/cfspopcon/algorithms/use_LOC_tau_e_below_threshold.py @@ -0,0 +1,87 @@ +"""Switch to the LOC scaling if it predicts a worse energy confinement than our selected tau_e scaling.""" +import xarray as xr + +from .. import formulas, named_options +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "energy_confinement_time", + "P_in", + "SOC_LOC_ratio", +] + + +def run_use_LOC_tau_e_below_threshold( + plasma_stored_energy: Unitfull, + energy_confinement_time: Unitfull, + P_in: Unitfull, + average_electron_density: Unitfull, + confinement_time_scalar: Unitfull, + plasma_current: Unitfull, + magnetic_field_on_axis: Unitfull, + major_radius: Unitfull, + areal_elongation: Unitfull, + separatrix_elongation: Unitfull, + inverse_aspect_ratio: Unitfull, + fuel_average_mass_number: Unitfull, + triangularity_psi95: Unitfull, + separatrix_triangularity: Unitfull, + q_star: Unitfull, +) -> dict[str, Unitfull]: + """Switch to the LOC scaling if it predicts a worse energy confinement than our selected tau_e scaling. + + Args: + plasma_stored_energy: :term:`glossary link` + energy_confinement_time: :term:`glossary link` + P_in: :term:`glossary link` + average_electron_density: :term:`glossary link` + confinement_time_scalar: :term:`glossary link` + plasma_current: :term:`glossary link` + magnetic_field_on_axis: :term:`glossary link` + major_radius: :term:`glossary link` + areal_elongation: :term:`glossary link` + separatrix_elongation: :term:`glossary link` + inverse_aspect_ratio: :term:`glossary link` + fuel_average_mass_number: :term:`glossary link` + triangularity_psi95: :term:`glossary link` + separatrix_triangularity: :term:`glossary link` + q_star: :term:`glossary link` + + Returns: + :term:`energy_confinement_time`, :term:`P_in`, :term:`SOC_LOC_ratio` + + """ + # Calculate linear ohmic confinement for low density + energy_confinement_time_LOC, P_in_LOC = formulas.calc_tau_e_and_P_in_from_scaling( + confinement_time_scalar=confinement_time_scalar, + plasma_current=plasma_current, + magnetic_field_on_axis=magnetic_field_on_axis, + average_electron_density=average_electron_density, + major_radius=major_radius, + areal_elongation=areal_elongation, + separatrix_elongation=separatrix_elongation, + inverse_aspect_ratio=inverse_aspect_ratio, + fuel_average_mass_number=fuel_average_mass_number, + triangularity_psi95=triangularity_psi95, + separatrix_triangularity=separatrix_triangularity, + plasma_stored_energy=plasma_stored_energy, + q_star=q_star, + tau_e_scaling=named_options.ConfinementScaling.LOC, + ) + + # Use Linearized Ohmic Confinement if it gives worse energy confinement. + SOC_LOC_ratio = energy_confinement_time / energy_confinement_time_LOC + energy_confinement_time = xr.where( + SOC_LOC_ratio > 1.0, energy_confinement_time_LOC, energy_confinement_time + ) # type:ignore[no-untyped-call] + P_in = xr.where(SOC_LOC_ratio > 1.0, P_in_LOC, P_in) # type:ignore[no-untyped-call] + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +use_LOC_tau_e_below_threshold = Algorithm( + function=run_use_LOC_tau_e_below_threshold, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/algorithms/zeff_and_dilution_from_impurities.py b/cfspopcon/algorithms/zeff_and_dilution_from_impurities.py new file mode 100644 index 00000000..36221452 --- /dev/null +++ b/cfspopcon/algorithms/zeff_and_dilution_from_impurities.py @@ -0,0 +1,57 @@ +"""Calculate the impact of core impurities on z_effective and dilution.""" +import xarray as xr + +from .. import formulas +from ..atomic_data import read_atomic_data +from ..unit_handling import Unitfull, convert_to_default_units +from .algorithm_class import Algorithm + +RETURN_KEYS = [ + "impurity_charge_state", + "z_effective", + "dilution", + "summed_impurity_density", + "average_ion_density", +] + + +def run_calc_zeff_and_dilution_from_impurities( + average_electron_density: Unitfull, + average_electron_temp: Unitfull, + impurities: xr.DataArray, +) -> dict[str, Unitfull]: + """Calculate the impact of core impurities on z_effective and dilution. + + Args: + average_electron_density: :term:`glossary link` + average_electron_temp: :term:`glossary link` + impurities: :term:`glossary link` + + Returns: + :term:`impurity_charge_state`, :term:`z_effective`, :term:`dilution`, :term:`summed_impurity_density`, :term:`average_ion_density` + + """ + starting_zeff = 1.0 + starting_dilution = 1.0 + + atomic_data = read_atomic_data() + + impurity_charge_state = formulas.calc_impurity_charge_state( + average_electron_density, average_electron_temp, impurities.dim_species, atomic_data + ) + change_in_zeff = formulas.calc_change_in_zeff(impurity_charge_state, impurities) + change_in_dilution = formulas.calc_change_in_dilution(impurity_charge_state, impurities) + + z_effective = starting_zeff + change_in_zeff.sum(dim="dim_species") + dilution = starting_dilution - change_in_dilution.sum(dim="dim_species") + summed_impurity_density = impurities.sum(dim="dim_species") * average_electron_density + average_ion_density = dilution * average_electron_density + + local_vars = locals() + return {key: convert_to_default_units(local_vars[key], key) for key in RETURN_KEYS} + + +calc_zeff_and_dilution_from_impurities = Algorithm( + function=run_calc_zeff_and_dilution_from_impurities, + return_keys=RETURN_KEYS, +) diff --git a/cfspopcon/atomic_data/__init__.py b/cfspopcon/atomic_data/__init__.py new file mode 100644 index 00000000..9705e76a --- /dev/null +++ b/cfspopcon/atomic_data/__init__.py @@ -0,0 +1,4 @@ +"""Interface to atomic data from radas.""" +from .read_radas_data import read_atomic_data + +__all__ = ["read_atomic_data"] diff --git a/cfspopcon/atomic_data/read_radas_data.py b/cfspopcon/atomic_data/read_radas_data.py new file mode 100644 index 00000000..8aa15b51 --- /dev/null +++ b/cfspopcon/atomic_data/read_radas_data.py @@ -0,0 +1,80 @@ +"""Open the atomic data files and return corresponding xr.Datasets and interpolators.""" +from pathlib import Path +from typing import Optional, Union + +import numpy as np +import xarray as xr +from scipy.interpolate import RectBivariateSpline, RegularGridInterpolator # type: ignore[import] + +from ..named_options import Impurity +from ..unit_handling import convert_units, magnitude, ureg + + +def read_atomic_data(directory: Optional[Path] = None) -> dict[Impurity, xr.DataArray]: + """Read the atomic data files and return a dictionary mapping Impurity keys to xr.DataArrays of atomic data.""" + if directory is None: + directory = Path(__file__).parent + + atomic_data_files = { + Impurity.Helium: directory / "helium.nc", + Impurity.Lithium: directory / "lithium.nc", + Impurity.Beryllium: directory / "beryllium.nc", + Impurity.Carbon: directory / "carbon.nc", + Impurity.Nitrogen: directory / "nitrogen.nc", + Impurity.Oxygen: directory / "oxygen.nc", + Impurity.Neon: directory / "neon.nc", + Impurity.Argon: directory / "argon.nc", + Impurity.Krypton: directory / "krypton.nc", + Impurity.Xenon: directory / "xenon.nc", + Impurity.Tungsten: directory / "tungsten.nc", + } + + atomic_data = {} + + for key, file in atomic_data_files.items(): + if not file.exists(): + raise FileNotFoundError(f"Could not find the atomic data file {file.absolute()} for species {key}") + + ds = xr.open_dataset(file).pint.quantify() + + # Convert the dimensions from linear to log values + ds["dim_log_electron_temperature"] = xr.DataArray( + np.log10(magnitude(convert_units(ds.electron_temperature, ureg.eV))), dims="dim_electron_temperature" + ) + ds["dim_log_electron_density"] = xr.DataArray( + np.log10(magnitude(convert_units(ds.electron_density, ureg.m**-3))), dims="dim_electron_density" + ) + ds["dim_log_ne_tau"] = xr.DataArray(np.log10(magnitude(convert_units(ds.ne_tau, ureg.m**-3 * ureg.s))), dims="dim_ne_tau") + + ds = ds.swap_dims({"dim_electron_temperature": "dim_log_electron_temperature"}) + ds = ds.swap_dims({"dim_electron_density": "dim_log_electron_density"}) + ds = ds.swap_dims({"dim_ne_tau": "dim_log_ne_tau"}) + + def build_interpolator(curve: xr.Dataset) -> Union[RectBivariateSpline, RegularGridInterpolator]: + if curve.ndim == 2: + return RectBivariateSpline( + x=curve.dim_log_electron_temperature, + y=curve.dim_log_electron_density, + z=np.log10(magnitude(curve.transpose("dim_log_electron_temperature", "dim_log_electron_density"))), # type: ignore[arg-type] + ) + elif curve.ndim == 3: + return RegularGridInterpolator( + points=(curve.dim_log_electron_temperature, curve.dim_log_electron_density, curve.dim_log_ne_tau), + values=np.log10(magnitude(curve.transpose("dim_log_electron_temperature", "dim_log_electron_density", "dim_log_ne_tau"))), # type: ignore[arg-type] + bounds_error=False, + method="linear", + ) + else: + raise NotImplementedError(f"Cannot build an interpolator for a curve with ndim={curve.ndim}") + + ds = ds.assign_attrs( + coronal_Lz_interpolator=build_interpolator(ds.coronal_electron_emission_prefactor), + coronal_mean_Z_interpolator=build_interpolator(ds.coronal_mean_charge_state), + noncoronal_Lz_interpolator=build_interpolator(ds.noncoronal_electron_emission_prefactor), + noncoronal_mean_Z_interpolator=build_interpolator(ds.noncoronal_mean_charge_state), + ) + + # Drop the linear coordinates + atomic_data[key] = ds.drop_vars(("dim_ne_tau", "dim_electron_temperature", "dim_electron_density")) + + return atomic_data diff --git a/cfspopcon/cli.py b/cfspopcon/cli.py new file mode 100755 index 00000000..2c9357a3 --- /dev/null +++ b/cfspopcon/cli.py @@ -0,0 +1,79 @@ +#!.venv/bin/python +# Run this script from the repository directory. +"""CLI for cfspopcon.""" +import sys +from pathlib import Path + +import click +import matplotlib.pyplot as plt # type:ignore[import] +import xarray as xr +from ipdb import launch_ipdb_on_exception # type:ignore[import] + +from cfspopcon import file_io +from cfspopcon.input_file_handling import read_case +from cfspopcon.plotting import make_plot, read_plot_style + + +@click.command() +@click.argument("case", type=click.Path(exists=True)) +@click.option( + "--plots", + "-p", + type=click.Path(exists=True), + multiple=True, +) +@click.option("--show", is_flag=True, help="Display an interactive figure of the result") +@click.option("--debug", is_flag=True, help="Enable the ipdb exception catcher") +def run_popcon_cli(case: str, plots: tuple[str], show: bool, debug: bool) -> None: + """Run POPCON from the command line. + + This function uses "Click" to develop the command line interface. You can execute it using + poetry run python cfspopcon/cli.py --help + + You can specify a set of plots to create by specifying a plot style file after `-p` on the command-line. Multiple entries are supported. + """ + if show and not plots: + print(f"Speficied show={show}, but did not specify a plot style, see --plots!") + sys.exit(1) + + if not debug: + run_popcon(case, plots, show) + else: + with launch_ipdb_on_exception(): + run_popcon(case, plots, show) + + +def run_popcon(case: str, plots: tuple[str], show: bool) -> None: + """Run popcon case. + + Args: + case: specify case to run (corresponding to a case in cases) + plots: specify which plots to make (corresponding to a plot_style in plot_styles) + show: show the resulting plots + """ + input_parameters, algorithm, points = read_case(case) + + dataset = xr.Dataset(input_parameters) + + algorithm.validate_inputs(dataset) + algorithm.update_dataset(dataset, in_place=True) + + output_dir = Path(case) / "output" if Path(case).is_dir() else Path(case).parent / "output" + output_dir.mkdir(exist_ok=True) + + file_io.write_dataset_to_netcdf(dataset, filepath=output_dir / "dataset.nc") + + for point, point_params in points.items(): + file_io.write_point_to_file(dataset, point, point_params, output_dir=output_dir) + + # Plot the results + for plot_style in plots: + make_plot(dataset, read_plot_style(plot_style), points, title=input_parameters.get("plot_title", "POPCON"), output_dir=output_dir) + + print("Done") + if show: + plt.show() + + +if __name__ == "__main__": + run_popcon_cli() diff --git a/cfspopcon/file_io.py b/cfspopcon/file_io.py new file mode 100644 index 00000000..56e304d5 --- /dev/null +++ b/cfspopcon/file_io.py @@ -0,0 +1,104 @@ +"""Functions for saving results to file and loading those files.""" +import json +from pathlib import Path +from typing import Any + +import xarray as xr + +from .helpers import convert_named_options +from .point_selection import build_mask_from_dict, find_coords_of_minimum +from .unit_handling import convert_to_default_units, set_default_units + + +def sanitize_variable(val: xr.DataArray, key: str) -> xr.DataArray: + """Strip units and Enum values from a variable so that it can be stored in a NetCDF file.""" + try: + val = convert_to_default_units(val, key).pint.dequantify() + except KeyError: + pass + + if val.dtype == object: + if val.size == 1: + val = val.item().name + else: + val = xr.DataArray([v.name for v in val.values]) + + return val + + +def write_dataset_to_netcdf(dataset: xr.Dataset, filepath: Path) -> None: + """Write a dataset to a NetCDF file.""" + serialized_dataset = dataset.copy() + for key in dataset.keys(): + assert isinstance(key, str) # because hashable type of key is broader str but we know it's str + serialized_dataset[key] = sanitize_variable(dataset[key], key) + + for key in dataset.coords: + assert isinstance(key, str) # because hashable type of key is broader str but we know it's str + serialized_dataset[key] = sanitize_variable(dataset[key], key) + + serialized_dataset.to_netcdf(filepath) + + +def promote_variable(val: xr.DataArray, key: str) -> Any: + """Add back in units and Enum values that were removed by sanitize_variable.""" + try: + val = set_default_units(val, key) + except KeyError: + pass + + if val.dtype == object: + if val.size == 1: + return convert_named_options(key, val.item()) + else: + return [convert_named_options(key, v) for v in val.values] + + return val + + +def read_dataset_from_netcdf(filepath: Path) -> xr.Dataset: + """Open a dataset from a NetCDF file.""" + dataset = xr.open_dataset(filepath) + + for key in dataset.keys(): + assert isinstance(key, str) + dataset[key] = promote_variable(dataset[key], key) + + for key in dataset.coords: + if key == "dim_species": + dataset[key] = promote_variable(dataset[key], key="impurity") + else: + assert isinstance(key, str) # because hashable type of key is broader str but we know it's str + dataset[key] = promote_variable(dataset[key], key) + + return dataset + + +def write_point_to_file(dataset: xr.Dataset, point_key: str, point_params: dict, output_dir: Path) -> None: + """Write the analysis values at the named points to a json file.""" + mask = build_mask_from_dict(dataset, point_params) + + if "minimize" not in point_params.keys() and "maximize" not in point_params.keys(): + raise ValueError(f"Need to provide either minimize or maximize in point specification. Keys were {point_params.keys()}") + + if "minimize" in point_params.keys(): + array = dataset[point_params["minimize"]] + else: + array = -dataset[point_params["maximize"]] + + point_coords = find_coords_of_minimum(array, keep_dims=point_params.get("keep_dims", []), mask=mask) + + point = dataset.isel(point_coords) + + for key in point.keys(): + assert isinstance(key, str) # because hashable type of key is broader str but we know it's str + point[key] = sanitize_variable(point[key], key) + + for key in point.coords: + assert isinstance(key, str) # because hashable type of key is broader str but we know it's str + point[key] = sanitize_variable(point[key], key) + + output_dir.mkdir(parents=True, exist_ok=True) + + with open(output_dir / f"{point_key}.json", "w") as file: + json.dump(point.to_dict(), file, indent=4) diff --git a/cfspopcon/formulas/Q_thermal_gain_factor.py b/cfspopcon/formulas/Q_thermal_gain_factor.py new file mode 100644 index 00000000..2f609114 --- /dev/null +++ b/cfspopcon/formulas/Q_thermal_gain_factor.py @@ -0,0 +1,39 @@ +"""Calculate the thermal gain factor (Q, Q_plasma, Q_thermal).""" +import numpy as np + +from ..unit_handling import ureg, wraps_ufunc + +_IGNITED_THRESHOLD = 1e3 +_IGNITED = 1e6 + + +def _ignition_above_threshold(Q: float) -> float: + """If Q > _IGNITED_THRESHOLD, set equal to _IGNITED. + + Args: + Q: Fusion power gain [~] + + Returns: + Q [~] + """ + if Q > _IGNITED_THRESHOLD: + return _IGNITED + else: + return Q + + +@wraps_ufunc(return_units=dict(Q=ureg.dimensionless), input_units=dict(P_fusion=ureg.MW, P_launched=ureg.MW)) +def thermal_calc_gain_factor(P_fusion: float, P_launched: float) -> float: + """Calculate the fusion gain. + + Args: + P_fusion: [MW] :term:`glossary link` + P_launched: [MW] :term:`glossary link` + + Returns: + Q [~] + """ + if np.isclose(P_launched, 0.0): + return _IGNITED + else: + return _ignition_above_threshold(P_fusion / P_launched) diff --git a/cfspopcon/formulas/__init__.py b/cfspopcon/formulas/__init__.py new file mode 100644 index 00000000..68239238 --- /dev/null +++ b/cfspopcon/formulas/__init__.py @@ -0,0 +1,94 @@ +"""Formulas for POPCONs analysis.""" + +from . import energy_confinement_time_scalings, fusion_reaction_data, plasma_profile_data, radiated_power +from .average_fuel_ion_mass import calc_fuel_average_mass_number +from .beta import calc_beta_normalised, calc_beta_poloidal, calc_beta_toroidal, calc_beta_total +from .confinement_regime_threshold_powers import ( + calc_confinement_transition_threshold_power, + calc_LH_transition_threshold_power, + calc_LI_transition_threshold_power, +) +from .current_drive import ( + calc_bootstrap_fraction, + calc_current_relaxation_time, + calc_f_shaping, + calc_loop_voltage, + calc_neoclassical_loop_resistivity, + calc_ohmic_power, + calc_plasma_current, + calc_q_star, + calc_resistivity_trapped_enhancement, + calc_Spitzer_loop_resistivity, +) +from .density_peaking import calc_density_peaking, calc_effective_collisionality +from .divertor_metrics import calc_B_pol_omp, calc_B_tor_omp +from .energy_confinement_time_scalings import calc_tau_e_and_P_in_from_scaling +from .figures_of_merit import calc_normalised_collisionality, calc_peak_pressure, calc_rho_star, calc_triple_product +from .fusion_rates import calc_fusion_power, calc_neutron_flux_to_walls +from .geometry import calc_plasma_surface_area, calc_plasma_volume +from .impurity_effects import calc_change_in_dilution, calc_change_in_zeff, calc_impurity_charge_state +from .operational_limits import calc_greenwald_density_limit, calc_greenwald_fraction, calc_troyon_limit +from .plasma_profiles import calc_1D_plasma_profiles +from .Q_thermal_gain_factor import thermal_calc_gain_factor +from .radiated_power import ( + calc_bremsstrahlung_radiation, + calc_impurity_radiated_power, + calc_impurity_radiated_power_mavrin_coronal, + calc_impurity_radiated_power_mavrin_noncoronal, + calc_impurity_radiated_power_post_and_jensen, + calc_impurity_radiated_power_radas, + calc_synchrotron_radiation, +) + +__all__ = [ + "energy_confinement_time_scalings", + "fusion_reaction_data", + "calc_density_peaking", + "calc_effective_collisionality", + "plasma_profile_data", + "calc_fuel_average_mass_number", + "calc_B_pol_omp", + "calc_B_tor_omp", + "calc_beta_normalised", + "calc_beta_poloidal", + "calc_beta_toroidal", + "calc_troyon_limit", + "calc_greenwald_density_limit", + "calc_beta_total", + "calc_bootstrap_fraction", + "calc_current_relaxation_time", + "calc_f_shaping", + "calc_fusion_power", + "calc_greenwald_fraction", + "calc_LH_transition_threshold_power", + "calc_LI_transition_threshold_power", + "calc_loop_voltage", + "calc_resistivity_trapped_enhancement", + "calc_neoclassical_loop_resistivity", + "calc_neutron_flux_to_walls", + "calc_normalised_collisionality", + "calc_1D_plasma_profiles", + "calc_ohmic_power", + "calc_peak_pressure", + "calc_plasma_current", + "calc_plasma_surface_area", + "calc_plasma_volume", + "calc_rho_star", + "calc_Spitzer_loop_resistivity", + "calc_q_star", + "calc_triple_product", + "calc_tau_e_and_P_in_from_scaling", + "thermal_calc_gain_factor", + "calc_confinement_transition_threshold_power", + "calc_change_in_zeff", + "calc_change_in_dilution", + "calc_bremsstrahlung_radiation", + "calc_synchrotron_radiation", + "calc_impurity_radiated_power_post_and_jensen", + "calc_impurity_radiated_power_radas", + "calc_impurity_radiated_power", + "calc_impurity_radiated_power_mavrin_coronal", + "calc_impurity_radiated_power_mavrin_noncoronal", + "radiated_power", + "calc_impurity_charge_state", +] diff --git a/cfspopcon/formulas/average_fuel_ion_mass.py b/cfspopcon/formulas/average_fuel_ion_mass.py new file mode 100644 index 00000000..1bd23c54 --- /dev/null +++ b/cfspopcon/formulas/average_fuel_ion_mass.py @@ -0,0 +1,30 @@ +"""Calculate the average fuel mass in atomic mass units.""" +from typing import Callable + +from ..named_options import ReactionType +from ..unit_handling import ureg, wraps_ufunc + +FUEL_MASS_AMU: dict[ReactionType, Callable[[float], float]] = { + ReactionType.DT: lambda heavier_fuel_species_fraction: 2.0 + heavier_fuel_species_fraction, + ReactionType.DD: lambda _: 2.0, + ReactionType.DHe3: lambda heavier_fuel_species_fraction: 2.0 + heavier_fuel_species_fraction, + ReactionType.pB11: lambda heavier_fuel_species_fraction: 11.0 * heavier_fuel_species_fraction + + 1.0 * (1.0 - heavier_fuel_species_fraction), +} + + +@wraps_ufunc( + return_units=dict(fuel_average_mass_number=ureg.amu), + input_units=dict(fusion_reaction=None, heavier_fuel_species_fraction=ureg.dimensionless), +) +def calc_fuel_average_mass_number(fusion_reaction: ReactionType, heavier_fuel_species_fraction: float) -> float: + """Calculate the average mass of the fuel ions, based on reaction type and fuel mixture ratio. + + Args: + fusion_reaction: reaction type. + heavier_fuel_species_fraction: n_heavier / (n_heavier + n_lighter) number fraction. + + Returns: + :term:`fuel_average_mass_number` [amu] + """ + return FUEL_MASS_AMU[fusion_reaction](heavier_fuel_species_fraction) diff --git a/cfspopcon/formulas/beta.py b/cfspopcon/formulas/beta.py new file mode 100644 index 00000000..8b17ec0e --- /dev/null +++ b/cfspopcon/formulas/beta.py @@ -0,0 +1,135 @@ +"""Calculate the ratio of magnetic to plasma (kinetic) pressure.""" +import numpy as np + +from ..unit_handling import Quantity, Unitfull, convert_units, ureg + + +def _calc_beta_general( + average_electron_density: Unitfull, average_electron_temp: Unitfull, average_ion_temp: Unitfull, magnetic_field: Unitfull +) -> Unitfull: + """Calculate the average ratio of the plasma pressure to the magnetic pressure due to a magnetic_field. + + Using equation 11.58 from Freidberg, "Plasma Physics and Fusion Energy" :cite:`freidberg_plasma_2007` + + The unit_conversion_factor comes from cancelling the units to get a dimensionless quantity + + >>> from pint import Quantity + >>> n = Quantity(1e19, "m^-3") + >>> T = Quantity(1, "keV") + >>> B = Quantity(1, "T") + >>> mu_0 = Quantity(1, "mu_0") + >>> ((2*mu_0 * n * T / (B**2)).to('').units + + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + magnetic_field: magnetic field generating magnetic pressure [T] + + Returns: + beta (toroidal or poloidal) [~] + """ + mu_0 = Quantity(1, "mu_0") + # to make the result dimensionless + unit_conversion_factor = 2 * mu_0 + ret = unit_conversion_factor * (average_electron_density * (average_electron_temp + average_ion_temp)) / (magnetic_field**2) + return convert_units(ret, ureg.dimensionless) + + +def calc_beta_toroidal( + average_electron_density: Unitfull, average_electron_temp: Unitfull, average_ion_temp: Unitfull, magnetic_field_on_axis: Unitfull +) -> Unitfull: + """Calculate the average ratio of the plasma pressure to the magnetic pressure due to the toroidal field. + + Also called beta_external, since the toroidal field is generated by external toroidal field coils. + Using equation 11.58 from Freidberg, "Plasma Physics and Fusion Energy" :cite:`freidberg_plasma_2007` + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + + Returns: + :term:`beta_toroidal` [~] + """ + return _calc_beta_general(average_electron_density, average_electron_temp, average_ion_temp, magnetic_field=magnetic_field_on_axis) + + +def calc_beta_poloidal( + average_electron_density: Unitfull, + average_electron_temp: Unitfull, + average_ion_temp: Unitfull, + plasma_current: Unitfull, + minor_radius: Unitfull, +) -> Unitfull: + """Calculate the average ratio of the plasma pressure to the magnetic pressure due to the plasma current. + + Calculates the poloidal magnetic field at radius a from the plasma current using + equation 11.55 from Freidberg, "Plasma Physics and Fusion Energy" :cite:`freidberg_plasma_2007` + and then evaluates beta_poloidal using + equation 11.58 from Freidberg, "Plasma Physics and Fusion Energy" :cite:`freidberg_plasma_2007` + + The unit_conversion_factor cancels the units, and can be calculated using the following + + >>> from pint import Quantity + >>> from numpy import pi + >>> mu_0 = Quantity(1, "mu_0") + >>> I = Quantity(1, "MA") + >>> minor_radius = Quantity(1, "m") + >>> (mu_0 * I / (2 * pi * minor_radius)).to("T").units + + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + plasma_current: [MA] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + + Returns: + :term:`beta_poloidal` [~] + """ + mu_0 = Quantity(1, "mu_0") + # to ensure the final result is in units of tesla + units_conversion_factor = mu_0 / (2 * np.pi) + B_pol = units_conversion_factor * plasma_current / minor_radius + + return _calc_beta_general(average_electron_density, average_electron_temp, average_ion_temp, magnetic_field=B_pol) + + +def calc_beta_total(beta_toroidal: Unitfull, beta_poloidal: Unitfull) -> Unitfull: + """Calculate the total beta from the toroidal and poloidal betas. + + Using equation 11.59 from Freidberg, "Plasma Physics and Fusion Energy" :cite:`freidberg_plasma_2007` + + Args: + beta_toroidal: [~] :term:`glossary link` + beta_poloidal: [~] :term:`glossary link` + + Returns: + :term:`beta_total` [~] + """ + return 1.0 / (1.0 / beta_toroidal + 1.0 / beta_poloidal) + + +def calc_beta_normalised(beta: Unitfull, minor_radius: Unitfull, magnetic_field_on_axis: Unitfull, plasma_current: Unitfull) -> Unitfull: + """Normalize beta to stability (Troyon) parameters. + + See section 6.18 in Wesson :cite:`wesson_tokamaks_2011`. + + Args: + beta: plasma pressure normalized against toroidal B-on-axis [%] + minor_radius: [m] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + plasma_current: [MA] :term:`glossary link` + + Returns: + :term:`beta_N` + """ + normalisation = plasma_current / (minor_radius * magnetic_field_on_axis) + + beta_N = beta / normalisation + + return beta_N diff --git a/cfspopcon/formulas/confinement_regime_threshold_powers.py b/cfspopcon/formulas/confinement_regime_threshold_powers.py new file mode 100644 index 00000000..3d080e83 --- /dev/null +++ b/cfspopcon/formulas/confinement_regime_threshold_powers.py @@ -0,0 +1,153 @@ +"""Threshold powers required to enter improved confinement regimes.""" +from ..named_options import ConfinementScaling +from ..unit_handling import ureg, wraps_ufunc + + +def _calc_Martin_LH_threshold( + magnetic_field_on_axis: float, surface_area: float, fuel_average_mass_number: float, electron_density_profile: float +) -> float: + """See below.""" + _DEUTERIUM_MASS_NUMBER = 2.0 + + return float(0.0488 * ((electron_density_profile / 10.0) ** 0.717) * (magnetic_field_on_axis**0.803) * (surface_area**0.941)) * ( + _DEUTERIUM_MASS_NUMBER / fuel_average_mass_number + ) + + +@wraps_ufunc( + return_units=dict(P_LH_thresh=ureg.MW), + input_units=dict( + plasma_current=ureg.MA, + magnetic_field_on_axis=ureg.T, + minor_radius=ureg.m, + major_radius=ureg.m, + surface_area=ureg.m**2, + fuel_average_mass_number=ureg.amu, + average_electron_density=ureg.n19, + scale=ureg.dimensionless, + ), +) +def calc_LH_transition_threshold_power( + plasma_current: float, + magnetic_field_on_axis: float, + minor_radius: float, + major_radius: float, + surface_area: float, + fuel_average_mass_number: float, + average_electron_density: float, + scale: float = 1.0, +) -> float: + """Calculate the threshold power (crossing the separatrix) to transition into H-mode. + + From Martin NF 2008 Scaling, with mass correction :cite:`martin_power_2008` + Added in low density branch from Ryter 2014 :cite:`Ryter_2014` + + Args: + plasma_current: [MA] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + major_radius: [m] :term:`glossary link` + surface_area: [m^2] :term:`glossary link` + fuel_average_mass_number: [amu] :term:`glossary link` + average_electron_density: [1e19 m^-3] :term:`glossary link` + scale: (optional) scaling factor for P_LH adjustment studies [~] + + Returns: + :term:`P_LH_thresh` [MW] + """ + neMin19 = ( + 0.7 * (plasma_current**0.34) * (magnetic_field_on_axis**0.62) * (minor_radius**-0.95) * ((major_radius / minor_radius) ** 0.4) + ) + + if average_electron_density < neMin19: + P_LH_thresh = _calc_Martin_LH_threshold( + magnetic_field_on_axis, surface_area, fuel_average_mass_number, electron_density_profile=neMin19 + ) + return float(P_LH_thresh * (neMin19 / average_electron_density) ** 2.0) * scale + else: + P_LH_thresh = _calc_Martin_LH_threshold( + magnetic_field_on_axis, surface_area, fuel_average_mass_number, electron_density_profile=average_electron_density + ) + return P_LH_thresh * scale + + +@wraps_ufunc( + return_units=dict(P_LI_thresh=ureg.MW), + input_units=dict(plasma_current=ureg.MA, average_electron_density=ureg.n19, scale=ureg.dimensionless), +) +def calc_LI_transition_threshold_power(plasma_current: float, average_electron_density: float, scale: float = 1.0) -> float: + """Calculate the threshold power (crossing the separatrix) to transition into I-mode. + + Note: uses scaling described in Fig 5 of ref :cite:`hubbard_threshold_2012` + + Args: + plasma_current: [MA] :term:`glossary link` + average_electron_density: [1e19 m^-3] :term:`glossary link` + scale: (optional) scaling factor for P_LI adjustment studies [~] + + Returns: + :term:`P_LI_thresh` [MW] + """ + return float(2.11 * plasma_current**0.94 * ((average_electron_density / 10.0) ** 0.65)) * scale + + +@wraps_ufunc( + return_units=dict(P_LH_thresh=ureg.MW), + input_units=dict( + energy_confinement_scaling=None, + plasma_current=ureg.MA, + magnetic_field_on_axis=ureg.T, + minor_radius=ureg.m, + major_radius=ureg.m, + surface_area=ureg.m**2, + fuel_average_mass_number=ureg.amu, + average_electron_density=ureg.n19, + confinement_threshold_scalar=ureg.dimensionless, + ), +) +def calc_confinement_transition_threshold_power( + energy_confinement_scaling: ConfinementScaling, + plasma_current: float, + magnetic_field_on_axis: float, + minor_radius: float, + major_radius: float, + surface_area: float, + fuel_average_mass_number: float, + average_electron_density: float, + confinement_threshold_scalar: float = 1.0, +) -> float: + """Calculate the threshold power (crossing the separatrix) to transition into an improved confinement mode. + + Args: + energy_confinement_scaling: [] :term:`glossary link` + plasma_current: [MA] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + major_radius: [m] :term:`glossary link` + surface_area: [m^2] :term:`glossary link` + fuel_average_mass_number: [amu] :term:`glossary link` + average_electron_density: [1e19 m^-3] :term:`glossary link` + confinement_threshold_scalar: (optional) scaling factor for P_LH adjustment studies [~] + + Returns: + :term:`P_LH_thresh` [MW] + """ + if energy_confinement_scaling not in [ConfinementScaling.LOC, ConfinementScaling.IModey2]: + P_LH_thresh = calc_LH_transition_threshold_power.__wrapped__( + plasma_current, + magnetic_field_on_axis, + minor_radius, + major_radius, + surface_area, + fuel_average_mass_number, + average_electron_density, + scale=confinement_threshold_scalar, + ) + elif energy_confinement_scaling == ConfinementScaling.IModey2: + P_LH_thresh = calc_LI_transition_threshold_power.__wrapped__( + plasma_current, average_electron_density, scale=confinement_threshold_scalar + ) + else: + raise ValueError("Encountered unhandled confinement time scaling.") + + return float(P_LH_thresh) diff --git a/cfspopcon/formulas/current_drive.py b/cfspopcon/formulas/current_drive.py new file mode 100644 index 00000000..95be3129 --- /dev/null +++ b/cfspopcon/formulas/current_drive.py @@ -0,0 +1,254 @@ +"""Ohmic and bootstrap plasma current, loop resistivity & voltage, and current relaxation time.""" +from ..unit_handling import Unitfull, ureg, wraps_ufunc + + +def calc_f_shaping(inverse_aspect_ratio: Unitfull, areal_elongation: Unitfull, triangularity_psi95: Unitfull) -> Unitfull: + """Calculate the shaping function. + + Equation A11 from ITER Physics Basis Ch. 1. Eqn. A-11 :cite:`editors_iter_1999` + See following discussion for how this function is used. + q_95 = 5 * minor_radius^2 * magnetic_field_on_axis / (R * plasma_current) f_shaping + + Args: + inverse_aspect_ratio: [~] :term:`glossary link` + areal_elongation: [~] :term:`glossary link` + triangularity_psi95: [~] :term:`glossary link` + + Returns: + :term:`f_shaping` [~] + """ + return ((1.0 + areal_elongation**2.0 * (1.0 + 2.0 * triangularity_psi95**2.0 - 1.2 * triangularity_psi95**3.0)) / 2.0) * ( + (1.17 - 0.65 * inverse_aspect_ratio) / (1.0 - inverse_aspect_ratio**2.0) ** 2.0 + ) + + +@wraps_ufunc( + input_units=dict( + magnetic_field_on_axis=ureg.T, + major_radius=ureg.m, + inverse_aspect_ratio=ureg.dimensionless, + q_star=ureg.dimensionless, + f_shaping=ureg.dimensionless, + ), + return_units=dict(plasma_current=ureg.MA), +) +def calc_plasma_current( + magnetic_field_on_axis: float, major_radius: float, inverse_aspect_ratio: float, q_star: float, f_shaping: float +) -> float: + """Calculate the plasma current in mega-amperes. + + Updated formula from ITER Physics Basis Ch. 1. :cite:`editors_iter_1999` + + Args: + magnetic_field_on_axis: [T] :term:`glossary link` + major_radius: [m] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + q_star: [~] :term:`glossary link` + f_shaping: [~] :term:`glossary link` + + Returns: + :term:`plasma_current` [MA] + """ + return float(5.0 * ((inverse_aspect_ratio * major_radius) ** 2.0) * (magnetic_field_on_axis / (q_star * major_radius)) * f_shaping) + + +@wraps_ufunc( + input_units=dict( + magnetic_field_on_axis=ureg.T, + major_radius=ureg.m, + inverse_aspect_ratio=ureg.dimensionless, + plasma_current=ureg.MA, + f_shaping=ureg.dimensionless, + ), + return_units=dict(q_star=ureg.dimensionless), +) +def calc_q_star( + magnetic_field_on_axis: float, major_radius: float, inverse_aspect_ratio: float, plasma_current: float, f_shaping: float +) -> float: + """Calculate an analytical estimate for the edge safety factor q_star. + + Updated formula from ITER Physics Basis Ch. 1. :cite:`editors_iter_1999` + + Args: + magnetic_field_on_axis: [T] :term:`glossary link` + major_radius: [m] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + plasma_current: [MA] :term:`glossary link` + f_shaping: [~] :term:`glossary link` + + Returns: + :term:`plasma_current` [MA] + """ + return float(5.0 * (inverse_aspect_ratio * major_radius) ** 2.0 * magnetic_field_on_axis / (plasma_current * major_radius) * f_shaping) + + +def calc_ohmic_power(inductive_plasma_current: Unitfull, loop_voltage: Unitfull) -> Unitfull: + """Calculate the Ohmic heating power. + + Args: + inductive_plasma_current: [MA] :term:`glossary link` + loop_voltage: [V] :term:`glossary link` + + Returns: + :term:`P_Ohmic` [MW] + """ + return inductive_plasma_current * loop_voltage + + +@wraps_ufunc(input_units=dict(average_electron_temp=ureg.keV), return_units=dict(spitzer_resistivity=ureg.ohm * ureg.m)) +def calc_Spitzer_loop_resistivity(average_electron_temp: float) -> float: + """Calculate the parallel Spitzer loop resistivity assuming the Coulomb logarithm = 17 and Z=1. + + Resistivity from Wesson 2.16.2 :cite:`wesson_tokamaks_2011` + + Args: + average_electron_temp: [keV] :term:`glossary link` + + Returns: + :term:`spitzer_resistivity` [Ohm-m] + """ + return float((2.8e-8) * (average_electron_temp ** (-1.5))) + + +def calc_resistivity_trapped_enhancement(inverse_aspect_ratio: Unitfull, definition: int = 3) -> Unitfull: + """Calculate the enhancement of the plasma resistivity due to trapped particles. + + Definition 1 is the denominator of eta_n (neoclassical resistivity) on p801 of Wesson :cite:`wesson_tokamaks_2011` + + Args: + inverse_aspect_ratio: [~] :term:`glossary link` + definition: [~] choice of [1,2,3] to specify which definition to use + + Returns: + :term:`trapped_particle_fraction` [~] + + Raises: + NotImplementedError: if definition doesn't match an implementation + """ + if definition == 1: + trapped_particle_fraction = 1 / ((1.0 - (inverse_aspect_ratio**0.5)) ** 2.0) # pragma: nocover + elif definition == 2: + trapped_particle_fraction = 2 / (1.0 - 1.31 * (inverse_aspect_ratio**0.5) + 0.46 * inverse_aspect_ratio) # pragma: nocover + elif definition == 3: + trapped_particle_fraction = 0.609 / (0.609 - 0.785 * (inverse_aspect_ratio**0.5) + 0.269 * inverse_aspect_ratio) + else: + raise NotImplementedError(f"No implementation {definition} for calc_resistivity_trapped_enhancement.") # pragma: nocover + + return trapped_particle_fraction + + +def calc_neoclassical_loop_resistivity( + spitzer_resistivity: Unitfull, z_effective: Unitfull, trapped_particle_fraction: Unitfull +) -> Unitfull: + """Calculate the neoclassical loop resistivity including impurity ions. + + Wesson Section 14.10. Impact of ion charge. Impact of dilution ~ 0.9. + + Args: + spitzer_resistivity: [Ohm-m] :term:`glossary link` + z_effective: [~] :term:`glossary link` + trapped_particle_fraction: [~] :term:`glossary link` + + Returns: + :term:`neoclassical_loop_resistivity` [Ohm-m] + """ + return spitzer_resistivity * z_effective * 0.9 * trapped_particle_fraction + + +@wraps_ufunc( + input_units=dict( + major_radius=ureg.m, + inverse_aspect_ratio=ureg.dimensionless, + areal_elongation=ureg.dimensionless, + average_electron_temp=ureg.keV, + z_effective=ureg.dimensionless, + ), + return_units=dict(current_relaxation_time=ureg.s), +) +def calc_current_relaxation_time( + major_radius: float, inverse_aspect_ratio: float, areal_elongation: float, average_electron_temp: float, z_effective: float +) -> float: + """Calculate the current relaxation time. + + from :cite:`Bonoli` + + Args: + major_radius: [m] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + areal_elongation: [~] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + z_effective: [~] :term:`glossary link` + + Returns: + :term:`current_relaxation_time` [s] + """ + return float( + 1.4 * ((major_radius * inverse_aspect_ratio) ** 2.0) * areal_elongation * (average_electron_temp**1.5) / z_effective + ) # [s] + + +def calc_loop_voltage( + major_radius: Unitfull, + minor_radius: Unitfull, + inductive_plasma_current: Unitfull, + areal_elongation: Unitfull, + neoclassical_loop_resistivity: Unitfull, +) -> Unitfull: + """Calculate plasma toroidal loop voltage at flattop. + + Plasma loop voltage from Alex Creely's original work. + + Args: + major_radius: [m] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + inductive_plasma_current: [MA] :term:`glossary link` + areal_elongation: [~] :term:`glossary link` + neoclassical_loop_resistivity: [Ohm-m] :term:`glossary link` + + Returns: + :term:`loop_voltage` [V] + """ + Iind = inductive_plasma_current # Inductive plasma current [A] + + _term1 = 2 * major_radius / (minor_radius**2 * areal_elongation) # Toroidal length over plasma cross-section surface area [1/m] + return Iind * _term1 * neoclassical_loop_resistivity + + +def calc_bootstrap_fraction( + ion_density_peaking: Unitfull, + electron_density_peaking: Unitfull, + temperature_peaking: Unitfull, + z_effective: Unitfull, + q_star: Unitfull, + inverse_aspect_ratio: Unitfull, + beta_poloidal: Unitfull, +) -> Unitfull: + """Calculate bootstrap current fraction. + + K. Gi et al, Bootstrap current fraction scaling :cite:`gi_bootstrap_2014` + Equation assumes q0 = 1 + + Args: + ion_density_peaking: [~] :term:`glossary link` + electron_density_peaking: [~] :term:`glossary link` + temperature_peaking: [~] :term:`glossary link` + z_effective: [~] :term:`glossary link` + q_star: [~] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + beta_poloidal: [~] :term:`glossary link` + + Returns: + :term:`bootstrap_fraction` [~] + """ + nu_n = (ion_density_peaking + electron_density_peaking) / 2 + + bootstrap_fraction = 0.474 * ( + (temperature_peaking - 1.0 + nu_n - 1.0) ** 0.974 + * (temperature_peaking - 1.0) ** -0.416 + * z_effective**0.178 + * q_star**-0.133 + * inverse_aspect_ratio**0.4 + * beta_poloidal + ) + + return bootstrap_fraction diff --git a/cfspopcon/formulas/density_peaking.py b/cfspopcon/formulas/density_peaking.py new file mode 100644 index 00000000..2e1065ff --- /dev/null +++ b/cfspopcon/formulas/density_peaking.py @@ -0,0 +1,52 @@ +"""Estimate the density peaking based on scaling from C. Angioni.""" +import numpy as np +import xarray as xr + +from ..unit_handling import Unitfull, ureg, wraps_ufunc + + +def calc_density_peaking(effective_collisionality: Unitfull, betaE: Unitfull, nu_noffset: Unitfull) -> Unitfull: + """Calculate the density peaking (peak over volume average). + + Equation 3 from p1334 of Angioni et al, "Scaling of density peaking in H-mode plasmas based on a combined + database of AUG and JET observations" :cite:`angioni_scaling_2007` + + Args: + effective_collisionality: [~] :term:`glossary link ` + betaE: beta due to external field [~] + nu_noffset: scalar offset added to peaking factor [~] + + Returns: + :term:`nu_n` [~] + """ + nu_n = (1.347 - 0.117 * np.log(effective_collisionality) - 4.03 * betaE) + nu_noffset + if isinstance(nu_n, xr.DataArray): + return nu_n.clip(1.0, float("inf")) + else: + return max(nu_n, 1.0 * ureg.dimensionless) + + +@wraps_ufunc( + return_units=dict(effective_collisionality=ureg.dimensionless), + input_units=dict( + average_electron_density=ureg.n19, average_electron_temp=ureg.keV, major_radius=ureg.m, z_effective=ureg.dimensionless + ), +) +def calc_effective_collisionality( + average_electron_density: float, average_electron_temp: float, major_radius: float, z_effective: float +) -> float: + """Calculate the effective collisionality. + + From p1327 of Angioni et al, "Scaling of density peaking in H-mode plasmas based on a combined + database of AUG and JET observations" :cite:`angioni_scaling_2007` + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + major_radius: [m] :term:`glossary link` + z_effective: [~] :term:`glossary link` + + Returns: + :term:`effective_collisionality` [~] + """ + return float((0.1 * z_effective * average_electron_density * major_radius) / (average_electron_temp**2.0)) diff --git a/cfspopcon/formulas/divertor_metrics.py b/cfspopcon/formulas/divertor_metrics.py new file mode 100644 index 00000000..025ee269 --- /dev/null +++ b/cfspopcon/formulas/divertor_metrics.py @@ -0,0 +1,40 @@ +"""Divertor loading and functions to calculate OMP pitch (for q_parallel calculation).""" +import numpy as np +from scipy import constants # type: ignore[import] + +from ..unit_handling import ureg, wraps_ufunc + + +@wraps_ufunc( + return_units=dict(B_pol_omp=ureg.T), + input_units=dict(plasma_current=ureg.A, minor_radius=ureg.m), +) +def calc_B_pol_omp(plasma_current: float, minor_radius: float) -> float: + """Calculate the poloidal magnetic field at the outboard midplane. + + Args: + plasma_current: [MA] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + + Returns: + B_pol_omp [T] + """ + return float(constants.mu_0 * plasma_current / (2.0 * np.pi * minor_radius)) + + +@wraps_ufunc( + return_units=dict(B_tor_omp=ureg.T), + input_units=dict(magnetic_field_on_axis=ureg.T, major_radius=ureg.m, minor_radius=ureg.m), +) +def calc_B_tor_omp(magnetic_field_on_axis: float, major_radius: float, minor_radius: float) -> float: + """Calculate the toroidal magnetic field at the outboard midplane. + + Args: + magnetic_field_on_axis: [T] :term:`glossary link` + major_radius: [m] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + + Returns: + B_tor_omp [T] + """ + return magnetic_field_on_axis * (major_radius / (major_radius + minor_radius)) diff --git a/cfspopcon/formulas/energy_confinement_time_scalings/__init__.py b/cfspopcon/formulas/energy_confinement_time_scalings/__init__.py new file mode 100644 index 00000000..9f2c993c --- /dev/null +++ b/cfspopcon/formulas/energy_confinement_time_scalings/__init__.py @@ -0,0 +1,9 @@ +"""Empirical scalings for energy confinement time.""" + +from .tau_e_from_Wp import calc_tau_e_and_P_in_from_scaling, get_datasets, load_metadata + +__all__ = [ + "calc_tau_e_and_P_in_from_scaling", + "load_metadata", + "get_datasets", +] diff --git a/cfspopcon/formulas/energy_confinement_time_scalings/tau_e_from_Wp.py b/cfspopcon/formulas/energy_confinement_time_scalings/tau_e_from_Wp.py new file mode 100644 index 00000000..319df285 --- /dev/null +++ b/cfspopcon/formulas/energy_confinement_time_scalings/tau_e_from_Wp.py @@ -0,0 +1,169 @@ +"""Calculate tau_e and P_in from a tau_e scaling and the stored energy.""" +from pathlib import Path + +import numpy as np +import yaml + +from ...named_options import ConfinementScaling +from ...unit_handling import ureg, wraps_ufunc + +# Preload the scalings (instead of doing fileio in loop) +with open(Path(__file__).parent / "tau_e_scalings.yaml") as f: + TAU_E_SCALINGS = yaml.safe_load(f) + + +@wraps_ufunc( + return_units=dict(tau_e=ureg.s, P_tau=ureg.MW), + input_units=dict( + confinement_time_scalar=ureg.dimensionless, + plasma_current=ureg.MA, + magnetic_field_on_axis=ureg.T, + average_electron_density=ureg.n19, + major_radius=ureg.m, + areal_elongation=ureg.dimensionless, + separatrix_elongation=ureg.dimensionless, + inverse_aspect_ratio=ureg.dimensionless, + fuel_average_mass_number=ureg.amu, + triangularity_psi95=ureg.dimensionless, + separatrix_triangularity=ureg.dimensionless, + plasma_stored_energy=ureg.MJ, + q_star=ureg.dimensionless, + tau_e_scaling=None, + ), + output_core_dims=[(), ()], +) +def calc_tau_e_and_P_in_from_scaling( + confinement_time_scalar: float, + plasma_current: float, + magnetic_field_on_axis: float, + average_electron_density: float, + major_radius: float, + areal_elongation: float, + separatrix_elongation: float, + inverse_aspect_ratio: float, + fuel_average_mass_number: float, + triangularity_psi95: float, + separatrix_triangularity: float, + plasma_stored_energy: float, + q_star: float, + tau_e_scaling: ConfinementScaling, +) -> tuple[float, float]: + r"""Calculate energy confinement time and input power from a tau_E scaling. + + The energy confinement time can generally be written as + + .. math:: + \tau_e = H \cdot C \cdot P_{\tau}^{\alpha_P} + \cdot I_{MA}^{\alpha_I} \cdot B_0^{\alpha_B} \cdot \bar{n_{e,19}}^{\alpha_n} \cdot R_0^{\alpha_R} + \cdot \kappa_A^{\alpha_{ka}} \cdot \kappa_{sep}^{\alpha_{ks}} \cdot \epsilon^{\alpha_e} + \cdot m_i^{\alpha_A} \cdot \delta^{\alpha_d} + + We don't know :math:`P_{\tau}` in advance, so instead write + + .. math:: \tau_e = \gamma \cdot P_{\tau}^{\alpha_P} + + with + + .. math:: + \gamma = H \cdot C + \cdot I_{MA}^{\alpha_I} \cdot B_0^{\alpha_B} \cdot \bar{n_{e,19}}^{\alpha_n} \cdot R_0^{\alpha_R} + \cdot \kappa_A^{\alpha_{ka}} \cdot \kappa_{sep}^{\alpha_{ks}} \cdot \epsilon^{\alpha_e} + \cdot m_i^{\alpha_A} \cdot \delta^{\alpha_d} + + We have everything that we need to evaluate :math:`\gamma`. Then, we also know that + + .. math:: \tau_e = W_p / P_{loss} + + Then, we crucially need to define what exactly we mean by the two powers that we've introduced + (:math:`P_{\tau}` and :math:`P_{loss}`). We usually take + :math:`P_{\tau} = P_{heating} = P_{ohmic} + P_{\alpha} + P_{aux}` and + :math:`P_{loss}=P_{SOL} + P_{rad,core}` [Wesson definition]. From a + simple power balance, :math:`P_{heating}=P_{loss}` and so, setting the two :math:`\tau_e` equations equal, we get that + + .. math:: + W_p / P = \gamma \cdot P^{\alpha_P} + P^{\alpha_P + 1} = W_p / \gamma + P = \left(W_p / \gamma \right)^{\frac{1}{\alpha_P + 1}} + + Once we have :math:`P = P_{ohmic} + P_{\alpha} + P_{aux} = P_{SOL} + P_{rad,core}`, we can calculate :math:`W_p/P`. + + However, it is also possible that the core radiated power is subtracted when calculating :math:`\tau_e` + [Freidberg definition of :math:`W_p`], giving + + .. math:: + P_{\tau} = P_{ohmic} + P_{\alpha} + P_{aux} - P_{rad} = P_{loss} = P_{SOL} + + If you are using a scaling where this is the case, set ``tau_e_scaling_uses_P_in=False``. + Then, the returned value should be interpreted as :math:`P_{SOL}`. + + N.b. there are two more possible cases, where different powers are used in the two :math:`\tau_e` scalings. + We don't allow these cases, since 1) experiments generally pick a consistent definition for :math:`P` + and 2) this results in an equation for :math:`P` which cannot be solved analytically. + + Args: + confinement_time_scalar: [~] confinement scaling factor + plasma_current: [MA] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + average_electron_density: [1e19 m^-3] :term:`glossary link` + major_radius: [m] :term:`glossary link` + areal_elongation: [~] :term:`glossary link` + separatrix_elongation: [~] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + fuel_average_mass_number: [amu] :term:`glossary link` + triangularity_psi95: [~] :term:`glossary link` + separatrix_triangularity: [~] :term:`glossary link` + plasma_stored_energy: [MJ] :term:`glossary link` + q_star: [~] :term:`glossary link` + tau_e_scaling: [] :term:`glossary link` + + Returns: + :term:`energy_confinement_time` [s], :term:`P_in` if tau_e_scaling_uses_P_in=False, else :term:`P_SOL` [MW] + """ + scaling = TAU_E_SCALINGS[tau_e_scaling.name] + + gamma = ( + confinement_time_scalar + * scaling["params"]["C"] + * plasma_current ** scaling["params"]["a_I"] + * magnetic_field_on_axis ** scaling["params"]["a_B"] + * average_electron_density ** scaling["params"]["a_n"] + * major_radius ** scaling["params"]["a_R"] + * areal_elongation ** scaling["params"]["a_ka"] + * separatrix_elongation ** scaling["params"]["a_ks"] + * inverse_aspect_ratio ** scaling["params"]["a_e"] + * fuel_average_mass_number ** scaling["params"]["a_A"] + * (1.0 + np.mean([triangularity_psi95, separatrix_triangularity])) ** scaling["params"]["a_d"] + * q_star ** scaling["params"]["a_q"] + ) + + if gamma > 0.0: + P_tau = (plasma_stored_energy / gamma) ** (1.0 / (1.0 + scaling["params"]["a_P"])) + else: + P_tau = np.inf + + tau_E = plasma_stored_energy / P_tau + + return float(tau_E), float(P_tau) + + +def load_metadata(dataset: str) -> dict[str, str]: + """Load dataset metadata from YAML file. + + Args: + dataset: name of scaling in ./energy_confinement_time.yaml + + Returns: + Metadata + """ + metadata: dict[str, str] = TAU_E_SCALINGS[dataset]["metadata"] + return metadata + + +def get_datasets() -> list[str]: + """Get a list of names of valid datasets. + + Returns: + List of names of valid datasets + """ + datasets: list[str] = list(TAU_E_SCALINGS.keys()) # Unpack iterator to list + return datasets diff --git a/cfspopcon/formulas/energy_confinement_time_scalings/tau_e_scalings.yaml b/cfspopcon/formulas/energy_confinement_time_scalings/tau_e_scalings.yaml new file mode 100644 index 00000000..5568c1ae --- /dev/null +++ b/cfspopcon/formulas/energy_confinement_time_scalings/tau_e_scalings.yaml @@ -0,0 +1,342 @@ +# Power law scaling parameters + +# References +# [1]: P. N. Yushmanov, T. Takizuka, K. S. Riedel, O. J. W. F. Kardaun, J. G. Cordey, S. M. Kaye, +# and D. E. Post, "Scalings for tokamak energy confinement" Nuclear Fusion, vol. 30, +# no. 10, pp. 4-6, 1990. +# [2]: Verdoolaege, G., Kaye, S. M., Angioni, C., Kardaun, O. J. W. F., Ryter, F., Thomsen, K., +# Maslov, M., & Romanelli, M. (2018). (publication). First Analysis of the Updated ITPA +# Global H-mode Confinement Database. International Atomic Energy Agency. +# [3]: Verdoolaege, G., Kaye, S. M., Angioni, C., Kardaun, O. J. W. F., Ryter, F., Thomsen, K., +# Maslov, M., & Romanelli, M. (2021). (publication). The Updated ITPA Global H-mode +# Confinement Database: Description and Analysis. International Atomic Energy Agency. +# [4]: ITER Physics Expert Group on Confinement and Transport et al 1999 Nucl. Fusion 39 2175 +# "ITER Physics Basis Chapter 2, Plasma confinement and transport" p. 2206 +# [5]: Petty, C.C., Deboo, J.C., La Haye, R.J., Luce, T.C., Politzer, P.A., Wong, C.P-C. (2003), +# Fusion Science and Technology, 43, "Feasibility Study of a Compact Ignition Tokamak Based +# Upon GyroBohm Scaling Physics." +# [6]: J.E. Rice et al 2020 Nucl. Fusion 60 105001, "Understanding LOC/SOC phenomenology in tokamaks" +# [7]: S.M. Kaye et al 1997 Nucl. Fusion 37 1303, "ITER L mode confinement database" + +IModey2: + metadata: + documentation: "Walk, J. R., Pedestal structure and stability in high-performance plasmas on Alcator C-Mod, https://dspace.mit.edu/handle/1721.1/95524, equation 5.2" + notes: "Coefficient C adjusted to account for ne in 1e19m^-3" + regime: "I-Mode" + params: + C: 0.01346 + a_A: 0.0 + a_B: 0.768 + a_I: 0.685 + a_P: -0.286 + a_R: 0.0 + a_d: 0.0 + a_e: 0.0 + a_ka: 0.0 + a_ks: 0.0 + a_n: 0.017 + a_q: 0.0 + +ITER89P: + metadata: + documentation: "From Yushmanov NF 1990, ref. [1] in tau_e_scalings.yaml" + notes: "For L-mode. C is corrected for average_electron_density convention. N.b. The different factor of a_R is because we use inverse_aspect_ratio=a/R instead of a. R^1.2 a^0.3 = R^1.5 inverse_aspect_ratio^0.3." + regime: "L-Mode" + params: + C: 0.03812775526676551 + a_A: 0.5 + a_B: 0.2 + a_I: 0.85 + a_P: -0.5 + a_R: 1.5 + a_d: 0.0 + a_e: 0.3 + a_ka: 0.0 + a_ks: 0.5 + a_n: 0.1 + a_q: 0.0 + +ITER89P_ka: + metadata: + documentation: "From Yushmanov NF 1990, ref. [1] in tau_e_scalings.yaml" + notes: "For L-mode. C is corrected for average_electron_density convention. Using kappa_A instead of separatrix_elongation, which is likely more accurate for double-nulls. N.b. The different factor of a_R is because we use inverse_aspect_ratio=a/R instead of a. R^1.2 a^0.3 = R^1.5 inverse_aspect_ratio^0.3." + regime: "L-Mode" + params: + C: 0.03812775526676551 + a_A: 0.5 + a_B: 0.2 + a_I: 0.85 + a_P: -0.5 + a_R: 1.5 + a_d: 0.0 + a_e: 0.3 + a_ka: 0.5 + a_ks: 0.0 + a_n: 0.1 + a_q: 0.0 + +ITER97L: + metadata: + documentation: "From Kaye NF 1997, ref. [7] in tau_e_scalings.yaml" + notes: "" + regime: "L-Mode" + params: + C: 0.023 + a_I: 0.96 + a_B: 0.03 + a_R: 1.83 + a_e: -0.06 # inverse_aspect_ratio = (R / minor_radius)^-1 + a_ka: 0.64 + a_n: 0.40 + a_A: 0.20 # M_eff + a_P: -0.73 + a_d: 0.0 + a_ks: 0.0 + a_q: 0.0 + +ITER98y2: + metadata: + documentation: "ITER98y2 scaling , ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.0562 + a_A: 0.19 + a_B: 0.15 + a_I: 0.93 + a_P: -0.69 + a_R: 1.97 + a_d: 0.0 + a_e: 0.58 + a_ka: 0.78 + a_ks: 0.0 + a_n: 0.41 + a_q: 0.0 + +ITERL96Pth: + metadata: + documentation: "ITERL96P(th) scaling, ref. [4] in tau_e_scalings.yaml" + notes: "" + regime: "L-Mode" + params: + C: 0.023 + a_A: 0.20 + a_B: 0.03 + a_I: 0.96 + a_P: -0.73 + a_R: 1.83 + a_d: 0.0 + a_e: -0.06 + a_ka: 0.64 + a_ks: 0.0 + a_n: 0.40 + a_q: 0.0 + +ITPA_2018_STD5_GLS: + metadata: + documentation: "ITPA 2018 STD5-GLS (G. Verdoolaege et al, EX_P7- 1), ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.042 + a_A: 0.47 + a_B: 0.068 + a_I: 1.2 + a_P: -0.78 + a_R: 1.6 + a_d: 0.0 + a_e: -0.052 + a_ka: 0.88 + a_ks: 0.0 + a_n: 0.21 + a_q: 0.0 + +ITPA_2018_STD5_OLS: + metadata: + documentation: "ITPA 2018 STD5-OLS (G. Verdoolaege et al, EX_P7- 1), ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.049 + a_A: 0.25 + a_B: 0.085 + a_I: 1.1 + a_P: -0.71 + a_R: 1.5 + a_d: 0.0 + a_e: -0.043 + a_ka: 0.8 + a_ks: 0.0 + a_n: 0.19 + a_q: 0.0 + +ITPA_2018_STD5_SEL1_GLS: + metadata: + documentation: "ITPA 2018 STD5-SEL1-GLS (G. Verdoolaege et al, EX_P7- 1), ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.023 + a_A: 0.33 + a_B: -0.018 + a_I: 1.3 + a_P: -0.79 + a_R: 1.5 + a_d: 0.0 + a_e: -0.38 + a_ka: 1.9 + a_ks: 0.0 + a_n: 0.17 + a_q: 0.0 + +ITPA_2018_STD5_SEL1_OLS: + metadata: + documentation: "ITPA 2018 STD5-SEL1-OLS (G. Verdoolaege et al, EX_P7- 1), ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.045 + a_A: 0.24 + a_B: -0.1 + a_I: 1.3 + a_P: -0.71 + a_R: 1.2 + a_d: 0.0 + a_e: -0.32 + a_ka: 1.1 + a_ks: 0.0 + a_n: 0.13 + a_q: 0.0 + +ITPA_2018_STD5_SEL1_WLS: + metadata: + documentation: "ITPA 2018 STD5-SEL1-WLS (G. Verdoolaege et al, EX_P7- 1), ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.03 + a_A: 0.094 + a_B: -0.069 + a_I: 1.3 + a_P: -0.64 + a_R: 1.3 + a_d: 0.0 + a_e: -0.46 + a_ka: 1.3 + a_ks: 0.0 + a_n: 0.19 + a_q: 0.0 + +ITPA_2018_STD5_WLS: + metadata: + documentation: "ITPA 2018 STD5-WLS (G. Verdoolaege et al, EX_P7- 1), ref. [2] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.04 + a_A: 0.25 + a_B: 0.11 + a_I: 0.99 + a_P: -0.64 + a_R: 1.7 + a_d: 0.0 + a_e: 0.093 + a_ka: 0.79 + a_ks: 0.0 + a_n: 0.29 + a_q: 0.0 + +ITPA20_IL_HighZ: + metadata: + documentation: "ITER H20, DB5.2.3, High Z walls only, ref. [3] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.189 + a_A: 0.312 + a_B: -0.356 + a_I: 1.485 + a_P: -0.6077 + a_R: 0.671 + a_d: 0.0 + a_e: 0.0 + a_ka: 0.0 + a_ks: 0.0 + a_n: 0.018 + a_q: 0.0 + +ITPA20_IL: + metadata: + documentation: "ITER H20, DB5.2.3, ITER-like discharges, ref. [3] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.067 + a_A: 0.3 + a_B: -0.13 + a_I: 1.29 + a_P: -0.644 + a_R: 1.19 + a_d: 0.56 + a_e: 0.0 + a_ka: 0.67 + a_ks: 0.0 + a_n: 0.15 + a_q: 0.0 + +ITPA20_STD5: + metadata: + documentation: "ITER H20, DB5.2.3, STD5 discharges, ref. [3] in tau_e_scalings.yaml" + notes: "" + regime: "H-Mode" + params: + C: 0.053 + a_A: 0.2 + a_B: 0.22 + a_I: 0.98 + a_P: -0.669 + a_R: 1.71 + a_d: 0.36 + a_e: 0.35 + a_ka: 0.80 + a_ks: 0.0 + a_n: 0.24 + a_q: 0.0 + +LOC: + metadata: + documentation: "Linear Ohmic Confinement, from page 2 of ref. [6] in tau_e_scalings.yaml" + notes: "" + regime: "LOC" + params: + C: 0.0070 + a_n: 1.0 + a_q: 1.0 + a_ka: 0.5 + a_e: 1.0 + a_R: 3.0 + a_B: 0.0 + a_I: 0.0 + a_A: 0.0 + a_P: 0.0 + a_d: 0.0 + a_ks: 0.0 + +H_DS03: + metadata: + documentation: "Electrostatic, GyroBohm-like confinement scaling, eqn 21 from ref. [5] in tau_e_scalings.yaml" + notes: "" + regime: "H-mode" + params: + C: 0.028 + a_I: 0.83 + a_B: 0.07 + a_n: 0.49 + a_P: -0.55 + a_R: 2.11 + a_e: 0.3 # (major_radius/a)^-0.3 = (a/major_radius)^0.3 + a_ks: 0.75 + a_A: 0.14 # a_M — isotope mass scaling + a_ka: 0.0 + a_d: 0.0 + a_q: 0.0 diff --git a/cfspopcon/formulas/figures_of_merit.py b/cfspopcon/formulas/figures_of_merit.py new file mode 100644 index 00000000..d24df3ce --- /dev/null +++ b/cfspopcon/formulas/figures_of_merit.py @@ -0,0 +1,108 @@ +"""OD figures-of-merit to characterize a design point.""" +import numpy as np + +from ..unit_handling import Unitfull, convert_units, ureg, wraps_ufunc + + +def calc_triple_product(peak_fuel_ion_density: Unitfull, peak_ion_temp: Unitfull, energy_confinement_time: Unitfull) -> Unitfull: + """Calculate the fusion triple product. + + Args: + peak_fuel_ion_density: [1e20 m^-3] :term:`glossary link` + peak_ion_temp: [keV] :term:`glossary link` + energy_confinement_time: [s] :term:`glossary link` + + Returns: + fusion_triple_product [10e20 m**-3 keV s] + """ + return peak_fuel_ion_density * peak_ion_temp * energy_confinement_time + + +def calc_rho_star( + fuel_average_mass_number: Unitfull, average_ion_temp: Unitfull, magnetic_field_on_axis: Unitfull, minor_radius: Unitfull +) -> Unitfull: + """Calculate rho* (normalized gyroradius). + + Equation 1a from :cite:`Verdoolaege_2021` + + Args: + fuel_average_mass_number: [amu] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + magnetic_field_on_axis: :term:`glossary link` + minor_radius: [m] :term:`glossary link` + + Returns: + rho_star [~] + """ + return convert_units( + np.sqrt(fuel_average_mass_number * average_ion_temp) / (ureg.e * magnetic_field_on_axis * minor_radius), ureg.dimensionless + ) + + +@wraps_ufunc(input_units=dict(ne=ureg.m**-3, Te=ureg.eV), return_units=dict(Lambda_c=ureg.dimensionless)) +def calc_coulomb_logarithm(ne: float, Te: float) -> float: + """Calculate the Coulomb logarithm, for electron-electron or electron-ion collisions. + + From text on page 6 of :cite:`Verdoolaege_2021` + """ + return float(30.9 - np.log(ne**0.5 * Te**-1.0)) + + +def calc_normalised_collisionality( + average_electron_density: Unitfull, + average_electron_temp: Unitfull, + average_ion_temp: Unitfull, + q_star: Unitfull, + major_radius: Unitfull, + inverse_aspect_ratio: Unitfull, + z_effective: Unitfull, +) -> Unitfull: + """Calculate normalized collisionality. + + Equation 1c from :cite:`Verdoolaege_2021` + + Extra factor of ureg.e**2, presumably related to Te**-2 for Te in eV + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + q_star: [~] :term:`glossary link` + major_radius: [m] :term:`glossary link` + inverse_aspect_ratio: [m] :term:`glossary link` + z_effective: [~] :term:`glossary link` + + Returns: + nu_star [~] + """ + return convert_units( + ureg.e**4 + / (2.0 * np.pi * 3**1.5 * ureg.epsilon_0**2) + * calc_coulomb_logarithm(average_electron_density, average_electron_temp) + * average_electron_density + * q_star + * major_radius + * z_effective + / (average_ion_temp**2 * inverse_aspect_ratio**1.5), + ureg.dimensionless, + ) + + +def calc_peak_pressure( + peak_electron_temp: Unitfull, + peak_ion_temp: Unitfull, + peak_electron_density: Unitfull, + peak_fuel_ion_density: Unitfull, +) -> Unitfull: + """Calculate the peak pressure (needed for solving for the magnetic equilibrium). + + Args: + peak_electron_temp: [keV] :term:`glossary link` + peak_ion_temp: [keV] :term:`glossary link` + peak_electron_density: [1e19 m^-3] :term:`glossary link` + peak_fuel_ion_density: [~] :term:`glossary link` + + Returns: + peak_pressure [Pa] + """ + return convert_units(peak_electron_temp * peak_electron_density + peak_ion_temp * peak_fuel_ion_density, ureg.Pa) diff --git a/cfspopcon/formulas/fusion_rates.py b/cfspopcon/formulas/fusion_rates.py new file mode 100644 index 00000000..e9d2e0b8 --- /dev/null +++ b/cfspopcon/formulas/fusion_rates.py @@ -0,0 +1,241 @@ +"""Calculate fusion power and corresponding neutron wall loading.""" + +from typing import Union + +from numpy import float64 +from numpy.typing import NDArray + +from ..named_options import ReactionType +from ..unit_handling import ureg, wraps_ufunc +from .fusion_reaction_data import ENERGY, SIGMAV +from .helpers import integrate_profile_over_volume + + +@wraps_ufunc( + return_units=dict(P_fusion=ureg.MW, P_neutron=ureg.MW, P_alpha=ureg.MW), + input_units=dict( + fusion_reaction=None, + ion_temp_profile=ureg.keV, + heavier_fuel_species_fraction=ureg.dimensionless, + nfuel19=ureg.n19, + rho=ureg.dimensionless, + plasma_volume=ureg.m**3, + ), + input_core_dims=[(), ("dim_rho",), (), ("dim_rho",), ("dim_rho",), ()], + output_core_dims=[(), (), ()], +) +def calc_fusion_power( + fusion_reaction: ReactionType, + ion_temp_profile: NDArray[float64], + heavier_fuel_species_fraction: float, + nfuel19: NDArray[float64], + rho: NDArray[float64], + plasma_volume: float, +) -> tuple[float, float, float]: + """Calculate the fusion power. + + Args: + fusion_reaction: which nuclear reaction is being considered + ion_temp_profile: [keV] :term:`glossary link` + heavier_fuel_species_fraction: [~] fraction of fuel mixture which is the heavier nuclide + nfuel19: [1e19 m^-3] average fuel density + rho: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + :term:`P_fusion` [MW], :term:`P_neutron` [MW], :term:`P_alpha` [MW] + """ + reaction_at_Ti = _calc_fusion_reaction_rate(fusion_reaction, ion_temp_profile, heavier_fuel_species_fraction) + + power_density_factor_MW_m3 = reaction_at_Ti[4] + neutral_power_density_factor_MW_m3 = reaction_at_Ti[5] + charged_power_density_factor_MW_m3 = reaction_at_Ti[6] + + total_fusion_power_MW = _integrate_power( + power_density_factor_MW_m3=power_density_factor_MW_m3, + fuel_density_per_m3=nfuel19 * 1e19, + rho=rho, + plasma_volume=plasma_volume, + ) + + fusion_power_to_neutral_MW = _integrate_power( + power_density_factor_MW_m3=neutral_power_density_factor_MW_m3, + fuel_density_per_m3=nfuel19 * 1e19, + rho=rho, + plasma_volume=plasma_volume, + ) + + fusion_power_to_charged_MW = _integrate_power( + power_density_factor_MW_m3=charged_power_density_factor_MW_m3, + fuel_density_per_m3=nfuel19 * 1e19, + rho=rho, + plasma_volume=plasma_volume, + ) + + return total_fusion_power_MW, fusion_power_to_neutral_MW, fusion_power_to_charged_MW + + +@wraps_ufunc( + return_units=dict(neutron_power_flux_to_walls=ureg.MW / ureg.m**2, neutron_rate=ureg.s**-1), + input_units=dict( + P_neutron=ureg.MW, + surface_area=ureg.m**2, + fusion_reaction=None, + ion_temp_profile=ureg.keV, + heavier_fuel_species_fraction=ureg.dimensionless, + ), + input_core_dims=[(), (), (), ("dim_rho",), ()], + output_core_dims=[(), ()], +) +def calc_neutron_flux_to_walls( + P_neutron: float, + surface_area: float, + fusion_reaction: ReactionType, + ion_temp_profile: NDArray[float64], + heavier_fuel_species_fraction: float, +) -> tuple[float, float]: + """Calculate the neutron loading on the wall. + + Args: + P_neutron: [MW] :term:`glossary link` + surface_area: [m^2] :term:`glossary link` + fusion_reaction: which nuclear reaction is being considered + ion_temp_profile: [keV] :term:`glossary link` + heavier_fuel_species_fraction: fraction of fuel mixture which is the heavier nuclide + + Returns: + neutron_power_flux_to_walls [MW / m^2], neutron_rate [s^-1] + """ + neutron_power_flux_to_walls = P_neutron / surface_area + rxn_energy_neut = _calc_fusion_reaction_rate(fusion_reaction, ion_temp_profile, heavier_fuel_species_fraction)[2] + if rxn_energy_neut > 0: # This will happen for D-He3 reactions + neutron_rate = P_neutron / rxn_energy_neut # [MW / MJ] -> [1 / s] + else: + neutron_rate = 0.0 + + return neutron_power_flux_to_walls, neutron_rate + + +@wraps_ufunc( + return_units=dict( + sigmav=ureg.cm**3 / ureg.s, + rxn_energy=ureg.MJ, + rxn_energy_neut=ureg.MJ, + rxn_energy_charged=ureg.MJ, + number_power_dens=ureg.MW * ureg.m**3, + number_power_dens_neut=ureg.MW * ureg.m**3, + number_power_dens_charged=ureg.MW * ureg.m**3, + ), + input_units=dict( + fusion_reaction=None, + ion_temp_profile=ureg.keV, + heavier_fuel_species_fraction=ureg.dimensionless, + ), + input_core_dims=[(), ("dim_rho",), ()], + output_core_dims=[("dim_rho",), (), (), (), ("dim_rho",), ("dim_rho",), ("dim_rho",)], +) +def calc_fusion_reaction_rate( + fusion_reaction: ReactionType, ion_temp_profile: NDArray[float64], heavier_fuel_species_fraction: float +) -> tuple[ + NDArray[float64], + Union[NDArray[float64], float], + float, + Union[NDArray[float64], float], + NDArray[float64], + NDArray[float64], + NDArray[float64], +]: + """Calculate reaction properties based on reaction type, mixture ratio, and temperature. + + Args: + fusion_reaction: which nuclear reaction is being considered + ion_temp_profile: [keV] :term:`glossary link` + heavier_fuel_species_fraction: fraction of fuel mixture which is the heavier nuclide + + Returns: + :A tuple holding: + + :sigmav: rate coefficient for the given ion temperature [cm^3/s] + :rxn_energy: total energy released per reaction [MJ] + :rxn_energy_neut: energy released to neutral products per reaction [MJ] + :rxn_energy_charged: energy released to charged products per reaction [MJ] + :number_power_dens: power per unit volume divided by reactant densities [MW*m^3] + :number_power_dens_neut: power per unit volume divided by reactant densities deposited in neutral products [MW*m^3] + :number_power_dens_charged: power per unit volume divided by reactant densities deposited in charged products [MW*m^3] + """ + return _calc_fusion_reaction_rate(fusion_reaction, ion_temp_profile, heavier_fuel_species_fraction) + + +def _calc_fusion_reaction_rate( + fusion_reaction: ReactionType, ion_temp_profile: NDArray[float64], heavier_fuel_species_fraction: float +) -> tuple[ + NDArray[float64], + Union[NDArray[float64], float], + float, + Union[NDArray[float64], float], + NDArray[float64], + NDArray[float64], + NDArray[float64], +]: + """Calculate reaction properties based on reaction type, mixture ratio, and temperature, without unit-handling. + + Args: + fusion_reaction: which nuclear reaction is being considered + ion_temp_profile: [keV] :term:`glossary link` + heavier_fuel_species_fraction: fraction of fuel mixture which is the heavier nuclide + + Returns: + :A tuple holding: + + :sigmav: rate coefficient for the given ion temperature [cm^3/s] + :rxn_energy: total energy released per reaction [MJ] + :rxn_energy_neut: energy released to neutral products per reaction [MJ] + :rxn_energy_charged: energy released to charged products per reaction [MJ] + :number_power_dens: power per unit volume divided by reactant densities [MW*m^3] + :number_power_dens_neut: power per unit volume divided by reactant densities deposited in neutral products [MW*m^3] + :number_power_dens_charged: power per unit volume divided by reactant densities deposited in charged products [MW*m^3] + """ + sigmav_func = SIGMAV[fusion_reaction] # Reaction rate function to use based on reaction type + energy_func = ENERGY[fusion_reaction] # Reaction energy function to use based on reaction type + + sigmav = sigmav_func(ion_temp_profile) + + # This generates a false positive when type checking, as the type checker doesn't + # realize that the sigmav_func and energy_func pair always correctly matches. + # That's because the return type of a dictionary can't be narrowed based on a runtime key. + (rxn_energy, rxn_energy_neut, rxn_energy_charged, number_power_dens, number_power_dens_neut, number_power_dens_charged,) = energy_func( + sigmav=sigmav, heavier_fuel_species_fraction=heavier_fuel_species_fraction # type:ignore[call-arg] + ) + + return ( + sigmav, + rxn_energy, + rxn_energy_neut, + rxn_energy_charged, + number_power_dens, + number_power_dens_neut, + number_power_dens_charged, + ) # type:ignore[return-value] + + +def _integrate_power( + power_density_factor_MW_m3: NDArray[float64], + fuel_density_per_m3: NDArray[float64], + rho: NDArray[float64], + plasma_volume: float, +) -> float: + """Calculate the total power due to a nuclear reaction. + + Args: + power_density_factor_MW_m3: energy per unit volume divided by fuel species densities [MW*m^3] + fuel_density_per_m3: density of fuel species [m^-3] + rho: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + power [MW] + """ + power_density_MW_per_m3 = power_density_factor_MW_m3 * fuel_density_per_m3 * fuel_density_per_m3 + power_MW = integrate_profile_over_volume(power_density_MW_per_m3, rho, plasma_volume) + + return power_MW diff --git a/cfspopcon/formulas/fusion_reaction_data/__init__.py b/cfspopcon/formulas/fusion_reaction_data/__init__.py new file mode 100644 index 00000000..7430f8b7 --- /dev/null +++ b/cfspopcon/formulas/fusion_reaction_data/__init__.py @@ -0,0 +1,53 @@ +"""Reactions rates and power densities for various fusion reactions.""" +from typing import Callable, Union + +from numpy import float64 +from numpy.typing import NDArray + +from ...named_options import ReactionType +from .reaction_energies import reaction_energy_DD, reaction_energy_DHe3, reaction_energy_DT, reaction_energy_pB11 +from .reaction_rate_coefficients import sigmav_DD, sigmav_DD_BoschHale, sigmav_DHe3, sigmav_DT, sigmav_DT_BoschHale, sigmav_pB11 + +SIGMAV: dict[ + ReactionType, + Union[ + Callable[[NDArray[float64]], NDArray[float64]], + Callable[[NDArray[float64]], tuple[NDArray[float64], NDArray[float64], NDArray[float64]]], + ], +] = { + ReactionType.DT: sigmav_DT, + ReactionType.DD: sigmav_DD_BoschHale, + ReactionType.DHe3: sigmav_DHe3, + ReactionType.pB11: sigmav_pB11, +} + +ENERGY: dict[ + ReactionType, + Union[ + Callable[[NDArray[float64], float], tuple[float, float, float, NDArray[float64], NDArray[float64], NDArray[float64]]], + Callable[ + [tuple[NDArray[float64], NDArray[float64], NDArray[float64]]], + tuple[NDArray[float64], float, NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64]], + ], + ], +] = { + ReactionType.DT: reaction_energy_DT, + ReactionType.DD: reaction_energy_DD, + ReactionType.DHe3: reaction_energy_DHe3, + ReactionType.pB11: reaction_energy_pB11, +} + +__all__ = [ + "SIGMAV", + "ENERGY", + "reaction_energy_DD", + "reaction_energy_DHe3", + "reaction_energy_DT", + "reaction_energy_pB11", + "sigmav_DD_BoschHale", + "sigmav_DHe3", + "sigmav_DT", + "sigmav_pB11", + "sigmav_DD", + "sigmav_DT_BoschHale", +] diff --git a/cfspopcon/formulas/fusion_reaction_data/reaction_energies.py b/cfspopcon/formulas/fusion_reaction_data/reaction_energies.py new file mode 100644 index 00000000..bb8218f3 --- /dev/null +++ b/cfspopcon/formulas/fusion_reaction_data/reaction_energies.py @@ -0,0 +1,140 @@ +"""Reaction energies and power densities.""" + +from typing import Any + +from numpy import float64 +from numpy.typing import NDArray +from scipy import constants # type: ignore[import] + + +def reaction_energy_DT( + sigmav: NDArray[float64], heavier_fuel_species_fraction: float +) -> tuple[float, float, float, NDArray[float64], NDArray[float64], NDArray[float64]]: + r"""Deuterium-Tritium reaction. + + Calculate reaction energies and power density values. + + Args: + sigmav: :math:`\langle \sigma v \rangle` product in cm^3/s. + heavier_fuel_species_fraction: n_Tritium / (n_Tritium + n_Deuterium) number fraction. + + Returns: + Tuple of reaction energies and corresponding power densities. + """ + rxn_energy: float = 17.6 * constants.value("electron volt") # [MJ] + rxn_energy_neut: float = rxn_energy * (4.0 / 5.0) # [MJ] + rxn_energy_charged: float = rxn_energy * (1.0 / 5.0) # [MJ] + convert_volume: float = 1e-6 # [m^3/cm^3] + number_power_dens: NDArray[float64] = ( + sigmav * rxn_energy * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + number_power_dens_neut: NDArray[float64] = ( + sigmav * rxn_energy_neut * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + number_power_dens_charged: NDArray[float64] = ( + sigmav * rxn_energy_charged * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + + # Units: [MJ], [MW*m^3] + return rxn_energy, rxn_energy_neut, rxn_energy_charged, number_power_dens, number_power_dens_neut, number_power_dens_charged + + +def reaction_energy_DD( + sigmav: tuple[ + NDArray[float64], + NDArray[float64], + NDArray[float64], + ], + **_: Any, +) -> tuple[NDArray[float64], float, NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64]]: + r"""Deuterium-Deuterium reaction. + + Calculate reaction energies and power density values. + + Args: + sigmav: :math:`\langle \sigma v \rangle` product in cm^3/s. + _: Unused placeholder to enable unified call syntax with e.g. :func:`reaction_energy_DT`. + + Returns: + Tuple of reaction energies and corresponding power densities. + """ + sigmav_tot, sigmav_1, sigmav_2 = sigmav + path_1_energy: float = (1.01 + 3.02) * constants.value("electron volt") # MJ, D+D -> p+T + path_2_energy: float = (0.82 + 2.45) * constants.value("electron volt") # MJ, D+D -> n+He3 + rxn_energy: NDArray[float64] = (path_1_energy * sigmav_1 + path_2_energy * sigmav_2) / sigmav_tot + rxn_energy_neut: float = path_2_energy * (3.0 / 4.0) + rxn_energy_charged: NDArray[float64] = (path_1_energy * sigmav_1 + (path_2_energy * (1.0 / 4.0)) * sigmav_2) / sigmav_tot + + # So number_power_dens*electron_density_profile**2 = power_dens [MW/m^3] no need to divide since nD=ne + convert_volume = 1e-6 # m^3/cm^3 + number_power_dens: NDArray[float64] = (sigmav_1 * path_1_energy + sigmav_2 * path_2_energy) * convert_volume + number_power_dens_neut: NDArray[float64] = sigmav_2 * rxn_energy_neut * convert_volume + number_power_dens_charged: NDArray[float64] = (sigmav_1 * path_1_energy + sigmav_2 * path_2_energy * (1.0 / 4.0)) * convert_volume + + # Units: [MJ], [MW/m^3] + return rxn_energy, rxn_energy_neut, rxn_energy_charged, number_power_dens, number_power_dens_neut, number_power_dens_charged + + +def reaction_energy_DHe3( + sigmav: NDArray[float64], heavier_fuel_species_fraction: float +) -> tuple[float, float, float, NDArray[float64], NDArray[float64], NDArray[float64]]: + r"""Deuterium-Helium 3 reaction. + + Calculate reaction energies and power density values. + + Args: + sigmav: :math:`\langle \sigma v \rangle` product in cm^3/s. + heavier_fuel_species_fraction: n_heavier / (n_heavier + n_lighter) number fraction. + + Returns: + Tuple of reaction energies and corresponding power densities. + """ + rxn_energy: float = 18.3 * constants.value("electron volt") # MJoules + rxn_energy_neut: float = 0.0 + rxn_energy_charged: float = rxn_energy + convert_volume: float = 1e-6 # m^3/cm^3 + number_power_dens: NDArray[float64] = ( + sigmav * rxn_energy * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + number_power_dens_neut: NDArray[float64] = ( + sigmav * rxn_energy_neut * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + number_power_dens_charged: NDArray[float64] = ( + sigmav * rxn_energy_charged * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + + # Units: [MJ], [MW/m^3] + return rxn_energy, rxn_energy_neut, rxn_energy_charged, number_power_dens, number_power_dens_neut, number_power_dens_charged + + +def reaction_energy_pB11( + sigmav: NDArray[float64], heavier_fuel_species_fraction: float +) -> tuple[float, float, float, NDArray[float64], NDArray[float64], NDArray[float64]]: + r"""Proton (hydrogen)-Boron-11 reaction. + + Calculate reaction energies and power density values. + + Args: + sigmav: :math:`\langle \sigma v \rangle` product in cm^3/s. + heavier_fuel_species_fraction: n_heavier / (n_heavier + n_lighter) number fraction. + + Returns: + Tuple of reaction energies and corresponding power densities. + """ + rxn_energy: float = 8.7 * constants.value("electron volt") # MJoules + rxn_energy_neut: float = 0.0 + rxn_energy_charged: float = rxn_energy + # This is accurate to within 1% + convert_volume: float = 1e-6 # m^3/cm^3 + number_power_dens: NDArray[float64] = ( + sigmav * rxn_energy * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + number_power_dens_neut: NDArray[float64] = ( + sigmav * rxn_energy_neut * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + number_power_dens_charged: NDArray[float64] = ( + sigmav * rxn_energy_charged * convert_volume * heavier_fuel_species_fraction * (1.0 - heavier_fuel_species_fraction) + ) + + # Units: [MJ], [MW/m^3] + return rxn_energy, rxn_energy_neut, rxn_energy_charged, number_power_dens, number_power_dens_neut, number_power_dens_charged diff --git a/cfspopcon/formulas/fusion_reaction_data/reaction_rate_coefficients.py b/cfspopcon/formulas/fusion_reaction_data/reaction_rate_coefficients.py new file mode 100644 index 00000000..de09f4b6 --- /dev/null +++ b/cfspopcon/formulas/fusion_reaction_data/reaction_rate_coefficients.py @@ -0,0 +1,298 @@ +"""Reaction rates () as a function of ion temperature.""" + +import numpy as np +from numpy import float64 +from numpy.typing import NDArray + + +def sigmav_DT(ion_temp_profile: NDArray[float64]) -> NDArray[float64]: + r"""Deuterium-Tritium reaction. + + Calculate :math:`\langle \sigma v \rangle` for a given characteristic ion energy. + Formulation from table 1, column S5 in :cite:`hively_convenient_1977`. + Curvefit was performed for the range of [1,80]keV. + + Args: + ion_temp_profile: ion temperature profile [keV] + + Returns: + :math:`\langle \sigma v \rangle` in cm^3/s. + """ + A = [-21.377692, -25.204054, -7.1013427 * 1e-2, 1.9375451 * 1e-4, 4.9246592 * 1e-6, -3.9836572 * 1e-8] + r = 0.2935 + sigmav = np.exp( + A[0] / ion_temp_profile**r + + A[1] + + A[2] * ion_temp_profile + + A[3] * ion_temp_profile**2.0 + + A[4] * ion_temp_profile**3.0 + + A[5] * ion_temp_profile**4.0 + ) + return sigmav # type: ignore[no-any-return] # [cm^3/s] + + +def sigmav_DT_BoschHale(ion_temp_profile: NDArray[float64]) -> NDArray[float64]: + r"""Deuterium-Tritium reaction. + + Calculate :math:`\langle \sigma v \rangle` product for a given characteristic ion energy using Bosch Hale method. + + :func:`sigmav_DT_BoschHale` is more accurate than :func:`sigmav_DT` for ion_temp_profile > ~48.45 keV (estimate based on + linear interp between errors found at available datapoints). + Maximum error = 1.4% within range 50-1000 keV from available NRL data. + + Formulation from :cite:`bosch_improved_1992` + + Args: + ion_temp_profile: ion temperature profile [keV] + + Returns: + :math:`\langle \sigma v \rangle` in cm^3/s. + + """ + # Bosch Hale coefficients for DT reaction + C = [0.0, 1.173e-9, 1.514e-2, 7.519e-2, 4.606e-3, 1.35e-2, -1.068e-4, 1.366e-5] + B_G = 34.3827 + mr_c2 = 1124656 + + theta = ion_temp_profile / ( + 1 + - (ion_temp_profile * (C[2] + ion_temp_profile * (C[4] + ion_temp_profile * C[6]))) + / (1 + ion_temp_profile * (C[3] + ion_temp_profile * (C[5] + ion_temp_profile * C[7]))) + ) + eta = (B_G**2 / (4 * theta)) ** (1 / 3) + sigmav = C[1] * theta * np.sqrt(eta / (mr_c2 * ion_temp_profile**3)) * np.exp(-3 * eta) + return sigmav # type: ignore[no-any-return] # [cm^3/s] + + +def sigmav_DD(ion_temp_profile: NDArray[float64]) -> tuple[NDArray[float64], NDArray[float64], NDArray[float64]]: + r"""Deuterium-Deuterium reaction. + + Calculate :math:`\langle \sigma v \rangle` for a given characteristic ion energy. + Formulation from column S5, in table 3 and 4 in :cite:`hively_convenient_1977`. + Curvefit was performed for the range of [1,80]keV. + + Args: + ion_temp_profile: ion temperature profile [keV] + + Returns: + :math:`\langle \sigma v \rangle` tuple (total, D(d,p)T, D(d,n)3He) in cm^3/s. + """ + a_1 = [ + -15.511891, + -35.318711, + -1.2904737 * 1e-2, + 2.6797766 * 1e-4, + -2.9198685 * 1e-6, + 1.2748415 * 1e-8, + ] # For D(d,p)T + r_1 = 0.3735 + a_2 = [ + -15.993842, + -35.017640, + -1.3689787 * 1e-2, + 2.7089621 * 1e-4, + -2.9441547 * 1e-6, + 1.2841202 * 1e-8, + ] # For D(d,n)3He + r_2 = 0.3725 + # Ti in units of keV, sigmav in units of cm^3/s + sigmav_1: NDArray[float64] = np.exp( + a_1[0] / ion_temp_profile**r_1 + + a_1[1] + + a_1[2] * ion_temp_profile + + a_1[3] * ion_temp_profile**2.0 + + a_1[4] * ion_temp_profile**3.0 + + a_1[5] * ion_temp_profile**4.0 + ) + sigmav_2: NDArray[float64] = np.exp( + a_2[0] / ion_temp_profile**r_2 + + a_2[1] + + a_2[2] * ion_temp_profile + + a_2[3] * ion_temp_profile**2.0 + + a_2[4] * ion_temp_profile**3.0 + + a_2[5] * ion_temp_profile**4.0 + ) + sigmav_tot: NDArray[float64] = sigmav_1 + sigmav_2 + return sigmav_tot, sigmav_1, sigmav_2 # [cm^3/s] + + +def sigmav_DD_BoschHale(ion_temp_profile: NDArray[float64]) -> tuple[NDArray[float64], NDArray[float64], NDArray[float64]]: + r"""Deuterium-Deuterium reaction. + + Calculate :math:`\langle \sigma v \rangle` product for a given characteristic ion energy using Bosch Hale method. + + Function tested on available data at [1, 2, 5, 10, 20, 50, 100] keV. + Maximum error = 3.8% within range 5-50 keV and increases significantly outside of [5, 50] keV. + + Uses DD cross section formulation from :cite:`bosch_improved_1992`. + + Other form in :cite:`langenbrunner_analytic_2017`. + + Args: + ion_temp_profile: ion temperature profile [keV] + + Returns: + :math:`\langle \sigma v \rangle` tuple (total, D(d,p)T, D(d,n)3He) in cm^3/s. + """ + # For D(d,n)3He + cBH_1 = [((31.3970**2) / 4.0) ** (1.0 / 3.0), 5.65718e-12, 3.41e-03, 1.99e-03, 0, 1.05e-05, 0, 0] # 3.72e-16, + + mc2_1 = 937814.0 + + # For D(d,p)T + cBH_2 = [((31.3970**2) / 4.0) ** (1.0 / 3.0), 5.43360e-12, 5.86e-03, 7.68e-03, 0, -2.96e-06, 0, 0] # 3.57e-16, + + mc2_2 = 937814.0 + + thetaBH_1 = ion_temp_profile / ( + 1 + - ( + (cBH_1[2] * ion_temp_profile + cBH_1[4] * ion_temp_profile**2 + cBH_1[6] * ion_temp_profile**3) + / (1 + cBH_1[3] * ion_temp_profile + cBH_1[5] * ion_temp_profile**2 + cBH_1[7] * ion_temp_profile**3) + ) + ) + + thetaBH_2 = ion_temp_profile / ( + 1 + - ( + (cBH_2[2] * ion_temp_profile + cBH_2[4] * ion_temp_profile**2 + cBH_2[6] * ion_temp_profile**3) + / (1 + cBH_2[3] * ion_temp_profile + cBH_2[5] * ion_temp_profile**2 + cBH_2[7] * ion_temp_profile**3) + ) + ) + + etaBH_1: float = cBH_1[0] / (thetaBH_1 ** (1.0 / 3.0)) + etaBH_2: float = cBH_2[0] / (thetaBH_2 ** (1.0 / 3.0)) + + sigmav_1: NDArray[float64] = cBH_1[1] * thetaBH_1 * np.sqrt(etaBH_1 / (mc2_1 * (ion_temp_profile**3.0))) * np.exp(-3.0 * etaBH_1) + sigmav_2: NDArray[float64] = cBH_2[1] * thetaBH_2 * np.sqrt(etaBH_2 / (mc2_2 * (ion_temp_profile**3.0))) * np.exp(-3.0 * etaBH_2) + sigmav_tot: NDArray[float64] = sigmav_1 + sigmav_2 + + return sigmav_tot, sigmav_1, sigmav_2 # [cm^3/s] + + +def sigmav_DHe3(ion_temp_profile: NDArray[float64]) -> NDArray[float64]: + r"""Deuterium-Helium-3 reaction. + + Calculate :math:`\langle \sigma v \rangle` for a given characteristic ion energy. + + Function tested on available data at [1, 2, 5, 10, 20, 50, 100] keV. + Maximum error = 8.4% within range 2-100 keV and should not be used outside range [2, 100] keV. + + Uses DD cross section formulation :cite:`bosch_improved_1992`. + + Args: + ion_temp_profile: ion temperature profile [keV] + + Returns: + :math:`\langle \sigma v \rangle` in cm^3/s. + """ + # For He3(d,p)4He + cBH_1 = [ + ((68.7508**2) / 4.0) ** (1.0 / 3.0), + 5.51036e-10, # 3.72e-16, + 6.41918e-03, + -2.02896e-03, + -1.91080e-05, + 1.35776e-04, + 0, + 0, + ] + + mc2_1 = 1124572.0 + + thetaBH_1 = ion_temp_profile / ( + 1 + - ( + (cBH_1[2] * ion_temp_profile + cBH_1[4] * ion_temp_profile**2 + cBH_1[6] * ion_temp_profile**3) + / (1 + cBH_1[3] * ion_temp_profile + cBH_1[5] * ion_temp_profile**2 + cBH_1[7] * ion_temp_profile**3.0) + ) + ) + + etaBH_1: float = cBH_1[0] / (thetaBH_1 ** (1.0 / 3.0)) + + sigmav: NDArray[float64] = cBH_1[1] * thetaBH_1 * np.sqrt(etaBH_1 / (mc2_1 * (ion_temp_profile**3.0))) * np.exp(-3.0 * etaBH_1) + + return sigmav # [cm^3/s] + + +def sigmav_pB11(ion_temp_profile: NDArray[float64]) -> NDArray[float64]: + r"""Proton (hydrogen)-Boron11 reaction. + + Calculate :math:`\langle \sigma v \rangle` for a given characteristic ion energy. + + Uses cross section from Nevins and Swain :cite:`nevins_thermonuclear_2000`. + Updated cross sections in :cite:`sikora_new_2016`, and :cite:`putvinski_fusion_2019` are not in analytic form. + + Args: + ion_temp_profile: characteristic ion energy in keV. + + Returns: + :math:`\langle \sigma v \rangle` in cm^3/s. + """ + # High temperature (T>60 keV) + # For B11(p,alpha)alpha,alpha + cBH_1 = [ + ((22589.0) / 4.0) ** (1.0 / 3.0), + 4.4467e-14, + -5.9357e-02, + 2.0165e-01, + 1.0404e-03, + 2.7621e-03, + -9.1653e-06, + 9.8305e-07, + ] + + mc2_1 = 859526.0 + + thetaBH_1 = ion_temp_profile / ( + 1 + - ( + (cBH_1[2] * ion_temp_profile + cBH_1[4] * ion_temp_profile**2 + cBH_1[6] * ion_temp_profile**3) + / (1 + cBH_1[3] * ion_temp_profile + cBH_1[5] * ion_temp_profile**2 + cBH_1[7] * ion_temp_profile**3) + ) + ) + + etaBH_1 = cBH_1[0] / (thetaBH_1 ** (1.0 / 3.0)) + + sigmavNRhigh = ( + cBH_1[1] * thetaBH_1 * np.sqrt(etaBH_1 / (mc2_1 * (ion_temp_profile**3.0))) * np.exp(-3.0 * etaBH_1) + ) * 1e6 # m3 to cm3 + + # Low temperature (T<60 keV) + E0 = ((17.81) ** (1.0 / 3.0)) * (ion_temp_profile ** (2.0 / 3.0)) + + deltaE0 = 4.0 * np.sqrt(ion_temp_profile * E0 / 3.0) + + tau = (3.0 * E0) / ion_temp_profile + + Mp = 1.0 # *1.67e-27 + MB = 11.0 # *1.67e-27 + + Mr = (Mp * MB) / (Mp + MB) + + C0 = 197.000 * 1e-25 # MeVb to kev/m^2 + C1 = 0.240 * 1e-25 # MeVb to kev/m^2 + C2 = 0.000231 * 1e-25 # MeVb to kev/m^2 + + Seff = ( + C0 * (1 + (5.0 / (12.0 * tau))) + + C1 * (E0 + (35.0 / 36.0) * ion_temp_profile) + + C2 * (E0**2.0 + (89.0 / 36.0) * E0 * ion_temp_profile) + ) + + sigmavNRlow: NDArray[float64] = ( + np.sqrt(2 * ion_temp_profile / Mr) * ((deltaE0 * Seff) / (ion_temp_profile ** (2.0))) * np.exp(-tau) + ) * 1e6 # m3 to cm3 + # 148 keV resonance + sigmavR: NDArray[float64] = ( + (5.41e-21) * ((1.0 / ion_temp_profile) ** (3.0 / 2.0)) * np.exp(-148.0 / ion_temp_profile) + ) * 1e6 # m3 to cm3 + sigmav: NDArray[float64] = sigmavNRhigh + + for i in range(len(ion_temp_profile)): + if ion_temp_profile[i] < 60.0: # keV + sigmav[i] = sigmavNRlow[i] + sigmavR[i] + elif (ion_temp_profile[i] > 60.0) and (ion_temp_profile[i] < 130): # keV + sigmav[i] = sigmavNRhigh[i] + sigmavR[i] + + return sigmav # [cm^3/s] diff --git a/cfspopcon/formulas/geometry.py b/cfspopcon/formulas/geometry.py new file mode 100644 index 00000000..f81548f5 --- /dev/null +++ b/cfspopcon/formulas/geometry.py @@ -0,0 +1,41 @@ +"""Plasma geometry (inside the last-closed-flux-surface).""" +import numpy as np + +from ..unit_handling import Unitfull + + +def calc_plasma_volume(major_radius: Unitfull, inverse_aspect_ratio: Unitfull, areal_elongation: Unitfull) -> Unitfull: + """Calculate the plasma volume inside the last-closed-flux-surface. + + Args: + major_radius: [m] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + areal_elongation: [~] :term:`glossary link` + + Returns: + Vp [m^3] + """ + return ( + 2.0 + * np.pi + * major_radius**3.0 + * inverse_aspect_ratio**2.0 + * areal_elongation + * (np.pi - (np.pi - 8.0 / 3.0) * inverse_aspect_ratio) + ) + + +def calc_plasma_surface_area(major_radius: Unitfull, inverse_aspect_ratio: Unitfull, areal_elongation: Unitfull) -> Unitfull: + """Calculate the plasma surface area inside the last-closed-flux-surface. + + Args: + major_radius: [m] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + areal_elongation: [~] :term:`glossary link` + + Returns: + Sp [m^2] + """ + return ( + 2.0 * np.pi * (major_radius**2.0) * inverse_aspect_ratio * areal_elongation * (np.pi + 2.0 - (np.pi - 2.0) * inverse_aspect_ratio) + ) diff --git a/cfspopcon/formulas/helpers.py b/cfspopcon/formulas/helpers.py new file mode 100644 index 00000000..9da05324 --- /dev/null +++ b/cfspopcon/formulas/helpers.py @@ -0,0 +1,23 @@ +"""Common functionality shared between other functions.""" +import numpy as np +from numpy import float64 +from numpy.typing import NDArray + + +def integrate_profile_over_volume( + array_per_m3: NDArray[float64], + rho: NDArray[float64], + plasma_volume: float, +) -> float: + """Approximate the volume integral of a profile given as a function of rho. + + Args: + array_per_m3: a profile of values [units * m^-3] + rho: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + volume_integrated_value [units] + """ + drho = rho[1] - rho[0] + return float(np.sum(array_per_m3 * 2.0 * rho * drho) * plasma_volume) diff --git a/cfspopcon/formulas/impurity_effects.py b/cfspopcon/formulas/impurity_effects.py new file mode 100644 index 00000000..b7efa955 --- /dev/null +++ b/cfspopcon/formulas/impurity_effects.py @@ -0,0 +1,65 @@ +"""Calculate the effect of impurities on the effective charge and dilution.""" +import numpy as np +import xarray as xr + +from ..named_options import Impurity +from ..unit_handling import ureg, wraps_ufunc + + +@wraps_ufunc( + return_units=dict(mean_charge_state=ureg.dimensionless), + input_units=dict( + average_electron_density=ureg.m**-3, + average_electron_temp=ureg.eV, + impurity_species=None, + atomic_data=None, + ), + pass_as_kwargs=("atomic_data",), +) +def calc_impurity_charge_state( + average_electron_density: float, + average_electron_temp: float, + impurity_species: Impurity, + atomic_data: dict[Impurity, xr.DataArray], +) -> float: + """Calculate the impurity charge state of the specified impurity species. + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + impurity_species: [] :term:`glossary link` + atomic_data: :term:`glossary link` + + Returns: + :term:`impurity_charge_state` + """ + mean_charge_curve = atomic_data[impurity_species].coronal_mean_Z_interpolator + return float( + np.squeeze(np.power(10, mean_charge_curve(np.log10(average_electron_temp), np.log10(average_electron_density), grid=True))) + ) + + +def calc_change_in_zeff(impurity_charge_state: float, impurity_concentration: xr.DataArray) -> xr.DataArray: + """Calculate the change in the effective charge due to the specified impurities. + + Args: + impurity_charge_state: [~] :term:`glossary link` + impurity_concentration: [~] :term:`glossary link` + + Returns: + change in zeff [~] + """ + return impurity_charge_state * (impurity_charge_state - 1.0) * impurity_concentration + + +def calc_change_in_dilution(impurity_charge_state: float, impurity_concentration: xr.DataArray) -> xr.DataArray: + """Calculate the change in n_fuel/n_e due to the specified impurities. + + Args: + impurity_charge_state: [~] :term:`glossary link` + impurity_concentration: [~] :term:`glossary link` + + Returns: + change in dilution [~] + """ + return impurity_charge_state * impurity_concentration diff --git a/cfspopcon/formulas/operational_limits.py b/cfspopcon/formulas/operational_limits.py new file mode 100644 index 00000000..ad563447 --- /dev/null +++ b/cfspopcon/formulas/operational_limits.py @@ -0,0 +1,61 @@ +"""Operational limits to avoid disruptive regions.""" +import numpy as np + +from ..unit_handling import ureg, wraps_ufunc + + +@wraps_ufunc( + return_units=dict(greenwald_fraction=ureg.dimensionless), + input_units=dict( + average_electron_density=ureg.n20, inverse_aspect_ratio=ureg.dimensionless, major_radius=ureg.m, plasma_current=ureg.MA + ), +) +def calc_greenwald_fraction( + average_electron_density: float, inverse_aspect_ratio: float, major_radius: float, plasma_current: float +) -> float: + """Calculate the fraction of the Greenwald density limit. + + Args: + average_electron_density: [1e20 m^-3] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + major_radius: [m] :term:`glossary link` + plasma_current: [MA] :term:`glossary link` + + Returns: + :term:`greenwald_fraction` [~] + """ + n_Greenwald = calc_greenwald_density_limit.__wrapped__(plasma_current, inverse_aspect_ratio * major_radius) + + return float(average_electron_density / n_Greenwald) + + +@wraps_ufunc(return_units=dict(nG=ureg.n20), input_units=dict(plasma_current=ureg.MA, minor_radius=ureg.m)) +def calc_greenwald_density_limit(plasma_current: float, minor_radius: float) -> float: + """Calculate the Greenwald density limit. + + Args: + plasma_current: [MA] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + + Returns: + nG Greenwald density limit [n20] + """ + return plasma_current / (np.pi * minor_radius**2) + + +@wraps_ufunc( + return_units=dict(troyon_max_beta=ureg.percent), + input_units=dict(minor_radius=ureg.m, magnetic_field_on_axis=ureg.T, plasma_current=ureg.MA), +) +def calc_troyon_limit(minor_radius: float, magnetic_field_on_axis: float, plasma_current: float) -> float: + """Calculate the maximum value for beta, according to the Troyon limit. + + Args: + minor_radius: [m] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + plasma_current: [MA] :term:`glossary link` + + Returns: + troyon_max_beta [~] + """ + return 2.8 * plasma_current / (minor_radius * magnetic_field_on_axis) diff --git a/cfspopcon/formulas/plasma_profile_data/PRF/aLT.csv b/cfspopcon/formulas/plasma_profile_data/PRF/aLT.csv new file mode 100644 index 00000000..22672e3c --- /dev/null +++ b/cfspopcon/formulas/plasma_profile_data/PRF/aLT.csv @@ -0,0 +1,12 @@ +,,width,width,width,width,width,width,width,width,width,width +,,0,0.10555556,0.21111111,0.31666667,0.42222222,0.52777778,0.63333333,0.73888889,0.84444444,0.95 +peaking,1,-0.05069091,-0.05582754,-0.06176364,-0.06864038,-0.07662657,-0.08590871,-0.09666655,-0.1090216,-0.12294055,-0.13807588 +peaking,1.22222222,0.25014517,0.27424909,0.30241125,0.33536809,0.37396822,0.41910617,0.47157803,0.5318111,0.59941914,0.67257332 +peaking,1.44444444,0.51647618,0.56574693,0.62368044,0.69191175,0.772276,0.86662501,0.9764702,1.10238582,1.243156,1.39477072 +peaking,1.66666667,0.75227265,0.82363737,0.90825389,1.0087155,1.12785707,1.26841447,1.43241685,1.6202727,1.82964466,2.05439189 +peaking,1.88888889,0.96150508,1.05289181,1.16234156,1.29350424,1.45027173,1.63624119,1.8538249,2.1030419,2.38025976,2.67731241 +peaking,2.11111111,1.14814398,1.25848166,1.39215342,1.55400289,1.74908029,1.98187183,2.25510124,2.56826356,2.91637592,3.28940788 +peaking,2.33333333,1.31615985,1.44537832,1.60389941,1.79793635,2.03384305,2.31707304,2.65065277,3.03350782,3.45936777,3.91655387 +peaking,2.55555556,1.46952321,1.61855318,1.8037895,2.03302952,2.31412033,2.65361146,3.05488639,3.51634484,4.03060994,4.58462596 +peaking,2.77777778,1.61220457,1.78297764,1.99803364,2.26700733,2.59947242,3.00325374,3.482209,4.03434476,4.65147707,5.31949974 +peaking,3,1.74817444,1.94362311,2.19284179,2.50759466,2.89945963,3.37776654,3.94702751,4.60507774,5.34334378,6.1470508 diff --git a/cfspopcon/formulas/plasma_profile_data/PRF/metadata.yaml b/cfspopcon/formulas/plasma_profile_data/PRF/metadata.yaml new file mode 100644 index 00000000..1cef18a2 --- /dev/null +++ b/cfspopcon/formulas/plasma_profile_data/PRF/metadata.yaml @@ -0,0 +1,2 @@ +notes: "From Pablo Rodriguez-Fernandez, based on outputs from TRANSP." +documentation: "" diff --git a/cfspopcon/formulas/plasma_profile_data/PRF/width.csv b/cfspopcon/formulas/plasma_profile_data/PRF/width.csv new file mode 100644 index 00000000..dead5542 --- /dev/null +++ b/cfspopcon/formulas/plasma_profile_data/PRF/width.csv @@ -0,0 +1,12 @@ +,,aLT,aLT,aLT,aLT,aLT,aLT,aLT,aLT,aLT,aLT +,,1.0,1.33333333,1.66666667,2.0,2.33333333,2.66666667,3.0,3.33333333,3.66666667,4.0 +peaking,1.5,0.55525657,0.78965428,0.94114763,1.04129876,1.10808831,1.15259499,1.18196076,1.20093812,1.2127608,1.21966273 +peaking,1.66666667,0.30947926,0.57192988,0.75135627,0.87761883,0.96722366,1.03104933,1.07655831,1.10896602,1.13196415,1.14819024 +peaking,1.83333333,0.11214453,0.39602688,0.59122468,0.73461171,0.84095725,0.920017,0.9788843,1.02278864,1.05559384,1.08015795 +peaking,2.0,-0.06643852,0.25158105,0.45634084,0.61014671,0.72816489,0.81886394,0.88856167,0.9421717,0.98349881,1.01546521 +peaking,2.16666667,-0.2559608,0.12822814,0.34229274,0.50209313,0.62772236,0.72695611,0.80521335,0.86688094,0.91552797,0.95401137 +peaking,2.33333333,-0.4861132,0.01560391,0.24466838,0.40832025,0.53850546,0.64365945,0.72846229,0.79668207,0.85153022,0.89569578 +peaking,2.5,-0.78658663,-0.09665591,0.15905574,0.3266974,0.45938999,0.56833991,0.65793142,0.73134083,0.7913545,0.8404178 +peaking,2.66666667,-1.18707197,-0.21891553,0.08104281,0.25509385,0.38925174,0.50036343,0.59324367,0.67062294,0.7348497,0.78807679 +peaking,2.83333333,-1.71726012,-0.36153923,0.00621758,0.19137892,0.32696652,0.43909596,0.53402199,0.61429414,0.68186476,0.73857209 +peaking,3.0,-2.406842,-0.53489122,-0.06983196,0.1334219,0.27141011,0.38390344,0.47988931,0.56212015,0.63224858,0.69180306 diff --git a/cfspopcon/formulas/plasma_profile_data/__init__.py b/cfspopcon/formulas/plasma_profile_data/__init__.py new file mode 100644 index 00000000..3f9cfd28 --- /dev/null +++ b/cfspopcon/formulas/plasma_profile_data/__init__.py @@ -0,0 +1 @@ +"""1D plasma profiles based on TRANSP runs.""" diff --git a/cfspopcon/formulas/plasma_profile_data/density_and_temperature_profile_fits.py b/cfspopcon/formulas/plasma_profile_data/density_and_temperature_profile_fits.py new file mode 100644 index 00000000..fb75ba6b --- /dev/null +++ b/cfspopcon/formulas/plasma_profile_data/density_and_temperature_profile_fits.py @@ -0,0 +1,216 @@ +"""Realistic functional forms for T and n for POPCON analysis. + +private communication, P. Rodriguez-Fernandez (MIT PSFC), 2020 + +Description: + This functional form imposes: + 1) tanh pedestal for T and n. + 2) Linear aLT profile from 0 at rho=0 to X at rho=x_a, + where X is the specified core aLT value (default 2.0) + and x_a is calculated by matching specified temperature_peaking (peaking) + 3) Flat aLT profile from rho=x_a to rho=1-width_ped, where + width_ped is the pedestal width (default 0.05). + 4) T and n share the same x_a, and aLn is calculated by matching + specified nu_n (peaking) + 5) Pedestal is rescaled to match specified volume averages for + T and n. + +Notes: + - Not all combinations of aLT and temperature_peaking are valid. If aLT is too low, + temperature_peaking cannot be excessively high and viceversa. The code will not + crash, but will give profiles that do not match the specified + temperature peaking. + e.g. aLT = 2.0 requires temperature_peaking to be within [1.5,3.0] + + - It is not recommended to change width_ped from the default value, + since the Look-Up-Table hard-coded was computed using + width_ped=0.05 + + - If rho-grid is passed as argument, it is recommended to have equally + spaced 100 points. + +Example use: + + T_avol = 7.6 + n_avol = 3.1 + temperature_peaking = 2.5 + nu_n = 1.4 + + x, T, n = evaluate_density_and_temperature_profile_fits( T_avol, n_avol, temperature_peaking, nu_n, aLT = 2.0 ) + + Optionally: + - rho-grid can be passed (100 points recommended) + - Pedestal width can be passed (0.05 recommended) + +____________________________________________________________________ +""" # TODO: figure out valid regions of fits and print a warning when they are exceeded + +import warnings +from functools import cache +from pathlib import Path +from typing import Optional + +import numpy as np +import pandas as pd +import yaml +from numpy.typing import NDArray +from scipy.interpolate import RectBivariateSpline # type: ignore[import] + +plasma_profiles_directory = Path(__file__).parent + + +def load_dataframe(dataset: str, df_name: str) -> pd.DataFrame: + """Load specified dataframe for given dataset.""" + filepath = plasma_profiles_directory / dataset / f"{df_name}.csv" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + df = pd.read_csv(filepath, index_col=[0, 1], header=[0, 1]) + + return df + + +@cache +def get_df_interpolator(dataset: str, df_name: str) -> RectBivariateSpline: + """Return an interpolator for the given dataframe of the specified dataset.""" + df = load_dataframe(dataset, df_name) + interpolator = RectBivariateSpline( + [np.float64(x[1]) for x in df.columns.values], + [np.float64(x[1]) for x in df.index.values], + df.T.values, + ) + return interpolator + + +def evaluate_density_and_temperature_profile_fits( + T_avol: float, + n_avol: float, + temperature_peaking: float, + nu_n: float, + aLT: float = 2.0, + width_ped: float = 0.05, + rho: Optional[NDArray[np.float64]] = None, + dataset: str = "PRF", +) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]: # TODO: fill out docstring + """Evaluate temperature-density profile fits.""" + # ---- Get interpolator functions corresponding to this dataset + width_interpolator = get_df_interpolator(dataset=dataset, df_name="width") + aLT_interpolator = get_df_interpolator(dataset=dataset, df_name="aLT") + + # ---- Find parameters consistent with peaking + x_a = width_interpolator(aLT, temperature_peaking)[0] + aLn = aLT_interpolator(x_a, nu_n)[0] + + # ---- Evaluate profiles + x, T, _ = evaluate_profile(T_avol, width_ped=width_ped, aLT_core=aLT, width_axis=x_a, rho=rho) + x, n, _ = evaluate_profile(n_avol, width_ped=width_ped, aLT_core=aLn, width_axis=x_a, rho=rho) + + return x, T, n + + +def evaluate_profile( + Tavol: float, + aLT_core: float, + width_axis: float, + width_ped: float = 0.05, + rho: Optional[NDArray[np.float64]] = None, +) -> tuple[NDArray[np.float64], NDArray[np.float64], float]: + r"""This function generates a profile from :math:`\langle T \rangle`, aLT and :math:`x_a`. + + Example: + x, T, temperature_peaking = evaluate_profile(7.6, 2.0, 0.2) + """ + # ~~~~ Grid + if rho is None: + x = np.linspace(0, 1, 100) + else: + x = rho + + ix_c = np.argmin(np.abs(x - (1 - width_ped))) # Extend of core + ix_a = np.min([ix_c, np.argmin(np.abs(x - width_axis))]) # Extend of axis + + # ~~~~ aLT must be different from zero, adding non-rational small offset + aLT_core = aLT_core + np.pi * 1e-8 + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~ + # Functional Forms (normalized to pedestal temperature) + # ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # ~~~~ Pedestal + # Notes: + # - Because width_ped and Teped in my function represent the top values, I need to rescale them + # - The tanh does not result exactly in the top value (since it's an asymptote), so I need to correct for it + + wped_tanh = width_ped / 1.5 # The pedestal width in the tanh formula is 50% inside the pedestal-top width + Tedge_aux = 1 / 2 * (1 + np.tanh((1 - x - (wped_tanh / 2)) / (wped_tanh / 2))) + Tedge = Tedge_aux[int(ix_c) :] / Tedge_aux[ix_c] + + # ~~~~ Core + Tcore_aux = np.e ** (aLT_core * (1 - width_ped - x)) + Tcore = Tcore_aux[ix_a : int(ix_c)] + + # ~~~~ Axis + Taxis_aux = np.e ** (aLT_core * (-1 / 2 * x**2 / width_axis - 1 / 2 * width_axis + 1 - width_ped)) + Taxis = Taxis_aux[:ix_a] + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~ + # Analytical Integral ("pre-factor") + # ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # Pedestal contribution (solved with Matematica) + I1 = -0.0277778 * width_ped * (-23.3473 + 14.6132 * width_ped) + + # Core and axis contributions + I23 = ( + 1 + / aLT_core**2 + * ( + (width_axis * aLT_core * np.e ** (width_axis * aLT_core / 2) + 1) * np.e ** (-aLT_core * (width_axis + width_ped - 1)) + + aLT_core * width_ped + - aLT_core + - 1 + ) + ) + + # Total (this is the factor that relates Teped to Tavol) + I = 2 * (I1 + I23) # noqa: E741 + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~ + # Evaluation of the profile + # ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Teped = Tavol / I + T: NDArray[np.float64] = Teped * np.hstack((Taxis, Tcore, Tedge)).ravel() + if np.isclose(Tavol, 0.0) and np.isclose(T[0], 0.0): + peaking = 0.0 + else: + peaking = float(T[0] / Tavol) + + return x, T, peaking + + +def load_metadata(dataset: str) -> dict[str, str]: + r"""Load dataset metadata from YAML file. + + Args: + dataset: name of subfolder that holds metadata.yaml + + Returns: + metadata + """ + filepath = plasma_profiles_directory / dataset / "metadata.yaml" + with open(filepath) as f: + metadata: dict[str, str] = yaml.safe_load(f) + return metadata + + +def get_datasets() -> list[str]: + """Get a list of names of valid datasets. + + Every immediate subdirectory of the source folder represents a dataset + + Returns: + [str]*N, list of names of valid datasets + """ + datasets = [f.name for f in plasma_profiles_directory.iterdir() if (f.is_dir() and not f.name.startswith("_"))] + + return datasets diff --git a/cfspopcon/formulas/plasma_profiles.py b/cfspopcon/formulas/plasma_profiles.py new file mode 100644 index 00000000..ddb89e8f --- /dev/null +++ b/cfspopcon/formulas/plasma_profiles.py @@ -0,0 +1,186 @@ +"""Estimate 1D plasma profiles of density and temperature.""" + +from typing import Optional + +import numpy as np +from numpy import float64 +from numpy.typing import NDArray + +from ..named_options import ProfileForm +from ..unit_handling import ureg, wraps_ufunc +from .plasma_profile_data.density_and_temperature_profile_fits import evaluate_density_and_temperature_profile_fits + + +@wraps_ufunc( + return_units=dict( + rho=ureg.dimensionless, + electron_density_profile=ureg.n19, + fuel_ion_density_profile=ureg.n19, + electron_temp_profile=ureg.keV, + ion_temp_profile=ureg.keV, + ), + input_units=dict( + profile_form=None, + average_electron_density=ureg.n19, + average_electron_temp=ureg.keV, + average_ion_temp=ureg.keV, + electron_density_peaking=ureg.dimensionless, + ion_density_peaking=ureg.dimensionless, + temperature_peaking=ureg.dimensionless, + dilution=ureg.dimensionless, + normalized_inverse_temp_scale_length=ureg.dimensionless, + npoints=None, + ), + output_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), ("dim_rho",), ("dim_rho",)], +) +def calc_1D_plasma_profiles( + profile_form: ProfileForm, + average_electron_density: float, + average_electron_temp: float, + average_ion_temp: float, + electron_density_peaking: float, + ion_density_peaking: float, + temperature_peaking: float, + dilution: float, + normalized_inverse_temp_scale_length: Optional[float] = None, + npoints: int = 50, +) -> tuple[NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64]]: + """Estimate density and temperature profiles. + + Args: + profile_form: select between analytic fit or profiles from Pablo Rodriguez-Fernandez + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + electron_density_peaking: [~] :term:`glossary link` + ion_density_peaking: [~] :term:`glossary link` + temperature_peaking: [~] :term:`glossary link` + dilution: dilution of main ions [~] + normalized_inverse_temp_scale_length: [~] :term:`glossary link` + npoints: number of points to return in profile + + Returns: + :term:`rho` [~], :term:`electron_density_profile` [1e19 m^-3], fuel_ion_density_profile [1e19 m^-3], :term:`electron_temp_profile` [keV], :term:`ion_temp_profile` [keV] + + Raises: + ValueError: if profile_form == prf and normalized_inverse_temp_scale_length is not set + """ + if profile_form == ProfileForm.analytic: + rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile = calc_analytic_profiles( + average_electron_density, + average_electron_temp, + average_ion_temp, + electron_density_peaking, + ion_density_peaking, + temperature_peaking, + dilution, + npoints=npoints, + ) + + elif profile_form == ProfileForm.prf: + if normalized_inverse_temp_scale_length is None: + raise ValueError("normalized_inverse_temp_scale_length must be set if using profile_form = prf") + + rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile = calc_prf_profiles( + average_electron_density, + average_electron_temp, + average_ion_temp, + electron_density_peaking, + ion_density_peaking, + temperature_peaking, + dilution, + normalized_inverse_temp_scale_length, + npoints=npoints, + ) + + return rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile + + +def calc_analytic_profiles( + average_electron_density: float, + average_electron_temp: float, + average_ion_temp: float, + electron_density_peaking: float, + ion_density_peaking: float, + temperature_peaking: float, + dilution: float, + npoints: int = 50, +) -> tuple[NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64]]: + """Estimate density and temperature profiles using a simple analytic fit. + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + electron_density_peaking: [~] :term:`glossary link` + ion_density_peaking: [~] :term:`glossary link` + temperature_peaking: [~] :term:`glossary link` + dilution: dilution of main ions [~] + npoints: number of points to return in profile + + Returns: + :term:`rho` [~], :term:`electron_density_profile` [1e19 m^-3], fuel_ion_density_profile [1e19 m^-3], :term:`electron_temp_profile` [keV], :term:`ion_temp_profile` [keV] + """ + rho = np.linspace(0, 1, num=npoints, endpoint=False) + + electron_density_profile = ( + average_electron_density * electron_density_peaking * ((1.0 - rho**2.0) ** (electron_density_peaking - 1.0)) + ) + fuel_ion_density_profile = ( + average_electron_density * dilution * (ion_density_peaking) * ((1.0 - rho**2.0) ** (ion_density_peaking - 1.0)) + ) + electron_temp_profile = average_electron_temp * temperature_peaking * ((1.0 - rho**2.0) ** (temperature_peaking - 1.0)) + ion_temp_profile = average_ion_temp * temperature_peaking * ((1.0 - rho**2.0) ** (temperature_peaking - 1.0)) + + return rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile + + +def calc_prf_profiles( + average_electron_density: float, + average_electron_temp: float, + average_ion_temp: float, + electron_density_peaking: float, + ion_density_peaking: float, + temperature_peaking: float, + dilution: float, + normalized_inverse_temp_scale_length: float, + npoints: int = 50, +) -> tuple[NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64], NDArray[float64]]: + """Estimate density and temperature profiles using profiles from Pablo Rodriguez-Fernandez. + + Args: + average_electron_density: [1e19 m^-3] :term:`glossary link` + average_electron_temp: [keV] :term:`glossary link` + average_ion_temp: [keV] :term:`glossary link` + electron_density_peaking: [~] :term:`glossary link` + ion_density_peaking: [~] :term:`glossary link` + temperature_peaking: [~] :term:`glossary link` + dilution: dilution of main ions [~] + normalized_inverse_temp_scale_length: [~] :term:`glossary link` + npoints: number of points to return in profile + + Returns: + :term:`rho` [~], :term:`electron_density_profile` [1e19 m^-3], fuel_ion_density_profile [1e19 m^-3], :term:`electron_temp_profile` [keV], :term:`ion_temp_profile` [keV] + """ + rho = np.linspace(0, 1, num=npoints, endpoint=False) + + rho, electron_temp_profile, electron_density_profile = evaluate_density_and_temperature_profile_fits( + average_electron_temp, + average_electron_density, + temperature_peaking, + electron_density_peaking, + aLT=normalized_inverse_temp_scale_length, + rho=rho, + dataset="PRF", + ) + rho, ion_temp_profile, fuel_ion_density_profile = evaluate_density_and_temperature_profile_fits( + average_ion_temp, + average_electron_density * dilution, + temperature_peaking, + ion_density_peaking, + aLT=normalized_inverse_temp_scale_length, + rho=rho, + dataset="PRF", + ) + + return rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile diff --git a/cfspopcon/formulas/radiated_power/__init__.py b/cfspopcon/formulas/radiated_power/__init__.py new file mode 100644 index 00000000..20ab0c1f --- /dev/null +++ b/cfspopcon/formulas/radiated_power/__init__.py @@ -0,0 +1,17 @@ +"""Calculate the radiated power due to fuel and impurity species.""" +from .inherent import calc_bremsstrahlung_radiation, calc_synchrotron_radiation +from .mavrin_coronal import calc_impurity_radiated_power_mavrin_coronal +from .mavrin_noncoronal import calc_impurity_radiated_power_mavrin_noncoronal +from .post_and_jensen import calc_impurity_radiated_power_post_and_jensen +from .radas import calc_impurity_radiated_power_radas +from .radiated_power import calc_impurity_radiated_power + +__all__ = [ + "calc_bremsstrahlung_radiation", + "calc_synchrotron_radiation", + "calc_impurity_radiated_power_mavrin_coronal", + "calc_impurity_radiated_power_mavrin_noncoronal", + "calc_impurity_radiated_power_post_and_jensen", + "calc_impurity_radiated_power_radas", + "calc_impurity_radiated_power", +] diff --git a/cfspopcon/formulas/radiated_power/inherent.py b/cfspopcon/formulas/radiated_power/inherent.py new file mode 100644 index 00000000..0313334d --- /dev/null +++ b/cfspopcon/formulas/radiated_power/inherent.py @@ -0,0 +1,141 @@ +"""Calculate the inherent (Bremsstrahlung and Synchrotron) radiated power.""" + +import numpy as np +from numpy import float64 +from numpy.typing import NDArray + +from ...unit_handling import ureg, wraps_ufunc +from ..helpers import integrate_profile_over_volume + + +@wraps_ufunc( + return_units=dict(P_rad_bremsstrahlung=ureg.MW), + input_units=dict( + rho=ureg.dimensionless, + electron_density_profile=ureg.n19, + electron_temp_profile=ureg.keV, + z_effective=ureg.dimensionless, + plasma_volume=ureg.m**3, + ), + input_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), (), ()], +) +def calc_bremsstrahlung_radiation( + rho: NDArray[float64], + electron_density_profile: NDArray[float64], + electron_temp_profile: NDArray[float64], + z_effective: float, + plasma_volume: float, +) -> float: + """Calculate the Bremsstrahlung radiated power due to the main plasma. + + Formula 13 in :cite:`stott_feasibility_2005` + + Args: + electron_density_profile: [1e19 m^-3] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + z_effective: [~] :term:`glossary link` + rho: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + Radiated bremsstrahlung power per cubic meter [MW / m^3] + """ + ne20 = electron_density_profile / 10 + + Tm = 511.0 # keV, Tm = m_e * c**2 + xrel = (1.0 + 2.0 * electron_temp_profile / Tm) * ( + 1.0 + (2.0 / z_effective) * (1.0 - 1.0 / (1.0 + electron_temp_profile / Tm)) + ) # relativistic correction factor + + fKb = ne20**2 * np.sqrt(electron_temp_profile) * xrel + Kb = integrate_profile_over_volume(fKb, rho, plasma_volume) # radial profile factor + + P_brem = 5.35e-3 * z_effective * Kb # volume-averaged bremsstrahlung radiaton in MW + + return P_brem + + +@wraps_ufunc( + return_units=dict(P_rad_synchrotron=ureg.MW), + input_units=dict( + rho=ureg.dimensionless, + electron_density_profile=ureg.n19, + electron_temp_profile=ureg.keV, + major_radius=ureg.m, + minor_radius=ureg.m, + magnetic_field_on_axis=ureg.T, + separatrix_elongation=ureg.dimensionless, + plasma_volume=ureg.m**3, + ), + input_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), (), (), (), (), ()], +) +def calc_synchrotron_radiation( + rho: NDArray[float64], + electron_density_profile: NDArray[float64], + electron_temp_profile: NDArray[float64], + major_radius: float, + minor_radius: float, + magnetic_field_on_axis: float, + separatrix_elongation: float, + plasma_volume: float, +) -> float: + """Calculate the Synchrotron radiated power due to the main plasma. + + This can be an important loss mechanism in high temperature plasmas. + + Formula 15 in :cite:`stott_feasibility_2005` + + For now this calculation assumes 90% wall reflectivity, consistent with stott_feasibility_2005. + + This calculation also assumes profiles of the form n(r) = n[1 - (r/a)**2]**alpha_n and + T(r) = Tedge + (T - Tedge)[1 - (r/a)**gamma_T]**alpha_T. For now, these are assumed as + gamma_T = 2, alpha_n = 0.5 and alpha_T = 1, consistent with stott_feasibility_2005. + + An alternative approach could be developed using formula 6 in :cite:`zohm_use_2019`, which assumes 80% wall reflectivity. + + Args: + electron_density_profile: [1e19 m^-3] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + major_radius: [m] :term:`glossary link` + minor_radius: [m] :term:`glossary link` + magnetic_field_on_axis: [T] :term:`glossary link` + separatrix_elongation: [~] :term:`glossary link` + rho: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + Radiated bremsstrahlung power per cubic meter [MW / m^3] + """ + ne20 = electron_density_profile / 10 + + Rw = 0.8 # wall reflectivity + gamma_T = 2 # temperature profile inner exponent (2 is ~parabolic) + alpha_n = 0.5 # density profile outer exponent (0.5 is rather broad) + alpha_T = 1 # temperature profile outer exponent (1 is ~parabolic) + + # effective optical thickness + rhoa = 6.04e3 * minor_radius * ne20 / magnetic_field_on_axis + # profile peaking correction + Ks = ( + (alpha_n + 3.87 * alpha_T + 1.46) ** (-0.79) + * (1.98 + alpha_n) ** (1.36) + * gamma_T**2.14 + * (gamma_T**1.53 + 1.87 * alpha_T - 0.16) ** (-1.33) + ) + # aspect ratio correction + Gs = 0.93 * (1 + 0.85 * np.exp(-0.82 * major_radius / minor_radius)) + + # dimensionless parameter to account for plasma transparency and wall reflections + Phi = ( + 6.86e-5 + * separatrix_elongation ** (-0.21) + * (16 + electron_temp_profile) ** (2.61) + * ((rhoa / (1 - Rw)) ** (0.41) + 0.12 * electron_temp_profile) ** (-1.51) + * Ks + * Gs + ) + + P_sync_r = 6.25e-3 * ne20 * electron_temp_profile * magnetic_field_on_axis**2 * Phi + P_sync = integrate_profile_over_volume(P_sync_r, rho, plasma_volume) + + return P_sync diff --git a/cfspopcon/formulas/radiated_power/mavrin_coronal.py b/cfspopcon/formulas/radiated_power/mavrin_coronal.py new file mode 100644 index 00000000..88e8689d --- /dev/null +++ b/cfspopcon/formulas/radiated_power/mavrin_coronal.py @@ -0,0 +1,192 @@ +"""Calculate the radiated power due to impurities, according to an analytical fitted curve from Mavrin 2018.""" + +import warnings + +import numpy as np +from numpy import float64 +from numpy.polynomial.polynomial import polyval +from numpy.typing import NDArray + +from ...named_options import Impurity +from ...unit_handling import ureg, wraps_ufunc +from ..helpers import integrate_profile_over_volume + + +@wraps_ufunc( + return_units=dict(radiated_power=ureg.MW), + input_units=dict( + rho=ureg.dimensionless, + electron_temp_profile=ureg.keV, + electron_density_profile=ureg.n19, + impurity_concentration=ureg.dimensionless, + impurity_species=None, + plasma_volume=ureg.m**3, + ), + input_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), (), (), ()], +) +def calc_impurity_radiated_power_mavrin_coronal( # noqa: PLR0912, PLR0915 + rho: NDArray[float64], + electron_temp_profile: NDArray[float64], + electron_density_profile: NDArray[float64], + impurity_concentration: float, + impurity_species: Impurity, + plasma_volume: float, +) -> float: + """Calculation of radiated power, using fits from A.A. Mavrin's 2018 paper. + + "Improved fits of coronal radiative cooling rates for high-temperature plasmas." + + :cite:`mavrin_improved_2018` + + Args: + rho: [~] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + electron_density_profile: [1e19 m^-3] :term:`glossary link` + impurity_species: [] :term:`glossary link` + impurity_concentration: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + k [MW] Estimated radiation power due to this impurity + """ + impurity_Z = impurity_species.value + + zimp = np.array([2, 3, 4, 6, 7, 8, 10, 18, 36, 54, 74]) + + if impurity_Z not in zimp: # pragma: no cover + warnings.warn(f"Mavrin 2018 line radiation calculation not supported for impurity with Z={impurity_Z}", stacklevel=3) + return np.nan + + # If trying to evaluate for a temperature outside of the given range, assume nearest neighbor + # and throw a warning + if any(electron_density_profile < 0.1) or any(electron_density_profile > 100): # pragma: no cover + warnings.warn( + "Mavrin 2018 line radiation calculation is only valid between 0.1-100keV. Using nearest neighbor extrapolation.", stacklevel=3 + ) + electron_density_profile = np.maximum(electron_density_profile, 0.1) + electron_density_profile = np.minimum(electron_density_profile, 100) + + # L_z coefficients for the 11 supported impurities + if impurity_Z == 2: # Helium + temperature_bin_borders = np.array([0.0, 100.0]) + radc = np.array( + [ + [-3.5551e01, 3.1469e-01, 1.0156e-01, -9.3730e-02, 2.5020e-02], + ] + ) + + elif impurity_Z == 3: # Lithium + temperature_bin_borders = np.array([0.0, 100.0]) + radc = np.array( + [ + [-3.5115e01, 1.9475e-01, 2.5082e-01, -1.6070e-01, 3.5190e-02], + ] + ) + + elif impurity_Z == 4: # Beryllium + temperature_bin_borders = np.array([0.0, 100.0]) + radc = np.array( + [ + [-3.4765e01, 3.7270e-02, 3.8363e-01, -2.1384e-01, 4.1690e-02], + ] + ) + + elif impurity_Z == 6: # Carbon + temperature_bin_borders = np.array([0.0, 0.5, 100.0]) + radc = np.array( + [ + [-3.4738e01, -5.0085e00, -1.2788e01, -1.6637e01, -7.2904e00], + [-3.4174e01, -3.6687e-01, 6.8856e-01, -2.9191e-01, 4.4470e-02], + ] + ) + + elif impurity_Z == 7: # Nitrogen + temperature_bin_borders = np.array([0.0, 0.5, 2.0, 100.0]) + radc = np.array( + [ + [-3.4065e01, -2.3614e00, -6.0605e00, -1.1570e01, -6.9621e00], + [-3.3899e01, -5.9668e-01, 7.6272e-01, -1.7160e-01, 5.8770e-02], + [-3.3913e01, -5.2628e-01, 7.0047e-01, -2.2790e-01, 2.8350e-02], + ] + ) + + elif impurity_Z == 8: # Oxygen + temperature_bin_borders = np.array([0.0, 0.3, 100.0]) + radc = np.array( + [ + [-3.7257e01, -1.5635e01, -1.7141e01, -5.3765e00, 0.0000e00], + [-3.3640e01, -7.6211e-01, 7.9655e-01, -2.0850e-01, 1.4360e-02], + ] + ) + + elif impurity_Z == 10: # Neon + temperature_bin_borders = np.array([0.0, 0.7, 5, 100.0]) + radc = np.array( + [ + [-3.3132e01, 1.7309e00, 1.5230e01, 2.8939e01, 1.5648e01], + [-3.3290e01, -8.7750e-01, 8.6842e-01, -3.9544e-01, 1.7244e-01], + [-3.3410e01, -4.5345e-01, 2.9731e-01, 4.3960e-02, -2.6930e-02], + ] + ) + + elif impurity_Z == 18: # Argon + temperature_bin_borders = np.array([0.0, 0.6, 3, 100.0]) + radc = np.array( + [ + [-3.2155e01, 6.5221e00, 3.0769e01, 3.9161e01, 1.5353e01], + [-3.2530e01, 5.4490e-01, 1.5389e00, -7.6887e00, 4.9806e00], + [-3.1853e01, -1.6674e00, 6.1339e-01, 1.7480e-01, -8.2260e-02], + ] + ) + + elif impurity_Z == 36: # Krypton + temperature_bin_borders = np.array([0.0, 0.447, 2.364, 100.0]) + radc = np.array( + [ + [-3.4512e01, -2.1484e01, -4.4723e01, -4.0133e01, -1.3564e01], + [-3.1399e01, -5.0091e-01, 1.9148e00, -2.5865e00, -5.2704e00], + [-2.9954e01, -6.3683e00, 6.6831e00, -2.9674e00, 4.8356e-01], + ] + ) + + elif impurity_Z == 54: # Xenon + temperature_bin_borders = np.array([0.0, 0.5, 2.5, 10, 100.0]) + radc = np.array( + [ + [-2.9303e01, 1.4351e01, 4.7081e01, 5.9580e01, 2.5615e01], + [-3.1113e01, 5.9339e-01, 1.2808e00, -1.1628e01, 1.0748e01], + [-2.5813e01, -2.7526e01, 4.8614e01, -3.6885e01, 1.0069e01], + [-2.2138e01, -2.2592e01, 1.9619e01, -7.5181e00, 1.0858e00], + ] + ) + + elif impurity_Z == 74: # Tungsten + temperature_bin_borders = np.array([0.0, 1.5, 4, 100.0]) + radc = np.array( + [ + [-3.0374e01, 3.8304e-01, -9.5126e-01, -1.0311e00, -1.0103e-01], + [-3.0238e01, -2.9208e00, 2.2824e01, -6.3303e01, 5.1849e01], + [-3.2153e01, 5.2499e00, -6.2740e00, 2.6627e00, -3.6759e-01], + ] + ) + + # solve for radiated power + + Tlog = np.log10(electron_density_profile) + log10_Lz = np.zeros(electron_density_profile.size) + + for i in range(len(radc)): + it = np.nonzero( + (electron_density_profile >= temperature_bin_borders[i]) & (electron_density_profile < temperature_bin_borders[i + 1]) + )[0] + if it.size > 0: + log10_Lz[it] = polyval(Tlog[it], radc[i]) # type: ignore[no-untyped-call] + + radrate = 10.0**log10_Lz + radrate[np.isnan(radrate)] = 0 + + # 1e38 factor to account for the fact that our n_e values are electron_density_profile values + qRad = radrate * electron_temp_profile * electron_temp_profile * impurity_concentration * 1e38 # W / (m^3 s) + radiated_power = integrate_profile_over_volume(qRad, rho, plasma_volume) # [W] + + return float(radiated_power) / 1e6 # MW diff --git a/cfspopcon/formulas/radiated_power/mavrin_noncoronal.py b/cfspopcon/formulas/radiated_power/mavrin_noncoronal.py new file mode 100644 index 00000000..cc1f6df9 --- /dev/null +++ b/cfspopcon/formulas/radiated_power/mavrin_noncoronal.py @@ -0,0 +1,251 @@ +"""Calculate the radiated power due to impurities, according to an analytical fitted curve from Mavrin 2017.""" + +import warnings + +import numpy as np +from numpy import float64 +from numpy.typing import NDArray + +from ...named_options import Impurity +from ...unit_handling import Quantity, ureg, wraps_ufunc +from ..helpers import integrate_profile_over_volume + + +@wraps_ufunc( + return_units=dict(radiated_power=ureg.MW), + input_units=dict( + rho=ureg.dimensionless, + electron_temp_profile=ureg.keV, + electron_density_profile=ureg.n19, + tau_i=ureg.s, + impurity_concentration=ureg.dimensionless, + impurity_species=None, + plasma_volume=ureg.m**3, + ), + input_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), (), (), (), ()], +) +def calc_impurity_radiated_power_mavrin_noncoronal( # noqa: PLR0912 + rho: NDArray[float64], + electron_temp_profile: NDArray[float64], + electron_density_profile: NDArray[float64], + tau_i: Quantity, + impurity_concentration: float, + impurity_species: Impurity, + plasma_volume: float, +) -> float: + """Calculation of radiated power, using fits from A.A. Mavrin's 2017 paper. + + "Radiative Cooling Rates for Low-Z Impurities in Non-coronal Equilibrium State." + + :cite:`mavrin_radiative_2017` + + Args: + rho: [~] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + electron_density_profile: [1e19 m^-3] :term:`glossary link` + tau_i: [s] :term:`glossary link` + impurity_concentration: [~] :term:`glossary link` + impurity_species: [] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + [MW] Estimated radiation power due to this impurity + """ + impurity_Z = impurity_species.value + + # He, Li, Be, C, N, O, Ne, Ar + zimp = np.array([2, 3, 4, 6, 7, 8, 10, 18]) + + if impurity_Z not in zimp: # pragma: no cover + warnings.warn(f"Mavrin 2017 line radiation calculation not supported for impurity with Z={impurity_Z}", stacklevel=3) + return np.nan + + # L_z coefficients for the 11 supported impurities + if impurity_Z == 2: # Helium + temperature_bin_borders = np.array([1.0, 3.0, 10.0, 30.0, 100.0, 15000.0]) + radc = np.array( + [ + [-3.9341e01, -2.7185e01, -3.4950e01, -3.1299e01, -3.3203e01], + [2.2742e01, -3.4465e01, 5.5957e00, -4.4749e00, -2.3306e00], + [-8.5940e-02, 3.2223e-01, 2.1542e00, 2.9614e-01, -5.3911e-01], + [-2.5420e01, 5.0933e01, -7.4762e00, 1.5259e00, 7.2592e-01], + [1.8843e00, 1.0589e-01, -3.7391e00, -6.1433e-01, 9.7550e-02], + [-3.5681e-01, 1.1632e-01, 1.4444e-01, 3.2651e-01, 2.6917e-01], + [-3.2771e00, -2.3641e01, 2.4534e00, -1.6652e-01, -6.6110e-02], + [-4.9766e00, -7.4782e-01, 1.5000e00, 1.5704e-01, 8.9900e-03], + [1.9730e-02, -7.6200e-03, 2.1307e-01, -8.0601e-04, 2.9240e-02], + [-7.4260e-02, 2.1030e-02, 7.6590e-02, 5.0330e-02, 5.1180e-02], + ] + ) + + elif impurity_Z == 3: # Lithium + temperature_bin_borders = np.array([1.0, 7.0, 30.0, 60.0, 100.0, 1000.0, 10000.0]) + radc = np.array( + [ + [-3.5752e01, -3.1170e01, -3.6558e01, -3.0560e01, -3.0040e01, -3.4199e01], + [-1.6780e00, -1.6918e01, 9.4272e00, -2.4680e00, -4.2963e00, -8.5686e-01], + [9.5500e-03, 1.1481e-01, 3.5299e00, 1.7912e00, 2.7407e-01, -6.3246e-01], + [-6.1560e00, 2.0492e01, -8.1056e00, -2.8659e-01, 1.1569e00, 2.4968e-01], + [-1.5027e00, 2.6136e-01, -4.4113e00, -1.9929e00, -4.5453e-01, 9.9930e-02], + [2.5568e-01, 2.4870e-01, 5.1430e-02, 2.8150e-01, 3.0616e-01, 2.5080e-01], + [1.1009e01, -7.0035e00, 1.9427e00, 2.3898e-01, -9.1510e-02, -1.7230e-02], + [2.1169e00, -3.3910e-01, 1.3459e00, 5.0412e-01, 9.7550e-02, 1.4410e-02], + [-9.6420e-02, -3.5570e-02, 2.3865e-01, 5.8550e-02, 1.6540e-02, 3.7030e-02], + [1.3460e-02, 4.1910e-02, 8.6850e-02, 6.7410e-02, 5.4690e-02, 5.5670e-02], + ] + ) + + elif impurity_Z == 4: # Beryllium + temperature_bin_borders = np.array([0.2, 0.7, 3.0, 11.0, 45.0, 170.0, 10000.0]) + radc = np.array( + [ + [-3.0242e01, -3.2152e01, -3.0169e01, -3.7201e01, -4.0868e01, -2.8539e01], + [2.1405e01, 3.1572e00, -8.9830e00, -2.5643e00, 1.4625e01, -5.0020e00], + [1.0117e-01, 1.4168e-01, 6.3656e-01, -4.0467e00, 3.3373e00, 3.1089e-01], + [2.7450e01, -1.4617e01, 4.5232e00, 7.1732e00, -8.8128e00, 1.3149e00], + [8.8367e-01, 1.4646e-01, -1.5126e00, 5.8147e00, -3.1064e00, -4.0022e-01], + [-6.6110e-02, 1.4683e-01, 4.0756e-01, 4.0114e-01, 2.4343e-01, 3.1788e-01], + [3.0202e01, 4.3653e00, -3.7497e-01, -2.5926e00, 1.5996e00, -1.0780e-01], + [1.2175e00, -1.1290e00, 7.2552e-01, -2.0708e00, 6.8069e-01, 7.3280e-02], + [-1.4883e-01, 3.4914e-01, -2.9810e-02, -1.4775e-01, 6.0120e-02, 1.7320e-02], + [4.8900e-03, 4.1730e-02, 5.5620e-02, 2.1900e-02, 6.8350e-02, 6.1360e-02], + ] + ) + + elif impurity_Z == 6: # Carbon + temperature_bin_borders = np.array([1.0, 7.0, 20.0, 70.0, 200.0, 700.0, 15000.0]) + radc = np.array( + [ + [-3.4509e01, -4.9228e01, -1.9100e01, -6.7743e01, -2.4016e01, -2.8126e01], + [6.7599e00, 5.3922e01, -1.5476e01, 4.1606e01, -7.3974e00, -4.1679e00], + [-1.7140e-02, 8.4584e-01, 4.2962e00, -5.3665e00, 2.9707e00, 4.9937e-01], + [-4.0337e00, -5.1128e01, 2.1893e00, -1.5734e01, 1.6859e00, 9.0578e-01], + [1.5517e-01, -8.9366e-01, -6.1658e00, 6.1760e00, -2.1965e00, -5.3687e-01], + [2.1110e-02, -2.2710e-02, 1.6098e-01, 7.8010e-01, 3.0521e-01, 2.5962e-01], + [6.5977e-01, 1.4758e01, 1.1021e00, 1.7905e00, -1.1147e-01, -5.8310e-02], + [-1.7392e-01, 1.6371e-01, 2.1568e00, -1.7320e00, 3.8653e-01, 1.0420e-01], + [-2.9270e-02, 2.9362e-01, 1.1101e-01, -2.7897e-01, 3.8970e-02, 4.6610e-02], + [1.7600e-03, 5.5880e-02, 4.2700e-02, 2.3450e-02, 7.8690e-02, 7.3950e-02], + ] + ) + + elif impurity_Z == 7: # Nitrogen + temperature_bin_borders = np.array([1.0, 10.0, 30.0, 100.0, 300.0, 1000.0, 15000.0]) + radc = np.array( + [ + [-3.5312e01, -5.8692e01, -2.0301e01, -7.7571e01, -2.9401e01, -2.7201e01], + [7.1926e00, 6.8148e01, -8.8594e00, 5.0488e01, -3.8191e-01, -4.4640e00], + [7.8200e-03, 3.6209e-01, 6.0500e00, -6.5889e00, 3.5270e00, 7.6960e-01], + [-3.5696e00, -5.4257e01, -2.7129e00, -1.8187e01, -1.0347e00, 9.2450e-01], + [-1.2800e-02, 1.4835e-01, -7.6700e00, 6.8691e00, -2.4192e00, -6.7720e-01], + [1.1180e-02, -1.4700e-03, 1.0705e-01, 8.3119e-01, 3.2269e-01, 2.6185e-01], + [3.5812e-01, 1.3476e01, 1.9691e00, 2.0259e00, 2.2501e-01, -5.6280e-02], + [-2.5100e-03, -2.9646e-01, 2.3943e00, -1.7572e00, 3.9511e-01, 1.2014e-01], + [-2.2020e-02, 2.2706e-01, 1.4088e-01, -2.9376e-01, 2.6510e-02, 4.6870e-02], + [-1.0000e-03, 5.4220e-02, 4.7450e-02, 1.7200e-02, 7.8930e-02, 7.9250e-02], + ] + ) + + elif impurity_Z == 8: # Oxygen + temperature_bin_borders = np.array([1.0, 10.0, 30.0, 100.0, 300.0, 1000.0, 15000.0]) + radc = np.array( + [ + [-3.6208e01, -2.9057e01, -2.9370e01, -4.4120e-02, -3.7073e01, -2.5037e01], + [7.5487e00, -1.5228e01, 8.7451e00, -5.4918e01, 7.8826e00, -5.7568e00], + [2.3340e-02, -3.1460e00, 6.3827e00, -9.5003e00, 3.7999e00, 1.2973e00], + [-2.1983e00, 2.0826e01, -1.2357e01, 2.8883e01, -3.8006e00, 1.2040e00], + [-1.0131e-01, 5.9427e00, -7.6451e00, 8.5536e00, -2.2619e00, -9.1955e-01], + [8.0600e-03, 1.0610e-01, -2.2230e-02, 5.5336e-01, 5.0270e-01, 2.8988e-01], + [-6.5108e-01, -8.0843e00, 3.4958e00, -4.8731e00, 5.2144e-01, -7.6780e-02], + [8.4570e-02, -2.6827e00, 2.2661e00, -1.9172e00, 3.0219e-01, 1.4568e-01], + [-2.1710e-02, 1.0350e-02, 2.5727e-01, -1.5709e-01, -6.6330e-02, 3.9250e-02], + [-2.1200e-03, 2.6480e-02, 7.7800e-02, 1.6370e-02, 6.1140e-02, 8.3010e-02], + ] + ) + + elif impurity_Z == 10: # Neon + temperature_bin_borders = np.array([1.0, 10.0, 70.0, 300.0, 1000.0, 3000.0, 15000.0]) + radc = np.array( + [ + [-3.8610e01, -3.6822e01, -6.6901e00, -1.1261e02, -2.6330e02, -1.1174e02], + [1.2606e01, 4.9706e00, -2.4212e01, 8.5765e01, 2.1673e02, 6.1907e01], + [1.7866e-01, -1.5334e00, 7.3589e00, -2.1093e00, 1.2973e00, 4.7967e00], + [-1.0213e01, 1.1973e00, 5.7352e00, -3.0372e01, -6.7799e01, -1.6289e01], + [-7.7051e-01, 2.7279e00, -7.4602e00, 2.2928e00, -7.3310e-01, -2.5731e00], + [2.7510e-02, 9.0090e-02, -7.9030e-02, 7.7055e-01, 4.4883e-01, 4.2620e-01], + [4.3390e00, -1.3992e00, -8.5020e-02, 3.5346e00, 7.0398e00, 1.4263e00], + [6.4207e-01, -1.1084e00, 1.8679e00, -5.6062e-01, 9.3190e-02, 3.3443e-01], + [-3.3560e-02, 1.3620e-02, 2.2507e-01, -1.8569e-01, -1.5390e-02, -9.3734e-04], + [-1.3333e-04, 2.4300e-02, 7.1420e-02, 3.7550e-02, 7.7660e-02, 8.4220e-02], + ] + ) + + elif impurity_Z == 18: # Argon + temperature_bin_borders = np.array([1.0, 10.0, 50.0, 150.0, 500.0, 1500.0, 10000.0]) + radc = np.array( + [ + [-3.6586e01, -4.8732e01, -2.3157e01, -6.8134e01, 5.5851e01, -6.2758e01], + [1.2841e01, 3.8185e01, -8.5132e00, 3.6408e01, -7.8618e01, 2.5163e01], + [2.3080e-02, -7.0622e-01, 1.5617e00, -7.3868e00, 1.0520e01, -7.4717e-01], + [-1.2087e01, -2.5859e01, 1.5478e00, -1.0735e01, 2.2871e01, -6.8170e00], + [-9.8000e-03, 1.2850e00, -1.8880e00, 6.8800e00, -7.7061e00, 6.9486e-01], + [-2.4600e-03, -6.8710e-02, 2.2830e-01, 3.1142e-01, -1.8530e-01, 4.6946e-01], + [4.8823e00, 5.4372e00, 2.8279e-01, 8.0440e-01, -2.1616e00, 5.9969e-01], + [-3.7470e-02, -5.2157e-01, 5.5767e-01, -1.5740e00, 1.4123e00, -1.3487e-01], + [1.1100e-03, 1.4016e-01, -9.9600e-02, -9.9180e-02, 1.8409e-01, -8.1380e-02], + [1.1100e-03, 1.9120e-02, -1.5280e-02, 9.4500e-03, 6.7470e-02, 2.5840e-02], + ] + ) + else: + raise RuntimeError("This should never happen, please ensure all impurity cases in zimp array are covered!") + + # If trying to evaluate for a temperature outside of the given range, assume nearest neighbor + # and throw a warning + if any(electron_temp_profile < temperature_bin_borders[0]) or any( + electron_temp_profile > temperature_bin_borders[-1] + ): # pragma: no cover + warnings.warn( + f"Mavrin 2017 line radiation calculation is only valid between {temperature_bin_borders[0]}eV-{temperature_bin_borders[-1]}eV. Using nearest neighbor extrapolation.", + stacklevel=3, + ) + electron_temp_profile = np.maximum(electron_temp_profile, temperature_bin_borders[0]) + electron_temp_profile = np.minimum(electron_temp_profile, temperature_bin_borders[-1]) + + # solve for radiated power + ne_tau_i_per_m3 = electron_density_profile * tau_i + + X_vals = np.log10(electron_temp_profile) + Y_vals = np.log10(ne_tau_i_per_m3 / 1e19) + if np.any(Y_vals > 0.0): # pragma: no cover + warnings.warn("Warning: treating points with ne_tau_i_per_m3 > 1e19 m^-3 s as coronal.", stacklevel=3) + Y_vals = np.minimum(Y_vals, 0.0) + + log10_Lz = np.zeros(electron_temp_profile.size) + + for i, Te_test in enumerate(electron_temp_profile): + X, Y = X_vals[i], Y_vals[i] + + for j in range(temperature_bin_borders.size - 1): + Te_min, Te_max = temperature_bin_borders[j], temperature_bin_borders[j + 1] + + if Te_min <= Te_test <= Te_max: + log10_Lz[i] = ( + radc[0, j] + + radc[1, j] * X + + radc[2, j] * Y + + radc[3, j] * X**2 + + radc[4, j] * X * Y + + radc[5, j] * Y**2 + + radc[6, j] * X**3 + + radc[7, j] * X**2 * Y + + radc[8, j] * X * Y**2 + + radc[9, j] * Y**3 + ) + continue + + radrate = 10.0**log10_Lz + + qRad = radrate * electron_density_profile * electron_density_profile * impurity_concentration # W / (m^3 s) + radiated_power = integrate_profile_over_volume(qRad, rho, plasma_volume) # [W] + + return float(radiated_power) / 1e6 # MW diff --git a/cfspopcon/formulas/radiated_power/post_and_jensen.py b/cfspopcon/formulas/radiated_power/post_and_jensen.py new file mode 100644 index 00000000..dfde2533 --- /dev/null +++ b/cfspopcon/formulas/radiated_power/post_and_jensen.py @@ -0,0 +1,158 @@ +"""Calculate the radiated power due to impurities, according to an analytical fitted curve.""" + +import warnings + +import numpy as np +from numpy import float64 +from numpy.polynomial.polynomial import polyval +from numpy.typing import NDArray + +from ...named_options import Impurity +from ...unit_handling import ureg, wraps_ufunc +from ..helpers import integrate_profile_over_volume + + +@wraps_ufunc( + return_units=dict(radiated_power=ureg.MW), + input_units=dict( + rho=ureg.dimensionless, + electron_temp_profile=ureg.keV, + electron_density_profile=ureg.n19, + impurity_concentration=ureg.dimensionless, + impurity_species=None, + plasma_volume=ureg.m**3, + ), + input_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), (), (), ()], +) +def calc_impurity_radiated_power_post_and_jensen( + rho: NDArray[float64], + electron_temp_profile: NDArray[float64], + electron_density_profile: NDArray[float64], + impurity_concentration: float, + impurity_species: Impurity, + plasma_volume: float, +) -> float: + """Calculation of radiated power using Post & Jensen 1977. + + Radiation fits to the Post & Jensen cooling curves, which use the + coronal equilibrium model with data in :cite:`post_steady_1977`. + + Args: + rho: [~] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + electron_density_profile: [1e19 m^-3] :term:`glossary link` + impurity_species: [] :term:`glossary link` + impurity_concentration: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + + Returns: + [MW] Estimated radiation power due to this impurity + """ + impurity_Z = impurity_species.value + + zimp = np.array([2, 4, 5, 6, 8, 18, 22, 26, 28, 42, 74]) + + if impurity_Z not in zimp: # pragma: no cover + warnings.warn(f"Post & Jenson radiation calculation not supported for impurity with Z={impurity_Z}", stacklevel=3) + return np.nan + + # get the index of the impurity + iz = np.nonzero(zimp == impurity_Z)[0][0] + + # supported minimum temperature for each supported impurity above + Tmin = np.array([0.002, 0.002, 0.002, 0.003, 0.005, 0.03, 0.02, 0.02, 0.03, 0.06, 0.1]) + + # If trying to evaluate for a temperature outside of the given range, assume nearest neighbor + # and throw a warning + if any(electron_temp_profile < Tmin[iz]) or any(electron_temp_profile > 100): # pragma: no cover + warnings.warn( + f"Post 1977 line radiation calculation is only valid for Z={impurity_Z} between {Tmin[iz]}-100keV. Using nearest neighbor extrapolation.", + stacklevel=3, + ) + electron_temp_profile = np.maximum(electron_temp_profile, Tmin[iz]) + electron_temp_profile = np.minimum(electron_temp_profile, 100) + + temperature_bin_borders = np.array([0.0, 0.02, 0.2, 2.0, 20.0, 100.0]) + + # A_i coefficients for the first temperature bin, for the 10 supported impurities + # e.g. radc1[0][3] would be the A(0) coefficient for the first temperature + # bin for Carbon (zimp[3]==6). + # radc1[:][0] would be the [A_0, A_1..., A_5] coefficients for Helium. + radc1 = np.array( + [ + [144.1278, -342.5149, -1508.695, 1965.3, 652.374, 0, 0, 0, 0, 0, 0], + [294.0867, -947.126, -3512.267, 4572.039, 1835.499, 0, 0, 0, 0, 0, 0], + [176.1164, -1035.776, -3286.123, 4159.59, 1984.266, 0, 0, 0, 0, 0, 0], + [33.8743, -538.2415, -1520.07, 1871.56, 1059.846, 0, 0, 0, 0, 0, 0], + [-3.075936, -134.9198, -347.0698, 417.3889, 280.0476, 0, 0, 0, 0, 0, 0], + [-1.204179, -13.19063, -31.27689, 36.99382, 29.33792, 0, 0, 0, 0, 0, 0], + ], + dtype=float64, + ) + + # Coefficients for 2nd temperature bin + radc2 = np.array( + [ + [-22.7421, -34.29832, -63.7016, 74.67599, -55.15118, -20.53043, 23.91331, -27.52599, -12.03248, -139.1054, 5.340828], + [-0.7402954, -58.04948, -215.6758, 454.9038, -154.3956, -2.834287, 183.3595, -39.08228, 32.53908, -649.3335, 156.0876], + [-2.177691, -103.257, -430.8101, 837.2937, -248.992, 15.06902, 301.9617, -64.69423, 67.90773, -1365.838, 417.1704], + [-2.426768, -88.53015, -422.2842, 740.2515, -180.8154, 35.17177, 237.6019, -55.55048, 65.29924, -1406.464, 550.2576], + [-1.026211, -35.30521, -200.8412, 314.7607, -57.64175, 24.00122, 90.49792, -24.05568, 29.73465, -708.6213, 356.7583], + [-0.1798547, -5.13446, -36.87482, 51.64578, -6.149181, 5.072723, 13.4509, -4.09316, 5.271279, -140.0571, 90.42786], + ] + ) + + # Coefficients for 3rd temperature bin + radc3 = np.array( + [ + [-22.54156, -21.77747, -21.47874, -21.20151, -20.68816, -19.65204, -18.99097, -18.34973, -18.30482, -17.72591, -17.23894], + [0.350319, 0.04617764, -0.15653, -0.3668933, -0.7482238, -0.1172763, -3.403261, -1.252028, -0.003319243, -1.058217, 0.05423752], + [0.1210755, 0.4411196, 0.6181287, 0.7295099, 0.7390959, 7.83322, 1.43983, -7.533115, -3.332313, -3.583172, -1.22107], + [-0.1171573, -0.2972147, -0.2477378, -0.1944827, -0.672159, -6.351577, 17.35576, -3.289693, -11.12798, 1.660089, 0.4411812], + [0.08237547, 0.04526295, -0.1060488, -0.1263576, 1.338345, -30.58849, 0.2804832, 28.66739, 0.1053073, 8.565372, -4.485821], + [0.04361719, 0.1266794, -0.04537644, -0.1491027, 3.734628, -15.28534, -19.43971, 28.30249, 9.448907, 4.532909, -7.836137], + ] + ) + + # Coefficients for 4th temperature bin + radc4 = np.array( + [ + [-22.58311, -21.77388, -21.47337, -21.21979, -20.66766, -19.74883, -19.29037, -16.71042, -16.97678, -13.85096, -14.7488], + [0.6858961, 0.0147862, -0.1829426, -0.2346986, -0.955559, 2.964839, -3.260377, -16.46143, -9.49547, -36.78452, -14.39542], + [-0.8628176, 0.5259617, 0.6678447, 0.4093794, 1.467982, -8.829391, 14.54427, 37.66238, 11.09362, 114.0587, 21.05855], + [1.205242, -0.381643, -0.3864809, 0.07874548, -0.9822488, 9.791004, -23.83997, -39.4408, 0.04045904, -163.5634, -4.394746], + [-0.738631, 0.15834, 0.116592, -0.1841379, 0.4171964, -4.960018, 16.42804, 19.18529, -6.521934, 107.626, -11.06006], + [0.168653, -0.02891062, -0.01400226, 0.05590744, -0.08244216, 0.9820032, -4.084697, -3.509238, 2.654915, -26.42488, 5.616985], + ] + ) + + # Coefficients for 5th temperature bin + radc5 = np.array( + [ + [-17.30458, -20.31496, -24.46008, -24.76796, -27.80602, -21.17935, -13.4178, -24.53957, -28.64081, 39.92683, -262.426], + [-16.24615, -4.2026, 9.26496, 9.408181, 21.46056, 5.191481, -16.75967, 17.95222, 29.99289, -175.7093, 712.5586], + [21.00786, 5.289472, -11.10684, -9.657446, -26.65906, -7.439717, 18.4332, -23.5636, -37.26082, 207.4927, -825.0168], + [-13.12075, -3.002456, 6.837004, 4.999161, 16.70831, 4.969023, -10.33234, 14.84503, 22.5806, -121.4589, 474.2407], + [4.06935, 0.8528627, -2.065106, -1.237382, -5.191943, -1.55318, 2.96053, -4.542323, -6.716598, 35.31804, -135.5175], + [-0.5009445, -0.09687936, 0.2458526, 0.116061, 0.6410295, 0.1877047, -0.3423194, 0.5477462, 0.7911687, -4.083832, 15.41889], + ] + ) + + radc = np.array([radc1, radc2, radc3, radc4, radc5]) + + Tlog = np.log10(electron_temp_profile) + log10_Lz = np.zeros(electron_temp_profile.size) + + for i in range(len(radc)): + it = np.nonzero((electron_temp_profile >= temperature_bin_borders[i]) & (electron_temp_profile < temperature_bin_borders[i + 1]))[0] + if it.size > 0: + log10_Lz[it] = polyval(Tlog[it], radc[i, :, iz]) # type: ignore[no-untyped-call] + + radrate = 10.0**log10_Lz + radrate[np.isnan(radrate)] = 0 + radrate /= 1e13 # convert from erg cm^3 -> J m^3 (erg == 1e-7 J) + + # 1e38 factor to account for the fact that our n_e values are electron_density_profile values + qRad = radrate * electron_density_profile * electron_density_profile * impurity_concentration * 1e38 # W / (m^3 s) + radiated_power = integrate_profile_over_volume(qRad, rho, plasma_volume) # [W] + return float(radiated_power) / 1e6 # MW diff --git a/cfspopcon/formulas/radiated_power/radas.py b/cfspopcon/formulas/radiated_power/radas.py new file mode 100644 index 00000000..54d3132c --- /dev/null +++ b/cfspopcon/formulas/radiated_power/radas.py @@ -0,0 +1,67 @@ +"""Calculate the impurity radiated power using the radas atomic_data.""" +import numpy as np +import xarray as xr +from numpy import float64 +from numpy.typing import NDArray + +from ...named_options import Impurity +from ...unit_handling import magnitude, ureg, wraps_ufunc +from ..helpers import integrate_profile_over_volume + + +@wraps_ufunc( + return_units=dict(radiated_power=ureg.MW), + input_units=dict( + rho=ureg.dimensionless, + electron_temp_profile=ureg.eV, + electron_density_profile=ureg.m**-3, + impurity_concentration=ureg.dimensionless, + impurity_species=None, + plasma_volume=ureg.m**3, + atomic_data=None, + ), + input_core_dims=[("dim_rho",), ("dim_rho",), ("dim_rho",), (), (), ()], + pass_as_kwargs=("atomic_data",), +) +def calc_impurity_radiated_power_radas( + rho: NDArray[float64], + electron_temp_profile: NDArray[float64], + electron_density_profile: NDArray[float64], + impurity_concentration: float, + impurity_species: Impurity, + plasma_volume: float, + atomic_data: dict[Impurity, xr.DataArray], +) -> float: + """Calculation of radiated power using radas atomic_data datasets. + + Args: + rho: [~] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + electron_density_profile: [1e19 m^-3] :term:`glossary link` + impurity_species: [] :term:`glossary link` + impurity_concentration: [~] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + atomic_data: :term:`glossary link` + + Returns: + [MW] Estimated radiation power due to this impurity + """ + MW_per_W = 1e6 + + ds = atomic_data[impurity_species] + Lz_curve = ds.coronal_Lz_interpolator + + # Use nearest neighbor extrapolation if evaluating for a + # point off-grid + + electron_temp_profile = np.minimum(electron_temp_profile, magnitude(ds.electron_temperature.max())) + electron_temp_profile = np.maximum(electron_temp_profile, magnitude(ds.electron_temperature.min())) + electron_density_profile = np.minimum(electron_density_profile, magnitude(ds.electron_density.max())) + electron_density_profile = np.maximum(electron_density_profile, magnitude(ds.electron_density.min())) + + Lz = np.power(10, Lz_curve(np.log10(electron_temp_profile), np.log10(electron_density_profile), grid=False)) + radiated_power_profile = electron_density_profile**2 * Lz + + radiated_power = impurity_concentration * integrate_profile_over_volume(radiated_power_profile, rho, plasma_volume) / MW_per_W + + return radiated_power diff --git a/cfspopcon/formulas/radiated_power/radiated_power.py b/cfspopcon/formulas/radiated_power/radiated_power.py new file mode 100644 index 00000000..7f660a9f --- /dev/null +++ b/cfspopcon/formulas/radiated_power/radiated_power.py @@ -0,0 +1,55 @@ +"""Compute the total radiated power.""" +import numpy as np +import xarray as xr + +from ...named_options import Impurity, RadiationMethod +from ...unit_handling import Unitfull, ureg +from .mavrin_coronal import calc_impurity_radiated_power_mavrin_coronal +from .mavrin_noncoronal import calc_impurity_radiated_power_mavrin_noncoronal +from .post_and_jensen import calc_impurity_radiated_power_post_and_jensen +from .radas import calc_impurity_radiated_power_radas + + +def calc_impurity_radiated_power( + radiated_power_method: RadiationMethod, + rho: Unitfull, + electron_temp_profile: Unitfull, + electron_density_profile: Unitfull, + impurities: xr.DataArray, + plasma_volume: Unitfull, + atomic_data: dict[Impurity, xr.DataArray], +) -> xr.DataArray: + """Compute the total radiated power due to fuel and impurity species. + + Args: + radiated_power_method: [] :term:`glossary link` + rho: [~] :term:`glossary link` + electron_temp_profile: [keV] :term:`glossary link` + electron_density_profile: [1e19 m^-3] :term:`glossary link` + impurities: [] :term:`glossary link` + plasma_volume: [m^3] :term:`glossary link` + atomic_data: :term:`glossary link` + + Returns: + [MW] Estimated radiation power due to this impurity + """ + P_rad_kwargs = dict( + rho=rho, + electron_temp_profile=electron_temp_profile, + electron_density_profile=electron_density_profile, + impurity_concentration=impurities, + impurity_species=impurities.dim_species, + plasma_volume=plasma_volume, + ) + if radiated_power_method == RadiationMethod.PostJensen: + P_rad_impurity = calc_impurity_radiated_power_post_and_jensen(**P_rad_kwargs) + elif radiated_power_method == RadiationMethod.MavrinCoronal: + P_rad_impurity = calc_impurity_radiated_power_mavrin_coronal(**P_rad_kwargs) + elif radiated_power_method == RadiationMethod.MavrinNoncoronal: + P_rad_impurity = calc_impurity_radiated_power_mavrin_noncoronal(**P_rad_kwargs, tau_i=np.inf * ureg.s) + elif radiated_power_method == RadiationMethod.Radas: + P_rad_impurity = calc_impurity_radiated_power_radas(**P_rad_kwargs, atomic_data=atomic_data) + else: + raise NotImplementedError(f"No implementation for radiated_power_method = {radiated_power_method}") + + return P_rad_impurity # type:ignore[no-any-return] diff --git a/cfspopcon/formulas/scrape_off_layer_model/__init__.py b/cfspopcon/formulas/scrape_off_layer_model/__init__.py new file mode 100644 index 00000000..e58586a5 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/__init__.py @@ -0,0 +1,15 @@ +"""Module to perform simple scrape-off-layer calculations. + +These are mostly based on the two-point-model, from :cite:`stangeby_2018`. +""" +from .lambda_q import calc_lambda_q +from .parallel_heat_flux_density import calc_parallel_heat_flux_density +from .solve_target_first_two_point_model import solve_target_first_two_point_model +from .solve_two_point_model import solve_two_point_model + +__all__ = [ + "solve_two_point_model", + "calc_parallel_heat_flux_density", + "calc_lambda_q", + "solve_target_first_two_point_model", +] diff --git a/cfspopcon/formulas/scrape_off_layer_model/lambda_q.py b/cfspopcon/formulas/scrape_off_layer_model/lambda_q.py new file mode 100644 index 00000000..f983a938 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/lambda_q.py @@ -0,0 +1,92 @@ +"""Routines to calculate the heat flux decay length (lambda_q), for several different scalings.""" + +from ...named_options import LambdaQScaling +from ...unit_handling import ureg, wraps_ufunc + + +@wraps_ufunc( + return_units=dict(lambda_q=ureg.millimeter), + input_units=dict( + lambda_q_scaling=None, + average_total_pressure=ureg.atm, + power_crossing_separatrix=ureg.megawatt, + major_radius=ureg.meter, + B_pol_omp=ureg.tesla, + inverse_aspect_ratio=ureg.dimensionless, + ), +) +def calc_lambda_q( + lambda_q_scaling: LambdaQScaling, + average_total_pressure: float, + power_crossing_separatrix: float, + major_radius: float, + B_pol_omp: float, + inverse_aspect_ratio: float, +) -> float: + """Calculate SOL heat flux decay length (lambda_q) from a scaling. + + Args: + lambda_q_scaling: :term:`glossary link` + average_total_pressure: [atm] :term:`glossary link ` + power_crossing_separatrix: [MW] :term:`glossary link` + major_radius: [m] :term:`glossary link` + B_pol_omp: [T] :term:`glossary link` + inverse_aspect_ratio: [~] :term:`glossary link` + + Returns: + :term:`lambda_q` [mm] + """ + if lambda_q_scaling == LambdaQScaling.Brunner: + return float(calc_lambda_q_with_brunner.__wrapped__(average_total_pressure)) + elif lambda_q_scaling == LambdaQScaling.EichRegression14: + return float(calc_lambda_q_with_eich_regression_14.__wrapped__(B_pol_omp)) + elif lambda_q_scaling == LambdaQScaling.EichRegression15: + return float( + calc_lambda_q_with_eich_regression_15.__wrapped__(power_crossing_separatrix, major_radius, B_pol_omp, inverse_aspect_ratio) + ) + else: + raise NotImplementedError(f"No implementation for lambda_q scaling {lambda_q_scaling}") + + +@wraps_ufunc( + return_units=dict(lambda_q=ureg.millimeter), + input_units=dict(average_total_pressure=ureg.atm), +) +def calc_lambda_q_with_brunner(average_total_pressure: float) -> float: + """Return lambda_q according to the Brunner scaling. + + Equation 4 in :cite:`brunner_2018_heat_flux` + """ + return float(0.91 * average_total_pressure**-0.48) + + +@wraps_ufunc(return_units=dict(lambda_q=ureg.millimeter), input_units=dict(B_pol_omp=ureg.tesla)) +def calc_lambda_q_with_eich_regression_14(B_pol_omp: float) -> float: + """Return lambda_q according to Eich regression 14. + + #14 in Table 3 in :cite:`eich_scaling_2013` + """ + return float(0.63 * B_pol_omp**-1.19) + + +@wraps_ufunc( + return_units=dict(lambda_q=ureg.millimeter), + input_units=dict( + power_crossing_separatrix=ureg.megawatt, + major_radius=ureg.meter, + B_pol_omp=ureg.tesla, + inverse_aspect_ratio=ureg.dimensionless, + ), +) +def calc_lambda_q_with_eich_regression_15( + power_crossing_separatrix: float, major_radius: float, B_pol_omp: float, inverse_aspect_ratio: float +) -> float: + """Return lambda_q according to Eich regression 15. + + #15 in Table 3 in :cite:`eich_scaling_2013` + """ + lambda_q = 1.35 * major_radius**0.04 * B_pol_omp**-0.92 * inverse_aspect_ratio**0.42 + if power_crossing_separatrix > 0: + return float(lambda_q * power_crossing_separatrix**-0.02) + else: + return float(lambda_q) diff --git a/cfspopcon/formulas/scrape_off_layer_model/momentum_loss_functions.py b/cfspopcon/formulas/scrape_off_layer_model/momentum_loss_functions.py new file mode 100644 index 00000000..4dec8e3b --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/momentum_loss_functions.py @@ -0,0 +1,62 @@ +"""Calculate SOL momentum loss as a function target electron temperature. + +See Figure 15 of :cite:`stangeby_2018`. +""" +import numpy as np + +from ...named_options import MomentumLossFunction +from ...unit_handling import Quantity, ureg, wraps_ufunc + + +def _calc_SOL_momentum_loss_fraction(A: float, Tstar: float, n: float, target_electron_temp: float) -> float: + """Calculates the fraction of momentum lost in the SOL, for a generic SOL momentum loss function. + + This is equation 33 of :cite:`stangeby_2018`, rearranged for $f^{total}_{mom-loss}$ + """ + return float(1.0 - A * (1.0 - np.exp(-target_electron_temp / Tstar)) ** n) + + +@wraps_ufunc( + return_units=dict(momentum_loss_fraction=ureg.dimensionless), + input_units=dict(key=None, target_electron_temp=ureg.eV), +) +def calc_SOL_momentum_loss_fraction(key: MomentumLossFunction, target_electron_temp: Quantity) -> float: + """Calculate the fraction of momentum lost in the SOL. + + The coefficients come from figure captions in :cite:`stangeby_2018` + * KotovReiter: SOLPS scans with Deuterium only, no impurities for JET vertical target. Figure 7a) + * Sang: SOLPS scans for Deuterium with Carbon impurity, for DIII-D, variety of divertor configurations. Figure 7b) + * Jarvinen: EDGE2D density scan for JET with a horizontal target, for a variety of targets and injected impurities. Figure 10a) + * Moulton: SOLPS density scan for narrow slot divertor, no impurities. Figure 10b) + * PerezH: SOLPS density scan for AUG H-mode, only trace impurities. Figure 11a) + * PerezL: SOLPS density scan for AUG L-mode, with Carbon impurity. Figure 11b) + + Comparison is in Figure 15. + + Args: + key: which momentum loss function to use + target_electron_temp: electron temperature at the target [eV] + + Returns: + SOL_momentum_loss_fraction [~] + """ + if key == MomentumLossFunction.KotovReiter: + return _calc_SOL_momentum_loss_fraction(1.0, 0.8, 2.1, target_electron_temp) + + elif key == MomentumLossFunction.Sang: + return _calc_SOL_momentum_loss_fraction(1.3, 1.8, 1.6, target_electron_temp) + + elif key == MomentumLossFunction.Jarvinen: + return _calc_SOL_momentum_loss_fraction(1.7, 2.2, 1.2, target_electron_temp) + + elif key == MomentumLossFunction.Moulton: + return _calc_SOL_momentum_loss_fraction(1.0, 1.0, 1.5, target_electron_temp) + + elif key == MomentumLossFunction.PerezH: + return _calc_SOL_momentum_loss_fraction(0.8, 2.0, 1.2, target_electron_temp) + + elif key == MomentumLossFunction.PerezL: + return _calc_SOL_momentum_loss_fraction(1.1, 3.0, 0.9, target_electron_temp) + + else: + raise NotImplementedError(f"No implementation for MomentumLossFunction {key}") diff --git a/cfspopcon/formulas/scrape_off_layer_model/parallel_heat_flux_density.py b/cfspopcon/formulas/scrape_off_layer_model/parallel_heat_flux_density.py new file mode 100644 index 00000000..e304aa74 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/parallel_heat_flux_density.py @@ -0,0 +1,35 @@ +"""Routines to calculate the upstream (unmitigated) parallel heat flux density.""" +from numpy import pi + +from ...unit_handling import Unitfull + + +def calc_parallel_heat_flux_density( + power_crossing_separatrix: Unitfull, + fraction_of_P_SOL_to_divertor: Unitfull, + upstream_major_radius: Unitfull, + lambda_q: Unitfull, + upstream_fieldline_pitch: Unitfull, +) -> Unitfull: + """Calculate the parallel heat flux density entering the flux tube (q_par). + + This expression is power to target divided by the area perpendicular to the flux tube. + 1. Power to target = power crossing separatrix * fraction of that power going to the target considered + 2. The poloidal area of a ring at the outboard midplane is 2 * pi * (R + minor_radius) * width + 3. For the width, we take the heat flux decay length lambda_q + 4. P_SOL * f_share / (2 * pi * (R + minor_radius) lambda_q) gives the heat flux per poloidal area + 5. We project this poloidal heat flux density into a parallel heat flux density by dividing by the field-line pitch + + Args: + power_crossing_separatrix: [MW] :term:`glossary link` + fraction_of_P_SOL_to_divertor: :term:`glossary link ` + upstream_major_radius: [m] R + minor_radius, major radius at outboard midplane separatrix + lambda_q: [mm] :term:`glossary link` + upstream_fieldline_pitch: B_total / B_poloidal at outboard midplane separatrix [~] + + Returns: + q_parallel [GW/m^2] + """ + return ( + power_crossing_separatrix * fraction_of_P_SOL_to_divertor / (2.0 * pi * upstream_major_radius * lambda_q) * upstream_fieldline_pitch + ) diff --git a/cfspopcon/formulas/scrape_off_layer_model/required_power_loss_fraction.py b/cfspopcon/formulas/scrape_off_layer_model/required_power_loss_fraction.py new file mode 100644 index 00000000..79859b22 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/required_power_loss_fraction.py @@ -0,0 +1,40 @@ +"""Calculate the SOL power loss fraction required to achieve a specified target electron temperature.""" + +from typing import Union + +import numpy as np +import xarray as xr + +from ...unit_handling import Quantity + + +def calc_required_SOL_power_loss_fraction( + target_electron_temp_basic: Union[Quantity, xr.DataArray], + f_other_target_electron_temp: Union[float, xr.DataArray], + SOL_momentum_loss_fraction: Union[Quantity, xr.DataArray], + required_target_electron_temp: Union[Quantity, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate the SOL radiated power fraction required to reach a desired target electron temperature. + + This equation is equation 15 of :cite:`stangeby_2018`, rearranged for $f_{cooling}$. + + Args: + target_electron_temp_basic: from target_electron_temp module [eV] + f_other_target_electron_temp: from target_electron_temp module [~] + SOL_momentum_loss_fraction: fraction of momentum lost in SOL [~] + required_target_electron_temp: what target temperature do we want? [eV] + + Returns: + SOL_power_loss_fraction [~] + """ + required_SOL_power_loss_fraction = xr.DataArray( + 1.0 + - np.sqrt( + required_target_electron_temp + / target_electron_temp_basic + * (1.0 - SOL_momentum_loss_fraction) ** 2 + / f_other_target_electron_temp + ) + ) + + return required_SOL_power_loss_fraction.clip(min=0.0) diff --git a/cfspopcon/formulas/scrape_off_layer_model/solve_target_first_two_point_model.py b/cfspopcon/formulas/scrape_off_layer_model/solve_target_first_two_point_model.py new file mode 100644 index 00000000..f5c364a0 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/solve_target_first_two_point_model.py @@ -0,0 +1,121 @@ +"""Compute all terms in the two-point-model for a fixed target electron temperature.""" +from typing import Union + +import xarray as xr + +from ...named_options import MomentumLossFunction +from ...unit_handling import Unitfull, ureg +from .momentum_loss_functions import calc_SOL_momentum_loss_fraction +from .required_power_loss_fraction import calc_required_SOL_power_loss_fraction +from .target_electron_density import ( + calc_f_other_target_electron_density, + calc_f_vol_loss_target_electron_density, + calc_target_electron_density, + calc_target_electron_density_basic, +) +from .target_electron_flux import ( + calc_f_other_target_electron_flux, + calc_f_vol_loss_target_electron_flux, + calc_target_electron_flux, + calc_target_electron_flux_basic, +) +from .target_electron_temp import calc_f_other_target_electron_temp, calc_target_electron_temp_basic +from .total_pressure import calc_upstream_total_pressure +from .upstream_electron_temp import calc_upstream_electron_temp + + +def solve_target_first_two_point_model( + target_electron_temp: Unitfull, + parallel_heat_flux_density: Unitfull, + parallel_connection_length: Unitfull, + upstream_electron_density: Unitfull, + toroidal_flux_expansion: Unitfull, + fuel_average_mass_number: Unitfull, + kappa_e0: Unitfull, + SOL_momentum_loss_function: Union[MomentumLossFunction, xr.DataArray], + sheath_heat_transmission_factor: Unitfull = 7.5 * ureg.dimensionless, + SOL_conduction_fraction: Unitfull = 1.0 * ureg.dimensionless, + target_ratio_of_ion_to_electron_temp: Unitfull = 1.0 * ureg.dimensionless, + target_ratio_of_electron_to_ion_density: Unitfull = 1.0 * ureg.dimensionless, + target_mach_number: Unitfull = 1.0 * ureg.dimensionless, + upstream_ratio_of_ion_to_electron_temp: Unitfull = 1.0 * ureg.dimensionless, + upstream_ratio_of_electron_to_ion_density: Unitfull = 1.0 * ureg.dimensionless, + upstream_mach_number: Unitfull = 0.0 * ureg.dimensionless, +) -> tuple[Unitfull, Unitfull, Unitfull, Unitfull]: + """Calculate the SOL_power_loss_fraction required to keep the target temperature at a given value. + + Args: + target_electron_temp: [eV] + parallel_heat_flux_density: [GW/m^2] + parallel_connection_length: [m] + upstream_electron_density: [m^-3] + toroidal_flux_expansion: [~] + fuel_average_mass_number: [~] + kappa_e0: electron heat conductivity constant [W / (eV^3.5 * m)] + SOL_momentum_loss_function: which momentum loss function to use + sheath_heat_transmission_factor: [~] + SOL_conduction_fraction: [~] + target_ratio_of_ion_to_electron_temp: [~] + target_ratio_of_electron_to_ion_density: [~] + target_mach_number: [~] + upstream_ratio_of_ion_to_electron_temp: [~] + upstream_ratio_of_electron_to_ion_density: [~] + upstream_mach_number: [~] + + Returns: + SOL_power_loss_fraction [~], upstream_electron_temp [eV], target_electron_density [m^-3], target_electron_flux [m^-2 s^-1] + """ + SOL_momentum_loss_fraction = calc_SOL_momentum_loss_fraction(SOL_momentum_loss_function, target_electron_temp) + + upstream_electron_temp = calc_upstream_electron_temp( + target_electron_temp=target_electron_temp, + parallel_heat_flux_density=parallel_heat_flux_density, + parallel_connection_length=parallel_connection_length, + SOL_conduction_fraction=SOL_conduction_fraction, + kappa_e0=kappa_e0, + ) + + upstream_total_pressure = calc_upstream_total_pressure( + upstream_electron_density=upstream_electron_density, + upstream_electron_temp=upstream_electron_temp, + upstream_ratio_of_ion_to_electron_temp=upstream_ratio_of_ion_to_electron_temp, + upstream_ratio_of_electron_to_ion_density=upstream_ratio_of_electron_to_ion_density, + upstream_mach_number=upstream_mach_number, + ) + + f_basic_kwargs = dict( + fuel_average_mass_number=fuel_average_mass_number, + parallel_heat_flux_density=parallel_heat_flux_density, + upstream_total_pressure=upstream_total_pressure, + sheath_heat_transmission_factor=sheath_heat_transmission_factor, + ) + + f_other_kwargs = dict( + target_ratio_of_ion_to_electron_temp=target_ratio_of_ion_to_electron_temp, + target_ratio_of_electron_to_ion_density=target_ratio_of_electron_to_ion_density, + target_mach_number=target_mach_number, + toroidal_flux_expansion=toroidal_flux_expansion, + ) + + SOL_power_loss_fraction = calc_required_SOL_power_loss_fraction( + target_electron_temp_basic=calc_target_electron_temp_basic(**f_basic_kwargs), + f_other_target_electron_temp=calc_f_other_target_electron_temp(**f_other_kwargs), + SOL_momentum_loss_fraction=SOL_momentum_loss_fraction, + required_target_electron_temp=target_electron_temp, + ) + + f_vol_loss_kwargs = dict(SOL_power_loss_fraction=SOL_power_loss_fraction, SOL_momentum_loss_fraction=SOL_momentum_loss_fraction) + + target_electron_density = calc_target_electron_density( + target_electron_density_basic=calc_target_electron_density_basic(**f_basic_kwargs), + f_vol_loss_target_electron_density=calc_f_vol_loss_target_electron_density(**f_vol_loss_kwargs), + f_other_target_electron_density=calc_f_other_target_electron_density(**f_other_kwargs), + ) + + target_electron_flux = calc_target_electron_flux( + target_electron_flux_basic=calc_target_electron_flux_basic(**f_basic_kwargs), + f_vol_loss_target_electron_flux=calc_f_vol_loss_target_electron_flux(**f_vol_loss_kwargs), + f_other_target_electron_flux=calc_f_other_target_electron_flux(**f_other_kwargs), + ) + + return SOL_power_loss_fraction, upstream_electron_temp, target_electron_density, target_electron_flux diff --git a/cfspopcon/formulas/scrape_off_layer_model/solve_two_point_model.py b/cfspopcon/formulas/scrape_off_layer_model/solve_two_point_model.py new file mode 100644 index 00000000..cde26ad1 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/solve_two_point_model.py @@ -0,0 +1,209 @@ +"""Compute all terms in the two-point-model for a fixed SOL power loss fraction.""" +from typing import Union + +import numpy as np +import xarray as xr + +from ...named_options import MomentumLossFunction +from ...unit_handling import Quantity, Unitfull, ureg +from .momentum_loss_functions import calc_SOL_momentum_loss_fraction +from .target_electron_density import ( + calc_f_other_target_electron_density, + calc_f_vol_loss_target_electron_density, + calc_target_electron_density, + calc_target_electron_density_basic, +) +from .target_electron_flux import ( + calc_f_other_target_electron_flux, + calc_f_vol_loss_target_electron_flux, + calc_target_electron_flux, + calc_target_electron_flux_basic, +) +from .target_electron_temp import ( + calc_f_other_target_electron_temp, + calc_f_vol_loss_target_electron_temp, + calc_target_electron_temp, + calc_target_electron_temp_basic, +) +from .total_pressure import calc_upstream_total_pressure +from .upstream_electron_temp import calc_upstream_electron_temp + + +def solve_two_point_model( + SOL_power_loss_fraction: Unitfull, + parallel_heat_flux_density: Unitfull, + parallel_connection_length: Unitfull, + upstream_electron_density: Unitfull, + toroidal_flux_expansion: Unitfull, + fuel_average_mass_number: Unitfull, + kappa_e0: Unitfull, + SOL_momentum_loss_function: Union[MomentumLossFunction, xr.DataArray], + initial_target_electron_temp: Unitfull = 10.0 * ureg.eV, + sheath_heat_transmission_factor: Unitfull = 7.5 * ureg.dimensionless, + SOL_conduction_fraction: Unitfull = 1.0 * ureg.dimensionless, + target_ratio_of_ion_to_electron_temp: Unitfull = 1.0 * ureg.dimensionless, + target_ratio_of_electron_to_ion_density: Unitfull = 1.0 * ureg.dimensionless, + target_mach_number: Unitfull = 1.0 * ureg.dimensionless, + upstream_ratio_of_ion_to_electron_temp: Unitfull = 1.0 * ureg.dimensionless, + upstream_ratio_of_electron_to_ion_density: Unitfull = 1.0 * ureg.dimensionless, + upstream_mach_number: Unitfull = 0.0 * ureg.dimensionless, + # Controlling the iterative solve + max_iterations: int = 100, + upstream_temp_relaxation: float = 0.5, + target_electron_density_relaxation: float = 0.5, + target_temp_relaxation: float = 0.5, + upstream_temp_max_residual: float = 1e-2, + target_electron_density_max_residual: float = 1e-2, + target_temp_max_residual: float = 1e-2, + # Return converged values even if not whole array is converged + raise_error_if_not_converged: bool = True, + # Print information about the solve to terminal + quiet: bool = True, +) -> tuple[Union[Quantity, xr.DataArray], Union[Quantity, xr.DataArray], Union[Quantity, xr.DataArray], Union[Quantity, xr.DataArray]]: + """Calculate the upstream and target electron temperature and target electron density according to the extended two-point-model. + + Args: + SOL_power_loss_fraction: [~] + parallel_heat_flux_density: [GW/m^2] + parallel_connection_length: [m] + upstream_electron_density: [m^-3] + toroidal_flux_expansion: [~] + fuel_average_mass_number: [~] + kappa_e0: electron heat conductivity constant [W / (eV^3.5 * m)] + SOL_momentum_loss_function: which momentum loss function to use + initial_target_electron_temp: starting guess for target electron temp [eV] + sheath_heat_transmission_factor: [~] + SOL_conduction_fraction: [~] + target_ratio_of_ion_to_electron_temp: [~] + target_ratio_of_electron_to_ion_density: [~] + target_mach_number: [~] + upstream_ratio_of_ion_to_electron_temp: [~] + upstream_ratio_of_electron_to_ion_density: [~] + upstream_mach_number: [~] + max_iterations: how many iterations to try before returning NaN + upstream_temp_relaxation: step-size for upstream Te evolution + target_electron_density_relaxation: step-size for target ne evolution + target_temp_relaxation: step-size for target Te evolution + upstream_temp_max_residual: relative rate of change for convergence for upstream Te evolution + target_electron_density_max_residual: relative rate of change for convergence for target ne evolution + target_temp_max_residual: relative rate of change for convergence for target Te evolution + raise_error_if_not_converged: raise an error if not all point converge within max iterations (otherwise return NaN) + quiet: if not True, print additional information about the iterative solve to terminal + Returns: + upstream_electron_temp [eV], target_electron_density [m^-3], target_electron_temp [eV], target_electron_flux [m^-2 s^-1] + """ + f_other_kwargs = dict( + target_ratio_of_ion_to_electron_temp=target_ratio_of_ion_to_electron_temp, + target_ratio_of_electron_to_ion_density=target_ratio_of_electron_to_ion_density, + target_mach_number=target_mach_number, + toroidal_flux_expansion=toroidal_flux_expansion, + ) + f_other_target_electron_density = calc_f_other_target_electron_density(**f_other_kwargs) + f_other_target_electron_temp = calc_f_other_target_electron_temp(**f_other_kwargs) + f_other_target_electron_flux = calc_f_other_target_electron_flux(**f_other_kwargs) + + iteration = 0 + target_electron_temp = initial_target_electron_temp + + while iteration < max_iterations: + iteration += 1 + + new_upstream_electron_temp = calc_upstream_electron_temp( + target_electron_temp=target_electron_temp, + parallel_heat_flux_density=parallel_heat_flux_density, + parallel_connection_length=parallel_connection_length, + SOL_conduction_fraction=SOL_conduction_fraction, + kappa_e0=kappa_e0, + ) + + upstream_total_pressure = calc_upstream_total_pressure( + upstream_electron_density=upstream_electron_density, + upstream_electron_temp=new_upstream_electron_temp, + upstream_ratio_of_ion_to_electron_temp=upstream_ratio_of_ion_to_electron_temp, + upstream_ratio_of_electron_to_ion_density=upstream_ratio_of_electron_to_ion_density, + upstream_mach_number=upstream_mach_number, + ) + + f_vol_loss_kwargs = dict( + SOL_power_loss_fraction=SOL_power_loss_fraction, + SOL_momentum_loss_fraction=calc_SOL_momentum_loss_fraction(SOL_momentum_loss_function, target_electron_temp), + ) + + f_basic_kwargs = dict( + fuel_average_mass_number=fuel_average_mass_number, + parallel_heat_flux_density=parallel_heat_flux_density, + upstream_total_pressure=upstream_total_pressure, + sheath_heat_transmission_factor=sheath_heat_transmission_factor, + ) + + target_electron_density_basic = calc_target_electron_density_basic(**f_basic_kwargs) + target_electron_temp_basic = calc_target_electron_temp_basic(**f_basic_kwargs) + + f_vol_loss_target_electron_density = calc_f_vol_loss_target_electron_density(**f_vol_loss_kwargs) + f_vol_loss_target_electron_temp = calc_f_vol_loss_target_electron_temp(**f_vol_loss_kwargs) + + new_target_electron_density = calc_target_electron_density( + target_electron_density_basic=target_electron_density_basic, + f_vol_loss_target_electron_density=f_vol_loss_target_electron_density, + f_other_target_electron_density=f_other_target_electron_density, + ) + + new_target_electron_temp = calc_target_electron_temp( + target_electron_temp_basic=target_electron_temp_basic, + f_vol_loss_target_electron_temp=f_vol_loss_target_electron_temp, + f_other_target_electron_temp=f_other_target_electron_temp, + ) + + if iteration == 1: + upstream_electron_temp = new_upstream_electron_temp + target_electron_density = new_target_electron_density + target_electron_temp = new_target_electron_temp + continue + + change_in_upstream_electron_temp = new_upstream_electron_temp - upstream_electron_temp + change_in_target_electron_density = new_target_electron_density - target_electron_density + change_in_target_electron_temp = new_target_electron_temp - target_electron_temp + + upstream_electron_temp = upstream_electron_temp + upstream_temp_relaxation * change_in_upstream_electron_temp + target_electron_density = target_electron_density + target_electron_density_relaxation * change_in_target_electron_density + target_electron_temp = target_electron_temp + target_temp_relaxation * change_in_target_electron_temp + + if np.all( + [ + np.abs(change_in_upstream_electron_temp / upstream_electron_temp).max() < upstream_temp_max_residual, + np.abs(change_in_target_electron_density / target_electron_density).max() < target_electron_density_max_residual, + np.abs(change_in_target_electron_temp / target_electron_temp).max() < target_temp_max_residual, + ] + ): + if not quiet: + print(f"Converged in {iteration} iterations") + break + else: + if raise_error_if_not_converged: + raise RuntimeError("Iterative solve did not converge.") + + target_electron_flux_basic = calc_target_electron_flux_basic(**f_basic_kwargs) + f_vol_loss_target_electron_flux = calc_f_vol_loss_target_electron_flux(**f_vol_loss_kwargs) + + target_electron_flux = calc_target_electron_flux( + target_electron_flux_basic=target_electron_flux_basic, + f_vol_loss_target_electron_flux=f_vol_loss_target_electron_flux, + f_other_target_electron_flux=f_other_target_electron_flux, + ) + + mask = ( + (np.abs(change_in_upstream_electron_temp / upstream_electron_temp) < upstream_temp_max_residual) + & (np.abs(change_in_target_electron_density / target_electron_density) < target_electron_density_max_residual) + & (np.abs(change_in_target_electron_temp / target_electron_temp) < target_temp_max_residual) + ) + + number_nonconverged = np.count_nonzero(~mask) + if number_nonconverged > 0 and not quiet: + print(f"{number_nonconverged} values did not converge in {max_iterations} iterations.") + + upstream_electron_temp = xr.where(mask, upstream_electron_temp, np.nan) # type:ignore[no-untyped-call] + target_electron_density = xr.where(mask, target_electron_density, np.nan) # type:ignore[no-untyped-call] + target_electron_temp = xr.where(mask, target_electron_temp, np.nan) # type:ignore[no-untyped-call] + target_electron_flux = xr.where(mask, target_electron_flux, np.nan) # type:ignore[no-untyped-call] + + return upstream_electron_temp, target_electron_density, target_electron_temp, target_electron_flux diff --git a/cfspopcon/formulas/scrape_off_layer_model/target_electron_density.py b/cfspopcon/formulas/scrape_off_layer_model/target_electron_density.py new file mode 100644 index 00000000..f2659407 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/target_electron_density.py @@ -0,0 +1,93 @@ +"""Routines to calculate the target electron density, following the 2-point-model method of Stangeby, PPCF 2018.""" +from typing import Union + +import xarray as xr + +from ...unit_handling import Quantity + + +def calc_target_electron_density( + target_electron_density_basic: Union[Quantity, xr.DataArray], + f_vol_loss_target_electron_density: Union[float, xr.DataArray], + f_other_target_electron_density: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the target electron density, correcting for volume-losses and other effects. + + Components are calculated using the other functions in this file. + """ + return target_electron_density_basic * f_vol_loss_target_electron_density * f_other_target_electron_density + + +def calc_target_electron_density_basic( + fuel_average_mass_number: Union[Quantity, xr.DataArray], + parallel_heat_flux_density: Union[Quantity, xr.DataArray], + upstream_total_pressure: Union[Quantity, xr.DataArray], + sheath_heat_transmission_factor: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the electron density at the target according to the basic two-point-model. + + From equation 24, :cite:`stangeby_2018`. + + Args: + fuel_average_mass_number: [amu] + parallel_heat_flux_density: [GW/m^2] + upstream_total_pressure: [atm] + sheath_heat_transmission_factor: [~] + + Returns: + target_electron_density_basic [m^-3] + """ + return ( + sheath_heat_transmission_factor**2 + / (32.0 * fuel_average_mass_number) + * upstream_total_pressure**3 + / parallel_heat_flux_density**2 + ) + + +def calc_f_vol_loss_target_electron_density( + SOL_power_loss_fraction: Union[float, xr.DataArray], + SOL_momentum_loss_fraction: Union[float, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate the volume-loss correction term for the electron density at the target. + + From equation 24, :cite:`stangeby_2018`. + + Args: + SOL_power_loss_fraction: f_cooling [~] + SOL_momentum_loss_fraction: f_mom-loss [~] + + Returns: + f_vol_loss_target_electron_density [~] + """ + return (1.0 - SOL_momentum_loss_fraction) ** 3 / (1.0 - SOL_power_loss_fraction) ** 2 + + +def calc_f_other_target_electron_density( + target_ratio_of_ion_to_electron_temp: Union[float, xr.DataArray], + target_ratio_of_electron_to_ion_density: Union[float, xr.DataArray], + target_mach_number: Union[float, xr.DataArray], + toroidal_flux_expansion: Union[float, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate correction terms other than the volume-loss correction for the electron density at the target. + + Includes flux expansion, dilution of ions, different electron and ion temperatures and sub/super-sonic outflow. + + From equation 24, :cite:`stangeby_2018`., with + + Args: + target_ratio_of_ion_to_electron_temp: tau_t = (T_i / T_e)_target [equation 21] [~] + target_ratio_of_electron_to_ion_density: z_t = (ne / total ion density)_target [equation 22] [~] + target_mach_number: M_t = (parallel ion velocity / sound speed)_target [~] + toroidal_flux_expansion: R_t/R_u = major radius at target / major radius upstream [see discussion around equation 12] [~] + + Returns: + f_other_target_electron_density [~] + """ + return ( + (4.0 / (1.0 + target_ratio_of_ion_to_electron_temp / target_ratio_of_electron_to_ion_density) ** 2) + * 8.0 + * target_mach_number**2 + / (1.0 + target_mach_number**2) ** 3 + * toroidal_flux_expansion**2 + ) diff --git a/cfspopcon/formulas/scrape_off_layer_model/target_electron_flux.py b/cfspopcon/formulas/scrape_off_layer_model/target_electron_flux.py new file mode 100644 index 00000000..ce6292ae --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/target_electron_flux.py @@ -0,0 +1,87 @@ +"""Routines to calculate the target electron flux, following the 2-point-model method of Stangeby, PPCF 2018.""" +from typing import Union + +import xarray as xr + +from ...unit_handling import Quantity + + +def calc_target_electron_flux( + target_electron_flux_basic: Union[Quantity, xr.DataArray], + f_vol_loss_target_electron_flux: Union[float, xr.DataArray], + f_other_target_electron_flux: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the target electron flux, correcting for volume-losses and other effects. + + Components are calculated using the other functions in this file. + """ + return target_electron_flux_basic * f_vol_loss_target_electron_flux * f_other_target_electron_flux + + +def calc_target_electron_flux_basic( + fuel_average_mass_number: Union[Quantity, xr.DataArray], + parallel_heat_flux_density: Union[Quantity, xr.DataArray], + upstream_total_pressure: Union[Quantity, xr.DataArray], + sheath_heat_transmission_factor: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the flux of electrons (particles per square-metre per second) at the target according to the basic two-point-model. + + From equation 24, :cite:`stangeby_2018`. + + Args: + fuel_average_mass_number: [amu] + parallel_heat_flux_density: [GW/m^2] + upstream_total_pressure: [atm] + sheath_heat_transmission_factor: [~] + + Returns: + target_electron_flux_basic [m^-2 s^-1] + """ + return sheath_heat_transmission_factor / (8.0 * fuel_average_mass_number) * upstream_total_pressure**2 / parallel_heat_flux_density + + +def calc_f_vol_loss_target_electron_flux( + SOL_power_loss_fraction: Union[float, xr.DataArray], + SOL_momentum_loss_fraction: Union[float, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate the volume-loss correction term for the electron flux at the target. + + From equation 24, :cite:`stangeby_2018`. + + Args: + SOL_power_loss_fraction: f_cooling [~] + SOL_momentum_loss_fraction: f_mom-loss [~] + + Returns: + f_vol_loss_target_electron_flux [~] + """ + return (1.0 - SOL_momentum_loss_fraction) ** 2 / (1.0 - SOL_power_loss_fraction) + + +def calc_f_other_target_electron_flux( + target_ratio_of_ion_to_electron_temp: Union[float, xr.DataArray], + target_ratio_of_electron_to_ion_density: Union[float, xr.DataArray], + target_mach_number: Union[float, xr.DataArray], + toroidal_flux_expansion: Union[float, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate correction terms other than the volume-loss correction for the electron flux at the target. + + Includes flux expansion, dilution of ions, different electron and ion temperatures and sub/super-sonic outflow. + From equation 24, :cite:`stangeby_2018`., with + + Args: + target_ratio_of_ion_to_electron_temp: tau_t = (T_i / T_e)_target [equation 21] [~] + target_ratio_of_electron_to_ion_density: z_t = (ne / total ion density)_target [equation 22] [~] + target_mach_number: M_t = (parallel ion velocity / sound speed)_target [~] + toroidal_flux_expansion: R_t/R_u = major radius at target / major radius upstream [see discussion around equation 12] [~] + + Returns: + f_other_target_electron_flux [~] + """ + return ( + (2.0 / (1.0 + target_ratio_of_ion_to_electron_temp / target_ratio_of_electron_to_ion_density)) + * 4.0 + * target_mach_number**2 + / (1.0 + target_mach_number**2) ** 2 + * toroidal_flux_expansion + ) diff --git a/cfspopcon/formulas/scrape_off_layer_model/target_electron_temp.py b/cfspopcon/formulas/scrape_off_layer_model/target_electron_temp.py new file mode 100644 index 00000000..32065fec --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/target_electron_temp.py @@ -0,0 +1,88 @@ +"""Routines to calculate the target electron temperature, following the 2-point-model method of Stangeby, PPCF 2018.""" +from typing import Union + +import xarray as xr + +from ...unit_handling import Quantity + + +def calc_target_electron_temp( + target_electron_temp_basic: Union[Quantity, xr.DataArray], + f_vol_loss_target_electron_temp: Union[float, xr.DataArray], + f_other_target_electron_temp: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the target electron temperature, correcting for volume-losses and other effects. + + Components are calculated using the other functions in this file. + """ + return target_electron_temp_basic * f_vol_loss_target_electron_temp * f_other_target_electron_temp + + +def calc_target_electron_temp_basic( + fuel_average_mass_number: Union[Quantity, xr.DataArray], + parallel_heat_flux_density: Union[Quantity, xr.DataArray], + upstream_total_pressure: Union[Quantity, xr.DataArray], + sheath_heat_transmission_factor: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the electron temperature at the target according to the basic two-point-model. + + From equation 24, :cite:`stangeby_2018`. + + Args: + fuel_average_mass_number: [amu] + parallel_heat_flux_density: [GW/m^2] + upstream_total_pressure: [atm] + sheath_heat_transmission_factor: [~] + + Returns: + target_electron_temp_basic [eV] + """ + return (8.0 * fuel_average_mass_number / sheath_heat_transmission_factor**2) * ( + parallel_heat_flux_density**2 / upstream_total_pressure**2 + ) + + +def calc_f_vol_loss_target_electron_temp( + SOL_power_loss_fraction: Union[float, xr.DataArray], + SOL_momentum_loss_fraction: Union[float, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate the volume-loss correction term for the electron temperature at the target. + + From equation 24, :cite:`stangeby_2018`. + + Args: + SOL_power_loss_fraction: f_cooling [~] + SOL_momentum_loss_fraction: f_mom-loss [~] + + Returns: + f_vol_loss_target_electron_temp [~] + """ + return (1.0 - SOL_power_loss_fraction) ** 2 / (1.0 - SOL_momentum_loss_fraction) ** 2 + + +def calc_f_other_target_electron_temp( + target_ratio_of_ion_to_electron_temp: Union[float, xr.DataArray], + target_ratio_of_electron_to_ion_density: Union[float, xr.DataArray], + target_mach_number: Union[float, xr.DataArray], + toroidal_flux_expansion: Union[float, xr.DataArray], +) -> Union[float, xr.DataArray]: + """Calculate correction terms other than the volume-loss correction for the electron temperature at the target. + + Includes flux expansion, dilution of ions, different electron and ion temperatures and sub/super-sonic outflow. + + From equation 24, :cite:`stangeby_2018`., with + + Args: + target_ratio_of_ion_to_electron_temp: tau_t = (T_i / T_e)_target [equation 21] [~] + target_ratio_of_electron_to_ion_density: z_t = (ne / total ion density)_target [equation 22] [~] + target_mach_number: M_t = (parallel ion velocity / sound speed)_target [~] + toroidal_flux_expansion: R_t/R_u = major radius at target / major radius upstream [see discussion around equation 12] [~] + + Returns: + f_other_target_electron_temp [~] + """ + return ( + ((1.0 + target_ratio_of_ion_to_electron_temp / target_ratio_of_electron_to_ion_density) / 2.0) + * ((1.0 + target_mach_number**2) ** 2 / (4.0 * target_mach_number**2)) + * toroidal_flux_expansion**-2 + ) diff --git a/cfspopcon/formulas/scrape_off_layer_model/total_pressure.py b/cfspopcon/formulas/scrape_off_layer_model/total_pressure.py new file mode 100644 index 00000000..46a74ac8 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/total_pressure.py @@ -0,0 +1,65 @@ +"""Routines to calculate the combined electron and ion pressure in the SOL.""" +from typing import Union + +import xarray as xr + +from ...unit_handling import Quantity + + +def calc_upstream_total_pressure( + upstream_electron_density: Union[Quantity, xr.DataArray], + upstream_electron_temp: Union[Quantity, xr.DataArray], + upstream_ratio_of_ion_to_electron_temp: Union[float, xr.DataArray], + upstream_ratio_of_electron_to_ion_density: Union[float, xr.DataArray], + upstream_mach_number: Union[float, xr.DataArray] = 0.0, +) -> Union[Quantity, xr.DataArray]: + """Calculate the upstream total pressure (including the ion temperature contribution). + + Same as calc_total_pressure, but with a default value upstream_mach_number=0.0. + + Args: + upstream_electron_density: [m^-3] + upstream_electron_temp: [eV] + upstream_ratio_of_ion_to_electron_temp: tau_t = (T_i / T_e) [~] + upstream_ratio_of_electron_to_ion_density: z_t = (ne / ni) [~] + upstream_mach_number: M_t = (parallel ion velocity / sound speed) [~] + + Returns: + upstream_total_pressure [atm] + """ + return calc_total_pressure( + electron_density=upstream_electron_density, + electron_temp=upstream_electron_temp, + ratio_of_ion_to_electron_temp=upstream_ratio_of_ion_to_electron_temp, + ratio_of_electron_to_ion_density=upstream_ratio_of_electron_to_ion_density, + mach_number=upstream_mach_number, + ) + + +def calc_total_pressure( + electron_density: Union[Quantity, xr.DataArray], + electron_temp: Union[Quantity, xr.DataArray], + ratio_of_ion_to_electron_temp: Union[float, xr.DataArray], + ratio_of_electron_to_ion_density: Union[float, xr.DataArray], + mach_number: Union[float, xr.DataArray], +) -> Union[Quantity, xr.DataArray]: + """Calculate the total pressure (including ion temperature contribution). + + From equation 20, :cite:`stangeby_2018`. + + Args: + electron_density: [m^-3] + electron_temp: [eV] + ratio_of_ion_to_electron_temp: tau_t = (T_i / T_e) [~] + ratio_of_electron_to_ion_density: z_t = (ne / ni) [~] + mach_number: M_t = (parallel ion velocity / sound speed) [~] + + Returns: + upstream_total_pressure [atm] + """ + return ( + (1.0 + mach_number**2) + * electron_density + * electron_temp + * (1.0 + ratio_of_ion_to_electron_temp / ratio_of_electron_to_ion_density) + ) diff --git a/cfspopcon/formulas/scrape_off_layer_model/upstream_electron_temp.py b/cfspopcon/formulas/scrape_off_layer_model/upstream_electron_temp.py new file mode 100644 index 00000000..e5f02f50 --- /dev/null +++ b/cfspopcon/formulas/scrape_off_layer_model/upstream_electron_temp.py @@ -0,0 +1,33 @@ +"""Routines to calculate the upstream electron temperature.""" + +from typing import Union + +import xarray as xr + +from ...unit_handling import Quantity + + +def calc_upstream_electron_temp( + target_electron_temp: Union[Quantity, xr.DataArray], + parallel_heat_flux_density: Union[Quantity, xr.DataArray], + parallel_connection_length: Union[Quantity, xr.DataArray], + kappa_e0: Union[Quantity, xr.DataArray], + SOL_conduction_fraction: Union[float, xr.DataArray] = 1.0, +) -> Union[Quantity, xr.DataArray]: + """Calculate the upstream electron temperature. + + Equation 38 from :cite:`stangeby_2018`, keeping the dependence on target_electron_temp. + + Args: + target_electron_temp: [eV] + parallel_heat_flux_density: [GW/m^2] + parallel_connection_length: [m] + kappa_e0: [W / (eV**3.5 m)] + SOL_conduction_fraction: [eV] + + Returns: + upstream_electron_temp [eV] + """ + return ( + target_electron_temp**3.5 + 3.5 * (SOL_conduction_fraction * parallel_heat_flux_density * parallel_connection_length / kappa_e0) + ) ** (2.0 / 7.0) diff --git a/cfspopcon/helpers.py b/cfspopcon/helpers.py new file mode 100644 index 00000000..cd03cb95 --- /dev/null +++ b/cfspopcon/helpers.py @@ -0,0 +1,105 @@ +"""Constructors and helper functions.""" +from typing import Any, Union + +import xarray as xr + +from .named_options import ( + Algorithms, + ConfinementScaling, + Impurity, + LambdaQScaling, + MomentumLossFunction, + ProfileForm, + RadiationMethod, + ReactionType, +) + + +def convert_named_options(key: str, val: Any) -> Any: # noqa: PLR0911, PLR0912 + """Given a 'key' matching a named_option, return the corresponding Enum value.""" + if key == "algorithms": + return Algorithms[val] + elif key == "energy_confinement_scaling": + return ConfinementScaling[val] + elif key == "profile_form": + return ProfileForm[val] + elif key == "radiated_power_method": + return RadiationMethod[val] + elif key == "fusion_reaction": + return ReactionType[val] + elif key == "impurity": + return Impurity[val] + elif key == "impurities": + return make_impurities_array(list(val.keys()), list(val.values())) + elif key == "core_radiator": + return Impurity[val] + elif key == "lambda_q_scaling": + return LambdaQScaling[val] + elif key == "SOL_momentum_loss_function": + return MomentumLossFunction[val] + elif key == "tauE_scaling": + return ConfinementScaling[val] + elif key == "reaction_type": + return ReactionType[val] + elif key == "radiation_method": + return RadiationMethod[val] + else: + # If the key doesn't match, don't convert the value + return val + + +def make_impurities_array( + species_list: Union[list[Union[str, Impurity]], Union[str, Impurity]], + concentrations_list: Union[list[Union[float, xr.DataArray]], Union[float, xr.DataArray]], +) -> xr.DataArray: + """Make an xr.DataArray with impurity species and their corresponding concentrations. + + This array should be used as the `impurities` variable. + """ + # Convert DataArrays of species into plain lists. This is useful if you want to store Impurity objects in a dataset. + if isinstance(species_list, (xr.DataArray)): + species_list = species_list.values.tolist() + # Deal with single-value input (not recommended, but avoids a confusing user error) + if isinstance(species_list, (str, Impurity)): + species_list = [ + species_list, + ] + if isinstance(concentrations_list, (float, xr.DataArray)): + concentrations_list = [ + concentrations_list, + ] + + if not len(species_list) == len(concentrations_list): + raise ValueError(f"Dimension mismatch. Input was species list [{species_list}], concentrations list [{concentrations_list}]") + + array = xr.DataArray() + for species, concentration in zip(species_list, concentrations_list): + array = extend_impurities_array(array, species, concentration) + + return array + + +def make_impurities_array_from_kwargs(**kwargs: Any) -> xr.DataArray: + """Make an xr.DataArray with impurity species and their corresponding concentrations, using the format (species1=concentration1, ...).""" + return make_impurities_array(list(kwargs.keys()), list(kwargs.values())) + + +def extend_impurities_array(array: xr.DataArray, species: Union[str, Impurity], concentration: Union[float, xr.DataArray]) -> xr.DataArray: + """Append a new element to the impurities array. + + This method automatically handles broadcasting. + + N.b. You can also 'extend' an empty array, constructed via xr.DataArray() + """ + if not isinstance(species, Impurity): + species = Impurity[species.capitalize()] + + if not isinstance(concentration, xr.DataArray): + concentration = xr.DataArray(concentration) + concentration = concentration.expand_dims("dim_species").assign_coords(dim_species=[species]) + + if array.ndim == 0: + return concentration + else: + other_species = array.sel(dim_species=[s for s in array.dim_species if s != species]) + return xr.concat((other_species, concentration), dim="dim_species") diff --git a/cfspopcon/input_file_handling.py b/cfspopcon/input_file_handling.py new file mode 100644 index 00000000..25e91e04 --- /dev/null +++ b/cfspopcon/input_file_handling.py @@ -0,0 +1,64 @@ +"""Methods to run analyses configured via input files.""" + +from pathlib import Path +from typing import Any, Union + +import numpy as np +import xarray as xr +import yaml + +from .algorithms import get_algorithm +from .algorithms.algorithm_class import Algorithm, CompositeAlgorithm +from .helpers import convert_named_options +from .unit_handling import set_default_units + + +def read_case(case: Union[str, Path]) -> tuple[dict[str, Any], Union[CompositeAlgorithm, Algorithm], dict[str, Any]]: + """Read a yaml file corresponding to a given case. + + case should be passed either as a complete filepath to an input.yaml file or to + the parent folder of an input.yaml file. + """ + if Path(case).exists(): + case = Path(case) + if case.is_dir(): + input_file = case / "input.yaml" + else: + input_file = case + else: + raise FileNotFoundError(f"Could not find {case}.") + + with open(input_file) as file: + repr_d: dict[str, Any] = yaml.load(file, Loader=yaml.FullLoader) + + algorithms = repr_d.pop("algorithms") + algorithm_list = [get_algorithm(algorithm) for algorithm in algorithms] + + # why doesn't mypy deduce the below without hint? + algorithm: Union[Algorithm, CompositeAlgorithm] = CompositeAlgorithm(algorithm_list) if len(algorithm_list) > 1 else algorithm_list[0] + + points = repr_d.pop("points") + + grid_values = repr_d.pop("grid") + for key, grid_spec in grid_values.items(): + grid_spacing = grid_spec.get("spacing", "linear") + + if grid_spacing == "linear": + grid_vals = np.linspace(grid_spec["min"], grid_spec["max"], num=grid_spec["num"]) + elif grid_spacing == "log": + grid_vals = np.logspace(np.log10(grid_spec["min"]), np.log10(grid_spec["max"]), num=grid_spec["num"]) + else: + raise NotImplementedError(f"No implementation for grid with {grid_spec['spacing']} spacing.") + + repr_d[key] = xr.DataArray(grid_vals, coords={f"dim_{key}": grid_vals}) + + for key, val in repr_d.items(): + if isinstance(val, (list, tuple)): + repr_d[key] = [convert_named_options(key=key, val=v) for v in val] + else: + repr_d[key] = convert_named_options(key=key, val=val) + + for key, val in repr_d.items(): + repr_d[key] = set_default_units(key=key, value=val) + + return repr_d, algorithm, points diff --git a/cfspopcon/named_options.py b/cfspopcon/named_options.py new file mode 100644 index 00000000..f905efc3 --- /dev/null +++ b/cfspopcon/named_options.py @@ -0,0 +1,127 @@ +"""Enumerators to constrain options for functions.""" +from enum import Enum, auto + + +class Algorithms(Enum): + """Select which top-level algorithm to run.""" + + predictive_popcon = auto() + two_point_model_fixed_fpow = auto() + two_point_model_fixed_qpart = auto() + two_point_model_fixed_tet = auto() + calc_beta = auto() + calc_core_radiated_power = auto() + calc_fusion_gain = auto() + calc_geometry = auto() + calc_heat_exhaust = auto() + calc_ohmic_power = auto() + calc_peaked_profiles = auto() + calc_plasma_current_from_q_star = auto() + calc_q_star_from_plasma_current = auto() + calc_power_balance_from_tau_e = auto() + calc_zeff_and_dilution_from_impurities = auto() + calc_confinement_transition_threshold_power = auto() + calc_ratio_P_LH = auto() + calc_f_rad_core = auto() + calc_normalised_collisionality = auto() + calc_rho_star = auto() + calc_triple_product = auto() + calc_greenwald_fraction = auto() + calc_current_relaxation_time = auto() + calc_peak_pressure = auto() + calc_average_total_pressure = auto() + calc_bootstrap_fraction = auto() + calc_auxillary_power = auto() + calc_average_ion_temp = auto() + calc_fuel_average_mass_number = auto() + calc_magnetic_field_on_axis = auto() + calc_extrinsic_core_radiator = auto() + require_P_rad_less_than_P_in = auto() + calc_P_SOL = auto() + use_LOC_tau_e_below_threshold = auto() + calc_plasma_stored_energy = auto() + + +class ProfileForm(Enum): + """Methods to calculate nT profiles.""" + + analytic = auto() + prf = auto() + + +class RadiationMethod(Enum): + """Methods to calculate radiation losses.""" + + Inherent = "Bremsstrahlung and synchrotron radiation only" + PostJensen = "Impurity radiation, using a coronal equilibrium model from Post & Jensen 1977" + MavrinCoronal = "Impurity radiation, using a coronal equilibrium model from Mavrin 2018" + MavrinNoncoronal = "Impurity radiation, using a non-coronal model from Mavrin 2017" + Radas = "Impurity line and bremsstrahlung radiation, using coronal Lz curves from Radas" + + +class ReactionType(Enum): + """Supported Fusion Fuel Reaction Types.""" + + DT = "Deuterium-Tritium" + DD = "Deuterium-Deuterium" + DHe3 = "Deuterium-Helium3" + pB11 = "Proton-Boron11" + + +class Impurity(Enum): + """Enum of possible impurity elements. + + The enum value represents the element's atomic number (Z). + """ + + Helium = 2 + Lithium = 3 + Beryllium = 4 + Carbon = 6 + Nitrogen = 7 + Oxygen = 8 + Neon = 10 + Argon = 18 + Krypton = 36 + Xenon = 54 + Tungsten = 74 + + +class ConfinementScaling(Enum): + r"""Enum of implemented \tau_{E} scalings.""" + ITER98y2 = auto() + ITER89P = auto() + ITER89P_ka = auto() + ITERL96Pth = auto() + ITER97L = auto() + IModey2 = auto() + ITPA20_STD5 = auto() + ITPA20_IL = auto() + ITPA20_IL_HighZ = auto() + ITPA_2018_STD5_OLS = auto() + ITPA_2018_STD5_WLS = auto() + ITPA_2018_STD5_GLS = auto() + ITPA_2018_STD5_SEL1_OLS = auto() + ITPA_2018_STD5_SEL1_WLS = auto() + ITPA_2018_STD5_SEL1_GLS = auto() + LOC = auto() + H_DS03 = auto() + + +class MomentumLossFunction(Enum): + """Select which SOL momentum loss function to use.""" + + KotovReiter = auto() + Sang = auto() + Jarvinen = auto() + Moulton = auto() + PerezH = auto() + PerezL = auto() + + +class LambdaQScaling(Enum): + """Options for heat flux decay length scaling.""" + + Brunner = auto() + EichRegression14 = auto() + EichRegression15 = auto() diff --git a/cfspopcon/plotting/__init__.py b/cfspopcon/plotting/__init__.py new file mode 100644 index 00000000..308326d9 --- /dev/null +++ b/cfspopcon/plotting/__init__.py @@ -0,0 +1,12 @@ +"""Plotting functionality.""" +from .coordinate_formatter import CoordinateFormatter +from .make_plot import label_contour, make_plot, units_to_string +from .plot_style_handling import read_plot_style + +__all__ = [ + "CoordinateFormatter", + "label_contour", + "make_plot", + "units_to_string", + "read_plot_style", +] diff --git a/cfspopcon/plotting/coordinate_formatter.py b/cfspopcon/plotting/coordinate_formatter.py new file mode 100644 index 00000000..a66c594c --- /dev/null +++ b/cfspopcon/plotting/coordinate_formatter.py @@ -0,0 +1,23 @@ +"""Adds a readout of the field at the current mouse position for a colormapped field plotted with pcolormesh, contour, quiver, etc. + +Usage: +>>> fig, ax = plt.subplots() +>>> ax.format_coord = CoordinateFormatter(x, y, z) +""" +import xarray as xr + + +class CoordinateFormatter: + """Data storage object used for providing a coordinate formatter.""" + + def __init__(self, array: xr.DataArray): # pragma: nocover + """Stores the data required for grid lookup.""" + self.array = array + + def __call__(self, mouse_x, mouse_y): # pragma: nocover + """Returns a string which gives the field value at the queried mouse position.""" + lookup = dict(zip(self.array.dims, (mouse_y, mouse_x))) + + mouse_z = float(self.array.sel(lookup, method="nearest").item()) + + return f"x={mouse_x:f}, y={mouse_y:f}, z={mouse_z:f}" diff --git a/cfspopcon/plotting/make_plot.py b/cfspopcon/plotting/make_plot.py new file mode 100644 index 00000000..ff03a4e4 --- /dev/null +++ b/cfspopcon/plotting/make_plot.py @@ -0,0 +1,156 @@ +"""Plot creation functions.""" +from pathlib import Path +from typing import Optional + +import matplotlib +import matplotlib.contour +import matplotlib.pyplot as plt +import numpy as np +import xarray as xr +from matplotlib.axes import Axes + +from cfspopcon import __version__ + +from ..point_selection import build_mask_from_dict, find_coords_of_minimum +from ..transform import build_transform_function_from_dict +from ..unit_handling import Quantity, Unit, dimensionless_magnitude +from .coordinate_formatter import CoordinateFormatter + + +def make_plot( + dataset: xr.Dataset, plot_params: dict, points: dict, title: str, ax: Optional[Axes] = None, output_dir: Path = Path(".") +) -> None: + """Given a dictionary corresponding to a plotting style, build a standard plot from the results of the POPCON.""" + if plot_params["type"] == "popcon": + if ax is None: + _, ax = plt.subplots(figsize=plot_params["figsize"], dpi=plot_params["show_dpi"]) + fig, ax = make_popcon_plot(dataset, title, plot_params, points, ax=ax) + else: + raise NotImplementedError(f"No plotting method for type '{plot_params['type']}'") + + if "save_as" in plot_params.keys() and output_dir is not None: + fig.savefig(output_dir / plot_params["save_as"]) + + +def make_popcon_plot(dataset: xr.Dataset, title: str, plot_params: dict, points: dict, ax: Axes): + """Make a plot.""" + fig = ax.figure + transform_func = build_transform_function_from_dict(dataset, plot_params) + + coords = plot_params["coords"] if "coords" in plot_params else plot_params["new_coords"] + legend_elements = dict() + + if "fill" in plot_params: + # Make a filled plot (max 1 variable) + subplot_params = plot_params["fill"] + field = dataset[subplot_params["variable"]] + units = subplot_params.get("units", field.pint.units) + field = field.pint.to(units) + + mask = build_mask_from_dict(dataset, plot_params=subplot_params) + transformed_field = transform_func(field.where(mask)) + + im = transformed_field.plot(ax=ax, add_colorbar=False) + cbar = fig.colorbar(im, ax=ax) + + ax.format_coord = CoordinateFormatter(transformed_field) + + cbar.ax.set_ylabel( + f"{subplot_params.get('cbar_label', subplot_params['variable'])} {units_to_string(field.pint.units)}", + rotation=270, + labelpad=subplot_params.get("labelpad", 15.0), + ) + + if "contour" in plot_params: + # Overlay contour plots + + for variable, subplot_params in plot_params["contour"].items(): + + field = dataset[variable] + units = subplot_params.get("units", field.pint.units) + field = field.pint.to(units) + + mask = build_mask_from_dict(dataset, plot_params=subplot_params) + transformed_field = transform_func(field.where(mask)) + + contour_set = transformed_field.plot.contour( + ax=ax, levels=subplot_params["levels"], colors=[subplot_params["color"]], linestyles=[subplot_params.get("line", "solid")] + ) + legend_entry = label_contour( + ax, contour_set, fontsize=subplot_params.get("fontsize", 10.0), format_spec=subplot_params.get("format", "") + ) + + legend_elements[subplot_params["label"]] = legend_entry + + for key, point_params in points.items(): + point_style = plot_params.get("points", dict()).get(key, dict()) + label = point_style.get("label", key) + + mask = build_mask_from_dict(dataset, point_params) + + if "minimize" not in point_params.keys() and "maximize" not in point_params.keys(): + raise ValueError(f"Need to provide either minimize or maximize in point specification. Keys were {point_params.keys()}") + + if "minimize" in point_params.keys(): + field = dataset[point_params["minimize"]] + else: + field = -dataset[point_params["maximize"]] + + transformed_field = transform_func(field.where(mask)) + + point_coords = find_coords_of_minimum(transformed_field, keep_dims=point_params.get("keep_dims", [])) + + point = transformed_field.isel(point_coords) + plotting_coords = [] + for dim in [coords["x"]["dimension"], coords["y"]["dimension"]]: + if dim not in point.coords and f"dim_{dim}" in point.coords: + dim = f"dim_{dim}" # noqa: PLW2901 + plotting_coords.append(point[dim]) + + legend_elements[label] = ax.scatter( + *plotting_coords, + s=point_style.get("size", None), + c=point_style.get("color", None), + marker=point_style.get("marker", None), + ) + + ax.set_title(f"{title} [{__version__}]") + ax.set_xlabel(coords["x"]["label"]) + ax.set_ylabel(coords["y"]["label"]) + ax.legend(legend_elements.values(), legend_elements.keys()) + plt.tight_layout() + + return fig, ax + + +def units_to_string(units: Unit) -> str: + """Given a pint Unit, return a string to represent the unit.""" + dummy_var = Quantity(1.0, units) + if dummy_var.check("") and np.isclose(dimensionless_magnitude(dummy_var), 1.0): + return "" + else: + return f"[{units:~P}]" + + +def label_contour(ax: plt.Axes, contour_set: matplotlib.contour.QuadContourSet, format_spec: str = "1.1f", fontsize: float = 10.0): + """Add in-line labels to contours. + + Returns the first label element, which can be used to construct a legend. + Works best with contour sets with only one color. + >>> contour_labels = dict() + >>> contour_labels["key"] = label_contour(...) + >>> ax.legend(contour_labels.values(), contour_labels.keys()) + + Inputs: + ax: the matplotlib axis of the contour plot + contour_set: the return argument of plt.contour(...) + format_spec: a format specification for the string formatting + fontsize: the font size of the label + """ + + def fmt(x): + return f"{x:{format_spec}}" + + ax.clabel(contour_set, contour_set.levels, inline=True, fmt=fmt, fontsize=fontsize) + + return contour_set.legend_elements()[0][0] diff --git a/cfspopcon/plotting/plot_style_handling.py b/cfspopcon/plotting/plot_style_handling.py new file mode 100644 index 00000000..226566e6 --- /dev/null +++ b/cfspopcon/plotting/plot_style_handling.py @@ -0,0 +1,21 @@ +"""Handling of yaml plot configuration.""" +from pathlib import Path +from typing import Any, Union + +import yaml + + +def read_plot_style(plot_style: Union[str, Path]) -> dict[str, Any]: + """Read a yaml file corresponding to a given plot_style. + + plot_style may be passed either as a complete filepath or as a string matching a plot_style in "plot_styles" + """ + if Path(plot_style).exists(): + input_file = plot_style + else: + raise FileNotFoundError(f"Could not find {plot_style}!") + + with open(input_file) as file: + repr_d: dict[str, Any] = yaml.load(file, Loader=yaml.FullLoader) + + return repr_d diff --git a/cfspopcon/point_selection.py b/cfspopcon/point_selection.py new file mode 100644 index 00000000..6a0297bf --- /dev/null +++ b/cfspopcon/point_selection.py @@ -0,0 +1,58 @@ +"""Routines to find the coordinates of the minimum or maximum value of a field.""" +from collections.abc import Sequence +from typing import Optional + +import numpy as np +import xarray as xr +from xarray.core.coordinates import DataArrayCoordinates + +from .unit_handling import Quantity + + +def find_coords_of_minimum(array: xr.DataArray, keep_dims: Sequence[str] = [], mask: Optional[xr.DataArray] = None) -> DataArrayCoordinates: + """Find the coordinates the minimum value of array. + + These coordinates can be used to find the value of other arrays at the same point. + + For example + >>> import xarray as xr + >>> import matplotlib.pyplot as plt + >>> import numpy as np + >>> from cfspopcon.operational_space import find_coords_of_minimum + >>> x = xr.DataArray(np.linspace(0, 1, num=10), dims="x") + >>> y = xr.DataArray(np.linspace(-1, 1, num=20), dims="y") + >>> z = xr.DataArray(np.abs(x + y), coords=dict(x=x, y=y)) + >>> z.T.plot() + >>> line = z.isel(find_coords_of_minimum(z, keep_dims="y")) + >>> plt.scatter(line.x, line.y) + """ + large = Quantity(np.inf, array.pint.units) + + along_dims = [dim for dim in array.dims if dim not in keep_dims] + + if mask is None: + point_coords = array.fillna(large).argmin(dim=along_dims) + else: + point_coords = array.where(mask).fillna(large).argmin(dim=along_dims) + + return point_coords # type:ignore[return-value] + + +def find_coords_of_maximum(array: xr.DataArray, keep_dims: Sequence[str] = [], mask: Optional[xr.DataArray] = None) -> DataArrayCoordinates: + """Find the coordinates of the maximum value of array.""" + return find_coords_of_minimum(-array, keep_dims=keep_dims, mask=mask) + + +def build_mask_from_dict(dataset: xr.Dataset, plot_params: dict) -> xr.DataArray: + """Build a mask field which hides inaccessible parts of the operational space.""" + mask = xr.DataArray(True) + + for mask_key, mask_range in plot_params.get("where", dict()).items(): + + mask_field = dataset[mask_key] + mask_min = Quantity(mask_range.get("min", -np.inf), mask_range.get("units", "")) + mask_max = Quantity(mask_range.get("max", +np.inf), mask_range.get("units", "")) + + mask = mask & ((mask_field > mask_min) & (mask_field < mask_max)) + + return mask diff --git a/cfspopcon/transform.py b/cfspopcon/transform.py new file mode 100644 index 00000000..38f680f6 --- /dev/null +++ b/cfspopcon/transform.py @@ -0,0 +1,173 @@ +"""Functions to reshape xarrays.""" +from collections.abc import Sequence +from typing import Callable, Optional, Union + +import numpy as np +import xarray as xr +from scipy.interpolate import griddata # type:ignore[import] + +from cfspopcon.unit_handling import Unit, magnitude + + +def order_dimensions( + array: xr.DataArray, + dims: Sequence[str], + units: Optional[dict[str, Unit]] = None, + template: Optional[Union[xr.DataArray, xr.Dataset]] = None, + order_for_plotting: bool = True, +) -> xr.DataArray: + """Reorder the dimensions of the array, broadcasting against `template` if necessary. + + This is particularly useful for plotting. + """ + if template is None: + template = xr.zeros_like(array) + + processed_dims = [] + for dim in dims: + # We sometimes add a "dim_" in front of coord to differentiate between + # variables and coordinates (in particular, coordinates can't have units) + if dim not in array.dims and f"dim_{dim}" in array.dims: + dim = f"dim_{dim}" # noqa: PLW2901 + + if dim in array.dims: + processed_dims.append(dim) + else: + # If we've asked for a dimension, but didn't find it in array.dims, + # look in the template. + if dim not in template.dims and f"dim_{dim}" in template.dims: + dim = f"dim_{dim}" # noqa: PLW2901 + if dim in template.dims: + # If we find the dimension in the template, broadcast the array + # to have the correct dimensions. + array = array.broadcast_like(template[dim]) + processed_dims.append(dim) + else: + raise ValueError(f"Array does not have dimension {dim.lstrip('dim_')}") + + if units is not None: + for dim, processed_dim in zip(dims, processed_dims): + array[processed_dim] = magnitude(template[dim.lstrip("dim_")].pint.to(units[dim])) + + if order_for_plotting: + processed_dims = processed_dims[::-1] + + return array.transpose(*processed_dims) + + +def interpolate_array_onto_new_coords( + array: xr.DataArray, + new_coords: dict[str, xr.DataArray], + resolution: Optional[dict[str, int]] = None, + coord_min: Optional[dict[str, int]] = None, + coord_max: Optional[dict[str, int]] = None, + default_resolution: int = 50, + max_distance: float = 2.0, + griddata_method: str = "linear", +) -> xr.DataArray: + """Take an xarray of values and map it to a grid of new coordinates. + + The input array and the new_coords must share the same coordinates (or be + able to be broadcast to the same coordinates). + + The new mesh will usually not overlap perfectly with the original mesh, and + may include regions not included in the original mesh. These regions are set + to NaN (based on the distance between a sample point and a new-grid point). + + This method works for arbitrary number of new_coords, but works best and makes + most sense for 2D (two new_coords). + """ + coords, coord_spacing = dict(), dict() + for key, coord_array in new_coords.items(): + coords[key], coord_spacing[key] = np.linspace( + start=coord_min.get(key, magnitude(coord_array.min())) if coord_min else magnitude(coord_array.min()), + stop=coord_max.get(key, magnitude(coord_array.max())) if coord_max else magnitude(coord_array.max()), + num=resolution.get(key, default_resolution) if resolution else default_resolution, + retstep=True, + ) + + mesh_coords = tuple(np.meshgrid(*coords.values(), indexing="ij")) + + broadcast_arrays = xr.broadcast(*(*list(new_coords.values()), array)) + sample_points = tuple([np.ravel(magnitude(broadcast_array)) for broadcast_array in broadcast_arrays[:-1]]) + array = broadcast_arrays[-1] + + interpolated_array = xr.DataArray( + griddata( + sample_points, + np.ravel(magnitude(array)), + mesh_coords, + method=griddata_method, + rescale=True, + ), + coords=coords, + attrs=array.attrs, + ).pint.quantify(array.pint.units) + + # Calculate the out-of-bounds mask based on distance to nearest sample point + mesh_shape = [coord.size for coord in coords.values()] + distance_to_nearest = np.zeros(mesh_shape, dtype=float) + stacked_samples = np.vstack(sample_points) + spacing = np.expand_dims(list(coord_spacing.values()), axis=-1) + + for index in np.ndindex(tuple(mesh_shape)): + # Iterate over each grid point + mesh_point = [mesh_coords[dimension][index] for dimension in range(len(index))] + broadcast_mesh_point = np.broadcast_to(np.expand_dims(mesh_point, axis=-1), stacked_samples.shape) + + distance_to_points = ((broadcast_mesh_point - stacked_samples) / spacing) ** 2 + distance_to_nearest[index] = np.min(np.sum(distance_to_points, axis=0)) + + clipped_array = interpolated_array.where(distance_to_nearest < max_distance).clip(min=array.min(), max=array.max()) + + return clipped_array # type:ignore[no-any-return] + + +def build_transform_function_from_dict(dataset: xr.Dataset, plot_params: dict) -> Callable[[xr.DataArray], xr.DataArray]: + """Build a function which can be called on a field to return an array with transformed coordinates. + + The simplest function is a transpose function, which makes sure that the dimensions are correctly ordered + for plotting. + + We can also build a more complicated function which transforms the field in terms of other computed fields, + remapping the field onto new axes. + """ + if "coords" in plot_params and "new_coords" in plot_params: + raise ValueError("Can only pass one of 'coords' or 'new_coords'.") + + if "coords" in plot_params: + xdim = plot_params["coords"]["x"]["dimension"] + ydim = plot_params["coords"]["y"]["dimension"] + units = { + xdim: plot_params["coords"]["x"].get("units"), + ydim: plot_params["coords"]["y"].get("units"), + } + + return lambda array: order_dimensions(array, dims=(xdim, ydim), units=units, template=dataset, order_for_plotting=True) + + elif "new_coords" in plot_params: + new_coords, new_coord_min, new_coord_max, new_coord_res = {}, {}, {}, {} + + for coord in ["y", "x"]: + new_coord = plot_params["new_coords"][coord] + new_key = new_coord["dimension"] + field = dataset[new_key] + new_coords[new_key] = field.pint.to(new_coord.get("units", field.pint.units)) + if "min" in new_coord: + new_coord_min[new_key] = new_coord["min"] + if "max" in new_coord: + new_coord_max[new_key] = new_coord["max"] + if "resolution" in new_coord: + new_coord_res[new_key] = new_coord["resolution"] + + return lambda array: interpolate_array_onto_new_coords( + array=array, + new_coords=new_coords, + resolution=new_coord_res, + coord_min=new_coord_min, + coord_max=new_coord_max, + max_distance=plot_params["new_coords"].get("max_distance", 5.0), + ) + + else: + raise NotImplementedError("Must provide either 'coords' or 'new_coords' for the transform function.") diff --git a/cfspopcon/unit_handling/__init__.py b/cfspopcon/unit_handling/__init__.py new file mode 100644 index 00000000..2bd60af4 --- /dev/null +++ b/cfspopcon/unit_handling/__init__.py @@ -0,0 +1,28 @@ +"""Uses pint and xarray to enable unit-handling over multi-dimensional arrays.""" +from typing import Union + +import xarray as xr +from pint import DimensionalityError, UnitStrippedWarning + +from .decorator import wraps_ufunc +from .default_units import convert_to_default_units, default_unit, magnitude_in_default_units, set_default_units +from .setup_unit_handling import Quantity, Unit, convert_units, dimensionless_magnitude, magnitude, ureg + +Unitfull = Union[Quantity, xr.DataArray] + +__all__ = [ + "ureg", + "Quantity", + "Unit", + "Unitfull", + "wraps_ufunc", + "magnitude_in_default_units", + "set_default_units", + "default_unit", + "convert_to_default_units", + "convert_units", + "magnitude", + "dimensionless_magnitude", + "DimensionalityError", + "UnitStrippedWarning", +] diff --git a/cfspopcon/unit_handling/decorator.py b/cfspopcon/unit_handling/decorator.py new file mode 100644 index 00000000..e2beb41d --- /dev/null +++ b/cfspopcon/unit_handling/decorator.py @@ -0,0 +1,294 @@ +"""Defines the wraps_ufunc decorator used to perform unit conversions and dimension handling.""" +import functools +import warnings +from collections.abc import Callable, Mapping, Sequence, Set +from inspect import Parameter, Signature, signature +from types import GenericAlias +from typing import Any, Optional, Union + +import xarray as xr +from pint import Unit, UnitStrippedWarning + +from .setup_unit_handling import Quantity, convert_units, magnitude, ureg + +FunctionType = Callable[..., Any] + + +def wraps_ufunc( # noqa: PLR0915 + input_units: dict[str, Union[str, Unit, None]], + return_units: dict[str, Union[str, Unit, None]], + pass_as_kwargs: tuple = (), + # kwargs for apply_ufunc + input_core_dims: Optional[Sequence[Sequence]] = None, + output_core_dims: Optional[Sequence[Sequence]] = ((),), + exclude_dims: Set = frozenset(), + vectorize: bool = True, + join: str = "exact", + dataset_join: str = "exact", + keep_attrs: str = "drop_conflicts", + dask: str = "forbidden", + output_dtypes: Optional[Sequence] = None, + output_sizes: Optional[Mapping[Any, int]] = None, + dask_gufunc_kwargs: Optional[dict[str, Any]] = None, +) -> FunctionType: + """Decorator for functions to add in unit and dimension handling. + + input_units and return_units must be provided, as dictionaries giving + a mapping between the function arguments/returns and their units. + + pass_as_kwargs can be used to optionally declare that specific arguments + should be pass directly into the function, rather than vectorized. + + The remaining arguments for the wrapper correspond to arguments for + xr.apply_ufunc. + https://docs.xarray.dev/en/stable/examples/apply_ufunc_vectorize_1d.html + """ + input_units = _check_units(input_units) + return_units = _check_units(return_units) + + ufunc_kwargs: dict[str, Any] = dict( + input_core_dims=input_core_dims, + output_core_dims=output_core_dims, + exclude_dims=exclude_dims, + vectorize=vectorize, + join=join, + dataset_join=dataset_join, + keep_attrs=keep_attrs, + dask=dask, + output_dtypes=output_dtypes, + output_sizes=output_sizes, + dask_gufunc_kwargs=dask_gufunc_kwargs, + ) + input_keys = list(input_units.keys()) + + if not isinstance(pass_as_kwargs, tuple): + raise ValueError(f"pass_as_kwargs must be passed as a tuple of keys, not {str(type(pass_as_kwargs))[1:-1]}") + + pass_as_positional_args = [key for key in input_keys if key not in pass_as_kwargs] + for arg in pass_as_kwargs: + kwarg_position = input_keys.index(arg) + if kwarg_position < len(pass_as_positional_args): + raise ValueError(f"Argument {arg} in pass_as_kwargs appears before the positional args {pass_as_positional_args}") + + if input_core_dims is not None: + if not len(input_core_dims) == len(pass_as_positional_args): + raise ValueError( + f"input_core_dims (len {len(input_core_dims)}) must the same length as positional_args ({pass_as_positional_args}, len {len(pass_as_positional_args)})" + ) + else: + input_core_dims = len(pass_as_positional_args) * [()] + + def _wraps_ufunc(func: FunctionType) -> FunctionType: + + func_signature = signature(func) + func_parameters = func_signature.parameters + + if not list(input_units.keys()) == list(func_parameters.keys()): + raise ValueError( + f"Keys for input_units {input_units.keys()} did not match func_parameters {func_parameters.keys()} (n.b. order matters!)" + ) + + default_values = {key: val.default for key, val in func_parameters.items() if val.default is not Parameter.empty} + + @functools.wraps(func) + def popcon_ufunc_wrapped_call(*args: Any, **kwargs: Any) -> Any: # noqa: PLR0912 + """Transform args and kwargs, then call the inner function.""" + # if anything goes wrong we can do some extra work to provide a better error below + try: + args_dict = dict(zip(input_keys, args)) + + if not set(args_dict.keys()).isdisjoint(kwargs.keys()): + raise RuntimeError( + f"{func.__name__} was called with repeat arguments. Input was interpreted as args={args_dict}, kwargs={kwargs}" + ) + + args_dict = {**args_dict, **kwargs} + args_dict = {**args_dict, **{key: val for key, val in default_values.items() if key not in args_dict.keys()}} + + args_dict = _return_magnitude_in_specified_units(args_dict, input_units) + + positional_args = [] + for i, key in enumerate(pass_as_positional_args): + arg = args_dict[key] + if not isinstance(arg, xr.DataArray): + positional_args.append(xr.DataArray(arg).expand_dims(input_core_dims[i])) + else: + positional_args.append(arg) + + with warnings.catch_warnings(): + warnings.simplefilter("error", category=UnitStrippedWarning) + function_return = xr.apply_ufunc( + func, + *positional_args, + kwargs={key: args_dict[key] for key in pass_as_kwargs}, + **ufunc_kwargs, + ) + + if len(return_units) == 0: + # Assume that the function return None + return function_return.item() + + function_return = _convert_return_to_quantities(function_return, return_units) + + function_return = list(function_return.values()) + + if len(function_return) > 1: + return tuple(function_return) + else: + return function_return[0] + + except Exception as e: + # the below checks if we are inside FunctionWrapper being called from another FunctionWrapper + # if that is the case we try and give a more helpful error + # if anything goes wrong in our frame inspection or we find that we aren't in a chained + # call we raise the previous exception + err = "" + try: + import inspect + + frames = inspect.getouterframes(inspect.currentframe()) + # the first entry is the current call so check if any of the earlier callees are a __call__ from a FunctionWrapper + for frame in frames[1:]: + if frame.function == "popcon_ufunc_wrapped_call": + f = frames[1] + err = "Calling `wraps_ufunc` decorated function from within `wraps_ufunc` decorated function is not allowed!\n" + err += f"Error at {f.filename}:{f.lineno}\n" + err += "\n".join(f.code_context) if f.code_context else "" + err += f"Try using `{frames[0].frame.f_locals['func'].__name__}.unitless_func(...)` instead." + break + except Exception: + # error while determining if we are withing a chained FunctionWrapper so re-raise original error + raise e from None + + # if err is not empty we have determined we are within a chained call so we raise a better error + if err: + raise RuntimeError(err) from None + else: + raise e + + # more meaningfull alias to the scalar non-unit version of the function + popcon_ufunc_wrapped_call.unitless_func = popcon_ufunc_wrapped_call.__wrapped__ # type:ignore[attr-defined] + popcon_ufunc_wrapped_call.__signature__ = _make_new_sig(func_signature, input_units, return_units) # type:ignore[attr-defined] + return popcon_ufunc_wrapped_call + + return _wraps_ufunc + + +def _check_units(units_dict: dict[str, Union[str, Unit, None]]) -> dict[str, Union[str, Unit, None]]: + + for key, unit in units_dict.items(): + if unit is None: + pass + elif isinstance(unit, str): + units_dict[key] = ureg(unit).units + elif not isinstance(unit, Unit): + raise TypeError(f"wraps_ufunc units for {key} must by of type str or Unit, not {str(type(unit))[1:-1]} (value was {unit})") + + return units_dict + + +def _return_magnitude_in_specified_units(vals: Any, units_mapping: dict[str, Union[str, Unit, None]]) -> dict[str, Any]: + + if not set(vals.keys()) == set(units_mapping): + raise ValueError(f"Argument keys {vals.keys()} did not match units_mapping keys {units_mapping.keys()}") + + converted_vals = {} + + for key in vals.keys(): + val = vals[key] + unit = units_mapping[key] + + if unit is None or val is None: + converted_vals[key] = val + + elif isinstance(val, Quantity): + converted_vals[key] = magnitude(convert_units(val, unit)) + + elif isinstance(val, xr.DataArray): + converted_vals[key] = convert_units(val, unit).pint.dequantify() + + elif Quantity(1, unit).check(ureg.dimensionless): + converted_vals[key] = val + + else: + raise NotImplementedError(f"Cannot convert {key} of type {str(type(val))[1:-1]} to units {unit}") + + return converted_vals + + +def _convert_return_to_quantities(vals: Any, units_mapping: dict[str, Union[str, Unit, None]]) -> dict[str, Any]: + + if not isinstance(vals, tuple): + vals = (vals,) + + if not len(vals) == len(units_mapping): + raise ValueError(f"Number of returned values ({len(vals)}) did not match length of units_mapping ({len(units_mapping)})") + vals = dict(zip(units_mapping.keys(), vals)) + + converted_vals = {} + + for key in vals.keys(): + val = vals[key] + unit = units_mapping[key] + + if unit is None or val is None: + converted_vals[key] = val + + elif isinstance(val, xr.DataArray): + converted_vals[key] = val.pint.quantify(unit, unit_registry=ureg) + + elif isinstance(val, Quantity): + converted_vals[key] = val.to(unit) + + else: + converted_vals[key] = Quantity(val, unit) + + return converted_vals + + +def _make_new_sig( + sig: Signature, + input_units: Mapping[str, Union[str, Unit, None]], + return_units: Mapping[str, Union[str, Unit, None]], +) -> Signature: + """Create a new signature for a wrapped function that replaces the plain floats/arrays with Quantity/DataArray.""" + parameters = list(sig.parameters.values()) + ret_annotation = sig.return_annotation + + # update parameter annotations + new_parameters: list[Parameter] = [] + for param, unit in zip(parameters, input_units.values()): + if unit is None: + new_parameters.append(param) + else: + new_parameters.append(param.replace(annotation=Union[Quantity, xr.DataArray])) + + # update return annotation + units_list = list(return_units.values()) + + # extract the types from the tuple + if isinstance(ret_annotation, GenericAlias) and ret_annotation.__origin__ == tuple: + old_types: list[Any] = list(ret_annotation.__args__) + elif ret_annotation == Parameter.empty: + old_types = [Any for _ in range(len(units_list))] + else: + old_types = [ret_annotation] + + if len(old_types) != len(units_list): + warnings.warn( + ( + f"Return type annotation {ret_annotation} has {len(old_types)} return values" + f", while the return_units: {return_units} specifies {len(return_units)} values" + ), + stacklevel=3, + ) + ret_types = tuple(xr.DataArray if units_list[i] is not None else old_types[i] for i in range(len(units_list))) + + if len(ret_types) == 0: + new_ret_ann: Union[type, None, GenericAlias] = None + elif len(ret_types) == 1: + new_ret_ann = ret_types[0] + else: + new_ret_ann = GenericAlias(tuple, ret_types) + + return sig.replace(parameters=new_parameters, return_annotation=new_ret_ann) diff --git a/cfspopcon/unit_handling/default_units.py b/cfspopcon/unit_handling/default_units.py new file mode 100644 index 00000000..6219eb58 --- /dev/null +++ b/cfspopcon/unit_handling/default_units.py @@ -0,0 +1,260 @@ +"""Define default units for writing to/from disk.""" +from collections.abc import Iterable +from numbers import Number +from typing import Any, Union, overload + +import numpy as np +import xarray as xr + +from .setup_unit_handling import DimensionalityError, Quantity, convert_units, magnitude + +DEFAULT_UNITS = dict( + areal_elongation="", + average_electron_density="n19", + average_electron_temp="keV", + average_ion_density="n19", + average_ion_temp="keV", + average_total_pressure="Pa", + B_pol_out_mid="T", + B_t_out_mid="T", + beta_poloidal="", + beta_toroidal="", + beta="", + bootstrap_fraction="", + confinement_threshold_scalar="", + confinement_time_scalar="", + core_radiated_power_fraction="", + core_radiator_charge_state="", + core_radiator_concentration="", + core_radiator=None, + current_relaxation_time="s", + dilution_change_from_core_rad="", + dilution="", + effective_collisionality="", + electron_density_peaking_offset="", + electron_density_peaking="", + electron_density_profile="n19", + electron_temp_profile="keV", + elongation_ratio_sep_to_areal="", + energy_confinement_scaling=None, + energy_confinement_time="s", + f_shaping="", + fieldline_pitch_at_omp="", + fraction_of_external_power_coupled="", + fraction_of_P_SOL_to_divertor="", + fuel_average_mass_number="amu", + fuel_ion_density_profile="n19", + fusion_reaction=None, + fusion_triple_product="n20 * keV * s", + greenwald_fraction="", + heavier_fuel_species_fraction="", + impurities="", + impurity_charge_state="", + input_SOL_power_loss_fraction="", + input_target_electron_temp="eV", + input_target_q_parallel="GW / m**2", + inverse_aspect_ratio="", + ion_density_peaking_offset="", + ion_density_peaking="", + ion_temp_profile="keV", + ion_to_electron_temp_ratio="", + kappa_e0="W / (eV**3.5 m)", + lambda_q_factor="", + lambda_q_scaling=None, + lambda_q="mm", + loop_voltage="V", + magnetic_field_on_axis="T", + major_radius="m", + minimum_core_radiated_fraction="", + minor_radius="m", + neoclassical_loop_resistivity="m * ohm", + nesep_over_nebar="", + neutron_power_flux_to_walls="MW / m**2", + neutron_rate="s**-1", + normalized_beta="percent * m * T / MA", + normalized_inverse_temp_scale_length="", + nu_star="", + P_alpha="MW", + P_auxillary="MW", + P_external="MW", + P_fusion="MW", + P_in="MW", + P_launched="MW", + P_LH_thresh="MW", + P_neutron="MW", + P_ohmic="MW", + P_radiated_by_core_radiator="MW", + P_radiation="MW", + P_sol="MW", + parallel_connection_length="m", + PB_over_R="MW * T / m", + PBpRnSq="MW * T / m * n20**-2", + peak_electron_density="n19", + peak_electron_temp="keV", + peak_fuel_ion_density="n19", + peak_ion_temp="keV", + peak_pressure="Pa", + plasma_current="A", + plasma_stored_energy="MJ", + plasma_volume="m**3", + product_of_magnetic_field_and_radius="m * T", + profile_form=None, + q_parallel="GW / m**2", + q_perp="MW / m**2", + q_star="", + Q="", + radiated_power_method=None, + radiated_power_scalar="", + ratio_of_P_SOL_to_P_LH="", + rho_star="", + rho="", + separatrix_elongation="", + separatrix_triangularity="", + SOC_LOC_ratio="", + SOL_momentum_loss_function=None, + SOL_power_loss_fraction="", + spitzer_resistivity="m * ohm", + summed_impurity_density="n19", + surface_area="m**2", + target_electron_density="n19", + target_electron_flux="m**-2 s**-1", + target_electron_temp="eV", + target_q_parallel="GW / m**2", + tau_e_scaling_uses_P_in=None, + temperature_peaking="", + toroidal_flux_expansion="", + trapped_particle_fraction="", + triangularity_psi95="", + triangularity_ratio_sep_to_psi95="", + two_point_model_method=None, + upstream_electron_temp="eV", + vertical_minor_radius="m", + z_effective="", + zeff_change_from_core_rad="", +) + + +def default_unit(var: str) -> Union[str, None]: + """Return cfspopcon's default unit for a given quantity. + + Args: + var: Quantity name + + Returns: Unit + """ + try: + return DEFAULT_UNITS[var] + except KeyError: + raise KeyError( + f"No default unit defined for {var}. Please check configured default units in the unit_handling submodule." + ) from None + + +def magnitude_in_default_units(value: Union[Quantity, xr.DataArray], key: str) -> Union[float, list[float], Any]: + """Convert values to default units and then return the magnitude. + + Args: + value: input value to convert to a float + key: name of field for looking up in DEFAULT_UNITS dictionary + + Returns: + magnitude of value in default units and as basic type + """ + try: + # unit conversion step + unit = default_unit(key) + if unit is None: + return value + + mag = magnitude(convert_units(value, unit)) + + except DimensionalityError as e: + print(f"Unit conversion failed for {key}. Could not convert '{value}' to '{DEFAULT_UNITS[key]}'") + raise e + + # single value arrays -> float + # np,xr array -> list + if isinstance(mag, (np.ndarray, xr.DataArray)): + if mag.size == 1: + return float(mag) + else: + return [float(v) for v in mag] + else: + return float(mag) + + +@overload +def set_default_units(value: Number, key: str) -> Quantity: + ... + + +@overload +def set_default_units(value: xr.DataArray, key: str) -> xr.DataArray: + ... + + +@overload +def set_default_units(value: Any, key: str) -> Any: + ... + + +def set_default_units(value: Any, key: str) -> Any: + """Return value as a quantity with default units. + + Args: + value: magnitude of input value to convert to a Quantity + key: name of field for looking up in DEFAULT_UNITS dictionary + + Returns: + magnitude of value in default units + """ + + def _is_number_not_bool(val: Any) -> bool: + return isinstance(val, Number) and not isinstance(val, bool) + + def _is_iterable_of_number_not_bool(val: Any) -> bool: + if not isinstance(val, Iterable): + return False + + if isinstance(val, (np.ndarray, xr.DataArray)) and val.ndim == 0: + return _is_number_not_bool(val.item()) + + return all(_is_number_not_bool(v) for v in value) + + # None is used to ignore class types + if DEFAULT_UNITS[key] is None: + if _is_number_not_bool(value) or _is_iterable_of_number_not_bool(value): + raise RuntimeError( + f"set_default_units for key {key} and value {value} of type {type(value)}: numeric types should carry units!" + ) + return value + elif isinstance(value, xr.DataArray): + return value.pint.quantify(DEFAULT_UNITS[key]) + else: + return Quantity(value, DEFAULT_UNITS[key]) + + +@overload +def convert_to_default_units(value: float, key: str) -> float: + ... + + +@overload +def convert_to_default_units(value: xr.DataArray, key: str) -> xr.DataArray: + ... + + +@overload +def convert_to_default_units(value: Quantity, key: str) -> Quantity: + ... + + +def convert_to_default_units(value: Union[float, Quantity, xr.DataArray], key: str) -> Union[float, Quantity, xr.DataArray]: + """Convert an array or scalar to default units.""" + unit = DEFAULT_UNITS[key] + if unit is None or unit == "": + return value + elif isinstance(value, (xr.DataArray, Quantity)): + return convert_units(value, unit) + else: + raise NotImplementedError(f"No implementation for 'convert_to_default_units' with an array of type {type(value)} ({value})") diff --git a/cfspopcon/unit_handling/setup_unit_handling.py b/cfspopcon/unit_handling/setup_unit_handling.py new file mode 100644 index 00000000..56727b66 --- /dev/null +++ b/cfspopcon/unit_handling/setup_unit_handling.py @@ -0,0 +1,98 @@ +"""Set up the pint library for unit handling.""" +import warnings +from collections.abc import Callable +from functools import wraps +from typing import Any, TypeVar, Union, overload + +import numpy as np +import numpy.typing as npt +import pint +import pint_xarray # type:ignore[import] +import xarray as xr +from pint.errors import DimensionalityError +from typing_extensions import ParamSpec + +ureg = pint_xarray.setup_registry( + pint.UnitRegistry( + force_ndarray_like=True, + cache_folder=":auto:", + ) +) + +Quantity = ureg.Quantity +Unit = ureg.Unit + +Params = ParamSpec("Params") +Ret = TypeVar("Ret") + +# Define custom units for density as n_19 or n_20 (used in several formulas) +ureg.define("_1e19_per_cubic_metre = 1e19 m^-3 = 1e19 m^-3 = n19") +ureg.define("_1e20_per_cubic_metre = 1e20 m^-3 = 1e10 m^-3 = n20") +ureg.define("percent = 0.01") + +# Needed for serialization/deserialization +pint.set_application_registry(ureg) # type:ignore[no-untyped-call] + + +def suppress_downcast_warning(func: Callable[Params, Ret]) -> Callable[Params, Ret]: + """Suppresses a common warning about downcasting quantities to arrays.""" + + @wraps(func) + def wrapper(*args: Params.args, **kwargs: Params.kwargs) -> Ret: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", message="The unit of the quantity is stripped when downcasting to ndarray.") + return func(*args, **kwargs) + + return wrapper + + +@overload +def convert_units(array: xr.DataArray, units: Union[str, pint.Unit]) -> xr.DataArray: + ... + + +@overload +def convert_units(array: pint.Quantity, units: Union[str, pint.Unit]) -> pint.Quantity: + ... + + +def convert_units(array: Union[xr.DataArray, pint.Quantity], units: Any) -> Union[xr.DataArray, pint.Quantity]: + """Convert an array to specified units, handling both Quantities and xr.DataArrays.""" + if isinstance(array, xr.DataArray): + if not hasattr(array.pint, "units") or array.pint.units is None: + array = array.pint.quantify(ureg.dimensionless) + + return array.pint.to(units) # type: ignore[no-any-return] + elif isinstance(array, Quantity): + return array.to(units) # type:ignore[no-any-return] + else: + raise NotImplementedError(f"No implementation for 'convert_units' with an array of type {type(array)} ({array})") + + +@suppress_downcast_warning +def magnitude(array: Union[xr.DataArray, pint.Quantity]) -> Union[npt.NDArray[np.float32], float]: + """Return the magnitude of an array, handling both Quantities and xr.DataArrays.""" + if isinstance(array, xr.DataArray): + return array.values + elif isinstance(array, Quantity): + return array.magnitude # type: ignore[no-any-return] + else: + raise NotImplementedError(f"No implementation for 'magnitude' with an array of type {type(array)} ({array})") + + +def dimensionless_magnitude(array: Union[xr.DataArray, pint.Quantity]) -> Union[npt.NDArray[np.float32], float]: + """Converts the array to dimensionless and returns the magnitude.""" + return magnitude(convert_units(array, ureg.dimensionless)) + + +__all__ = [ + "DimensionalityError", + "ureg", + "Quantity", + "Unit", + "suppress_downcast_warning", + "convert_units", + "magnitude", + "suppress_downcast_warning", + "dimensionless_magnitude", +] diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..8d22e749 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,265 @@ +"""Sphinx configuration for cfspopcon.""" +import warnings +from collections.abc import Mapping +from inspect import Parameter, Signature, signature +from types import GenericAlias +from typing import Any, Union + +import xarray as xr +from sphinx.ext.autodoc import ClassDocumenter, FunctionDocumenter +from sphinx.ext.autodoc.importer import get_class_members +from sphinx.ext.intersphinx import missing_reference +from sphinx.util.inspect import stringify_signature + +import cfspopcon +from cfspopcon.algorithms.algorithm_class import Algorithm +from cfspopcon import formulas +from cfspopcon.unit_handling.setup_unit_handling import Quantity, Unit + +project = "cfspopcon" +copyright = "2023, Commonwealth Fusion Systems" +author = cfspopcon.__author__ +version = cfspopcon.__version__ +release = version + +# -- General configuration + +# warn for missing references. Can be quite loud but at least we then have +# ensured that all links to other classes etc work. +nitpicky = True + +add_module_names = False + +# note that github actions seems to be on openssl 3.0. +# if you aren't locally, that can cause different behaviour. +linkcheck_ignore = [ + # server is incompatible with openssl 3.0 default, see e.g. + # https://github.com/urllib3/urllib3/issues/2653 + r"https://doi.org/10.2172/7297293", + r"https://doi.org/10.2172/1372790", + # these work but linkcheck doesn't like them.. + r"https://doi.org/10.2172/1334107", + r"https://doi.org/10.13182/FST91-A29553", + r"https://doi.org/10.1080/10420150.2018.1462361", + r"https://github.com/cfs-energy/cfspopcon/blob/main/docs/doc_sources/getting_started.ipynb", +] +linkcheck_retries = 5 +linkcheck_timeout = 120 + +source_suffix = ".rst" + +# If docs change signficantly such that navigation depth is more, this setting +# might need to be increased +html_theme_options = { + "navigation_depth": 3, +} + +# The master toctree document. +master_doc = "index" + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "friendly" +highlight_language = "python3" + +# -- Options for HTML output + +html_static_path = ["static"] +html_theme = "sphinx_rtd_theme" +html_domain_indices = False +html_use_index = False +html_show_sphinx = False +htmlhelp_basename = "cfspopconDoc" +python_maximum_signature_line_length = 90 +# +# -- extensions and their options +# + +extensions = [ + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.intersphinx", + # linkcode to point to github would be nicer + "sphinx.ext.viewcode", + "sphinx.ext.mathjax", + "matplotlib.sphinxext.plot_directive", + "sphinx_copybutton", + "sphinxcontrib.bibtex", + "nbsphinx", +] + +# -- nbsphinx +exclude_patterns = ["_build", "static"] +nbsphinx_execute = "never" + +# -- autodoc +autodoc_default_options = { + "show-inheritance": True, + "members": True, + "undoc-members": True, + "member-order": "bysource", +} +autoclass_content = "both" +autodoc_typehints = "signature" + +# -- doctest +doctest_global_setup = """ +from cfspopcon import * +""" + +# -- intersphinx +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable/", None), + "matplotlib": ("https://matplotlib.org/stable/", None), + "pandas": ("https://pandas.pydata.org/docs/", None), + "scipy": ("https://docs.scipy.org/doc/scipy/", None), + "pint": ("https://pint.readthedocs.io/en/stable/", None), + "xarray": ("https://docs.xarray.dev/en/stable/", None), +} + +# -- matplotlib plot_directive +# only plot a png +plot_formats = ["png"] +# don't show link to the png +plot_html_show_formats = False + +# -- copybutton +# make copy paste of code blocks nice on copy remove the leading >>> or ... of +# code blocks and remove printed output. Their default is usually good but +# currently a bit broken so we need the below +copybutton_exclude = ".lineos" +copybutton_prompt_text = r">>> |\.\.\. " +copybutton_prompt_is_regexp = True +copybutton_only_copy_prompt_lines = True + +# -- bibtex bibliography +bibtex_bibfiles = ["refs.bib"] + + +# register a resolve function to help sphinx with the resolve references sphinx +# couldn't note: sphinx doesn't stop calling listeners once one with lower +# priority has returned a good result so this function is called pretty much +# for every cross-reference, thus we need to filter out the cases we actually +# want to handle +def resolve(app, env, node, contnode): + """Custom reference resolver.""" + ret_node = None + + if node["refdomain"] == "py" and node["reftype"] == "class": + py = env.domains["py"] + + # type hint links are transformed into something like + # :py:class:`numpy.float64` but `numpy.float64` is actually documented + # as a :py:attr:. We just use the general :py:obj: here which should be + # fine as long as there aren't any name collisions in numpy + if "numpy" in node["reftarget"]: + node["reftype"] = "obj" + ret_node = missing_reference(app, env, node, contnode) + + # This is a similar fix to above. We have cases where we use a generic + # type e.g. cfspopcon.strict_base.T and that is is a :py:attr: so we + # run into the same case as above. Same sledgehammer approach of + # just using :py:obj: for any missing links at this tag + elif "cfspopcon" in node["reftarget"]: + node["reftype"] = "obj" + ret_node = py.resolve_xref(env, node["refdoc"], app.builder, node["reftype"], node["reftarget"], node, contnode) + + # patch Self return types to point to the class the function is defined + # on + elif "typing_ext" in node["reftarget"]: + node["reftarget"] = node["py:class"] + ret_node = py.resolve_xref(env, node["refdoc"], app.builder, node["reftype"], node["reftarget"], node, contnode) + + elif "pint" in node["reftarget"]: + s = node["reftarget"] + if s.startswith("pint") and s.endswith("Quantity"): + node["reftarget"] = "pint.Quantity" + ret_node = missing_reference(app, env, node, contnode) + + return ret_node + + +# the below workaround is adopted from: +# https://github.com/celery/celery/blob/1683008881717d2f8391264cb2b6177d85ff5ea8/celery/contrib/sphinx.py#L42 +# which is BSD3 licensed see: +# https://github.com/celery/celery/blob/1683008881717d2f8391264cb2b6177d85ff5ea8/LICENSE#L1 + +# wraps_ufunc returns a class which leads to sphinx ignoring the function +# This is a custom documenter to ensure automodule correctly lists wrapped functions +# and creates a better signature for them. Setting the signature object on the actual class (like for Algorithms) +# isn't possible because the __call__ function is always a member of the class and setting it on an instance +# does not work. +class FunctionWrapperDocumenter(FunctionDocumenter): + """Document a wraps_ufunc wrapped function""" + + # this means `autowraps_ufunc` is a new autodoc directive + objtype = "wraps_ufunc" + # but document those as functions + directivetype = "function" + member_order = 11 + + @classmethod + def can_document_member(cls, member, membername, isattr, parent): + return super().can_document_member(member, membername, isattr, parent) and hasattr(member, "unitless_func") + + def format_args(self): + fw = self.object + sig = signature(fw) + return stringify_signature(sig, unqualified_typehints=True) + + def document_members(self, all_members=False): + super(FunctionDocumenter, self).document_members(all_members) + + def get_object_members(self, want_all: bool): + members = get_class_members(self.object, self.objpath, self.get_attr, self.config.autodoc_inherit_docstrings) + unitless_func = members.get("unitless_func", None) + if unitless_func is not None: + unitless_func.object.__doc__ = "A scalar and not unit aware version of the above function." + # the unitless function will get documented as a member of the FuncitionWrapper clas + # but sphinx pops the first argument because it thinks that's the "self" so we monkey patch around that + # by prepending a parameter that gets thrown away + tmp_param = Parameter("tmp", kind=Parameter.POSITIONAL_ONLY) + s = signature(unitless_func.object) + new_sig = s.replace(parameters=[tmp_param, *s.parameters.values()], return_annotation=s.return_annotation) + unitless_func.object.__signature__ = new_sig + return False, [unitless_func] + + +class AlgDocumenter(ClassDocumenter): + """Document a Algorithm instance.""" + + objtype = "popcon_alg" + # data so that we don't get the "class" prefix in sphinx + directivetype = "data" + member_order = 21 + + @classmethod + def can_document_member(cls, member, membername, isattr, parent): + return isinstance(member, Algorithm) + + def add_directive_header(self, sig: str) -> None: + super(ClassDocumenter, self).add_directive_header(sig) + + def get_object_members(self, want_all: bool): + members = get_class_members(self.object, self.objpath, self.get_attr, self.config.autodoc_inherit_docstrings) + return False, [m for k, m in members.items() if k in {"run", "update_dataset", "return_keys"}] + + def format_signature(self, **kwargs) -> str: + return "" + + def get_doc(self): + return None + + def import_object(self, raiseerror: bool = False) -> bool: + ret = super().import_object(raiseerror) + self.doc_as_attr = False + return ret + + +def setup(app): + # default is 900, intersphinx is 500 + app.connect("missing-reference", resolve, 1000) + app.add_css_file("theme_overrides.css") + app.add_autodocumenter(FunctionWrapperDocumenter) + app.add_autodocumenter(AlgDocumenter) diff --git a/docs/doc_sources/Usage.rst b/docs/doc_sources/Usage.rst new file mode 100644 index 00000000..ad80ef6d --- /dev/null +++ b/docs/doc_sources/Usage.rst @@ -0,0 +1,38 @@ +.. _gettingstarted: + +Getting Started +=================== + +Installation +^^^^^^^^^^^^^ + +The cfspopcon package is available on the `Python Package Index `, thus installation is as simple as: + +.. code:: + + >>> pip install cfspopcon + +.. warning:: + The :code:`cfspopcon.atomic_data` module requires data files produced by the `radas project `_. Radas produces these files by processing `OpenADAS `_ data. These files are not shipped as part of :code:`cfspopcon`. Follow the below steps after the :code:`pip install cfspopcon` command (we will try to make this smoother in the future. N.b. this only has to be done once). + + .. code:: bash + + >>> export RADAS=$(python -c "from cfspopcon import atomic_data;from pathlib import Path; print(Path(atomic_data.__file__).parent)") + >>> pushd /tmp + >>> git clone https://github.com/cfs-energy/radas.git + >>> pushd radas + >>> poetry install --only main + >>> poetry run fetch_adas + >>> poetry run run_radas + >>> cp ./cases/*/output/*.nc $RADAS + >>> popd && popd + + +Example Notebook +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The example notebook linked below can be found within the `docs folder `_ of our github repository. + +.. toctree:: + + getting_started diff --git a/docs/doc_sources/api.rst b/docs/doc_sources/api.rst new file mode 100644 index 00000000..d55a0e49 --- /dev/null +++ b/docs/doc_sources/api.rst @@ -0,0 +1,26 @@ +API +********* + + + +Configuration Enums +===================== +.. automodule:: cfspopcon.named_options + +Algorithms +===================== +.. automodule:: cfspopcon.algorithms + +Internals +===================== + +The functions and classes below are listed here for completeness. +But these are internals, so it should usually not be required to interact with any of them directly. + +.. py:currentmodule:: none + +.. autoclass:: cfspopcon.unit_handling.Unitfull +.. automodule:: cfspopcon.algorithms.algorithm_class +.. automodule:: cfspopcon.formulas +.. automodule:: cfspopcon.formulas.scrape_off_layer_model +.. automodule:: cfspopcon.helpers diff --git a/docs/doc_sources/bib.rst b/docs/doc_sources/bib.rst new file mode 100644 index 00000000..816eb3c5 --- /dev/null +++ b/docs/doc_sources/bib.rst @@ -0,0 +1,6 @@ +Bibliography +============= + +.. bibliography:: + :all: + :style: unsrt diff --git a/docs/doc_sources/dev_guide.rst b/docs/doc_sources/dev_guide.rst new file mode 100644 index 00000000..794d0aec --- /dev/null +++ b/docs/doc_sources/dev_guide.rst @@ -0,0 +1,167 @@ +.. _devguide: + +Developer's Guide +******************* + +The cfspopcon team uses `Poetry `_ to develop. +If you are familiar with the usual poetry based development workflow, feel free to skip right ahead to the `Contribution Guidelines`_. + +Development Setup +==================== + +For more information and help installing Poetry, please refer to `their documentation `_. +Once you have Poetry installed we are ready to start developing. First we clone the repository and enter into the folder. + +.. code:: + + >>> git clone https://github.com/cfs-energy/cfspopcon.git + >>> cd cfspopcon + +Setting up a virtual environment and installing all dependencies required to develop, is done in just one command: + +.. code:: + + >>> poetry install + +If you are new to Poetry, we suggest that you at least read their brief introduction on `how to use this virtual environment `_. +You can verify that everything worked as expected by following the :ref:`Getting Started ` guide. + +At this point you are ready to read our `Contribution Guidelines`_ and start making changes to the code. We are looking forward to your contribution! + + +Contribution Guidelines +======================== + +If you have a question or found a bug, please feel free to raise an issue on GitHub. + +If you would like to make changes to the code, we ask that you follow the below guidelines: + +1. Please follow our `Style Guide`_ +2. The `Pre-Commit Checks`_ should all pass +3. Make sure tests in the test suite are still passing, see `Running the Test Suite`_ +4. If adding new functionality, please try to add a unit test for it, if applicable. +5. Please ensure that any changes are correctly reflected in the documentation, see `Building The Documentation`_ + + + +Style Guide +============= + +The set of tools configured to run as pre-commit hooks should cover the simple style decisions. +For everything else, we follow the `Google Python Style Guide `_, but make some exceptions for science / math variables. +The Google style guide and PEP8 encourage long, descriptive, lower case variables names. However, these can make science / math equations hard to read. +There is a case to be made for using well-established mathematical symbols as **local** variable names, e.g. :code:`T` for temperature or :code:`r` for position. +Subscripts can be added, e.g. :code:`r_plasma`. + +To make reading & validating formulas easier, we additionally follow the below guidelines: + +- Add a descriptive comment when using short variable names. +- When local variables are declared, specify their units in a comment next to the declaration, like :code:`x = 1.0 # [m]` +- Use basic SI units, unless you have a good reason not to. (e.g. prefer :code:`[A]` over :code:`[kA]`). +- Explicitly call out dimensionless physical quantities, e.g. :code:`reynolds_number = 1e3 # [~]`. +- Functions that handle dimensional quantities should use :class:`pint.Quantity`. + +Please note, that while we have some checks for docstrings, those checks do not cover all aspects. +So let's look at a basic example, the :func:`~cfspopcon.formulas.calc_plasma_volume` function: + +.. literalinclude:: ../../cfspopcon/formulas/geometry.py + :language: python + :linenos: + :pyobject: calc_plasma_volume + +To summarize the important points of the above example: + +1. Include short descriptive one-liner. +2. If applicable, add a more detailed description. +3. List the arguments with a short description, and include their units. +4. Each return value should come with a brief explanation and unit. +5. Do **not** include any type annotations within the docstring. These will be added automatically by sphinx. + +Aside from the units annotations in the docstring, you'll notice the parameters are annotated with the type :class:`~cfspopcon.unit_handling.Unitfull`. +This is because all calculations in cfspopcon use explicit unit handling to better ensure that calculations are correct and no units handling errors sneak into a formula. +The units handling cfspopcon is powered by the `pint `_ and `pint-xarray `_ python packages. +The type :class:`~cfspopcon.unit_handling.Unitfull`, used in the above function as type annotation, is an alias of :code:`pint.Quantity | xarray.DataArray`. + +In addition to the above example, we also recommend having a look at the :mod:`~cfspopcon.formulas` module, which holds many good examples. + + +Pre-Commit Checks +=================== + +As the name suggests, these are a list of checks that should be run before making a commit. +We use the `pre-commit `_ framework to ensure these checks are run for every commit. +You already installed the :code:`pre-commit` tool as a development dependency during the `Development Setup`_. + +Run all configured checks by executing: + +.. code:: + + >>> poetry run pre-commit run --all-files + +But instead of trying to remember to run this command before every commit, we suggest you follow the `pre-commit documentation `_ and install the git hooks. + +.. code:: + + >>> poetry run pre-commit install + +The installed git hooks will now automatically run the required checks when you try to :code:`git commit` some changes. +An added benefit is that this will usually be faster than running over all files, as :code:`pre-commit` is pretty smart at figuring out which files it needs to check for a given commit. + +If you are curious, you can see all the automatic checks that we have configured to run in the file :code:`.pre-commit-config.yaml`: + +.. literalinclude:: ../../.pre-commit-config.yaml + + + + +Running the Test Suite +======================= + +We use `pytest `_ and the `pytest-cov `_ plugin for our test suite. +All tests can be found in the :code:`tests` subfolder. +The configuration can be found in the :code:`pyproject.toml` file. + +Running the entire test suit can be done via: + +.. code:: + + >>> poetry run pytest + +Adding a new Test +------------------- + +When adding new functionality it is best to also add a test for it. +If the category of the added functionality fits within one of the existing files, please add your test to that file. +Otherwise feel free to create a new test file. The name should follow the convention :code:`test_{description}.py`. + + +Building The Documentation +=============================== + +Our documentation is build and hosted on `Read The Docs `_ and previews are available on each PR. +But when extending the documentation it is most convenient to first build it locally yourself to check that everything is included & rendered correctly. + +.. warning:: + Building the documentation unfortunately requires a non-python dependency: `pandoc `_. + Please ensure that the :code:`pandoc` executable is available before proceeding. + This package can easily be installed via :code:`sudo apt-get install pandoc` (Linux) or :code:`brew install pandoc` (MacOS). + For more details please see `pandoc's installation guide `_. + +Starting from inside the project folder you can trigger the build by running: + +.. code:: + + >>> poetry run make -C docs html + +Once that build is finished, open the file :code:`./docs/_build/html/index.html` to view the documentation. + +As part of our CI we also run the `sphinx-doctest `_ and `sphinx-linkcheck `_ extensions. +The :code:`sphinx-doctest` extension checks that python snippets used in docstrings are actually valid python code and produce the expected output. And :code:`sphinx-linkcheck` is used to ensure that any links used within our documentation are correct and accessible. + +To avoid having failures in the CI it's a good idea to run these locally first as well: + +.. code:: + + poetry run make -C docs doctest + poetry run make -C docs linkcheck + diff --git a/docs/doc_sources/getting_started.ipynb b/docs/doc_sources/getting_started.ipynb new file mode 100644 index 00000000..68dd28ea --- /dev/null +++ b/docs/doc_sources/getting_started.ipynb @@ -0,0 +1,2642 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Creating your first POPCON\n", + "\n", + "Welcome to cfspopcon!\n", + "\n", + "This notebook will work you through how to set up a POPCON run and plot the results.\n", + "\n", + "To start with, execute the cell below to import some additional libraries that we'll frequently use, as well as the cfspopcon library itself. If you can execute this cell without error, that's a great start. If not, make sure that the cfspopcon library is installed correctly." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import xarray as xr\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from pathlib import Path\n", + "\n", + "import cfspopcon\n", + "from cfspopcon.unit_handling import ureg" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The simplest way to configure a POPCON analysis is via a configuration file. For this, we use YAML files (which map neatly to python dictionaries).\n", + "\n", + "In the next cell, we read in the `SPARC_PRD/input.yaml` file, applying a few conversions on the data. This includes\n", + "\n", + "1. The `algorithms` entry is converted into a `cfspopcon.CompositeAlgorithm` which we'll talk about later. This basically gives the list of operations that we want to perform on the input data. \n", + "2. The `points` entry is stored in a separate dictionary. This gives a set of key-value pairs of 'optimal' points (for instance, giving the point with the maximum fusion power gain).\n", + "3. The `grids` entry is converted into an `xr.DataArray` storing a `np.linspace` or `np.logspace` of values which we scan over. We usually scan over `average_electron_density` and `average_electron_temp`, but there's nothing preventing you from scanning over other numerical input variables or having more than 2 dimensions which you scan over (n.b. this can get expensive!).\n", + "4. Each input variable is checked to see if its name matches one of the enumerators in `cfspopcon.named_options`. These are used to store switch values, such as `cfspopcon.named_options.ReactionType.DT` which indicates that we're interested in the DT fusion reaction.\n", + "5. Each input variable is converted into its default units, stored in `cfspopcon.unit_handling.default_units.DEFAULT_UNITS`. This will set, for instance, the `average_electron_temp` values to have units of `keV`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "input_parameters, algorithm, points = cfspopcon.read_case(\"../../example_cases/SPARC_PRD\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first want to make sure that our analysis won't crash due to missing input variables. For this, we use the `validate_inputs` method of the `cfspopcon.CompositeAlgorithm` object, which makes sure that all required input variables are defined by the `input.yaml` file. It will also tell you if the algorithms you're requesting are out of order." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "algorithm.validate_inputs(input_parameters);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since we're looking at the example, it's unsurprisingly well behaved. Let's intentionally drop an input variable to show that it works." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/j9/kfmd11x90hbgylhpfwhtqzyw0000gq/T/ipykernel_64214/170706882.py:4: UserWarning: Missing input parameters [major_radius].\n", + " algorithm.validate_inputs(incomplete_input_parameters, raise_error_on_missing_inputs=False);\n" + ] + } + ], + "source": [ + "incomplete_input_parameters = input_parameters.copy()\n", + "del incomplete_input_parameters[\"major_radius\"]\n", + "\n", + "algorithm.validate_inputs(incomplete_input_parameters, raise_error_on_missing_inputs=False);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we pack all of the (complete) input parameters into an `xarray.Dataset`.\n", + "\n", + "If you're not familiar with `xarray`, a `Dataset` functions like a dictionary which stores labelled `xr.DataArray`s, which in turn function like `np.array`s but with additional annotation to describe the coordinates and units of the array. We'll use a lot of `xarray` features, so it's worth [reading the docs](https://docs.xarray.dev/en/stable/), including their useful [How do I ...](https://docs.xarray.dev/en/stable/howdoi.html) section.\n", + "\n", + "Our starting dataset isn't super interesting: it's exactly what we defined in the `input.yaml` file. In the next cell, we construct a dataset from out input parameters, and then print into the notebook a representation of the notebook (this is the somewhat odd-looking second line)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:                               (dim_species: 3,\n",
+       "                                           dim_average_electron_density: 40,\n",
+       "                                           dim_average_electron_temp: 30)\n",
+       "Coordinates:\n",
+       "  * dim_species                           (dim_species) object Impurity.Tungs...\n",
+       "  * dim_average_electron_density          (dim_average_electron_density) float64 ...\n",
+       "  * dim_average_electron_temp             (dim_average_electron_temp) float64 ...\n",
+       "Data variables: (12/36)\n",
+       "    major_radius                          float64 [m] 1.85\n",
+       "    magnetic_field_on_axis                float64 [T] 12.2\n",
+       "    inverse_aspect_ratio                  float64 [] 0.3081\n",
+       "    areal_elongation                      float64 [] 1.75\n",
+       "    elongation_ratio_sep_to_areal         float64 [] 1.125\n",
+       "    triangularity_psi95                   float64 [] 0.3\n",
+       "    ...                                    ...\n",
+       "    SOL_momentum_loss_function            object MomentumLossFunction.KotovRe...\n",
+       "    fraction_of_P_SOL_to_divertor         float64 [] 0.6\n",
+       "    kappa_e0                              float64 [W/eV³⋅⁵/m] 2.6e+03\n",
+       "    target_electron_temp                  float64 [eV] 25.0\n",
+       "    average_electron_density              (dim_average_electron_density) float64 [1e19 m^-3] ...\n",
+       "    average_electron_temp                 (dim_average_electron_temp) float64 [keV] ...
" + ], + "text/plain": [ + "\n", + "Dimensions: (dim_species: 3,\n", + " dim_average_electron_density: 40,\n", + " dim_average_electron_temp: 30)\n", + "Coordinates:\n", + " * dim_species (dim_species) object Impurity.Tungs...\n", + " * dim_average_electron_density (dim_average_electron_density) float64 ...\n", + " * dim_average_electron_temp (dim_average_electron_temp) float64 ...\n", + "Data variables: (12/36)\n", + " major_radius float64 [m] 1.85\n", + " magnetic_field_on_axis float64 [T] 12.2\n", + " inverse_aspect_ratio float64 [] 0.3081\n", + " areal_elongation float64 [] 1.75\n", + " elongation_ratio_sep_to_areal float64 [] 1.125\n", + " triangularity_psi95 float64 [] 0.3\n", + " ... ...\n", + " SOL_momentum_loss_function object MomentumLossFunction.KotovRe...\n", + " fraction_of_P_SOL_to_divertor float64 [] 0.6\n", + " kappa_e0 float64 [W/eV³⋅⁵/m] 2.6e+03\n", + " target_electron_temp float64 [eV] 25.0\n", + " average_electron_density (dim_average_electron_density) float64 [1e19 m^-3] ...\n", + " average_electron_temp (dim_average_electron_temp) float64 [keV] ..." + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset = xr.Dataset(input_parameters)\n", + "\n", + "dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's run a POPCON!\n", + "\n", + "We'll use the `update_dataset` method of our algorithm and pass in our dataset of input parameters.\n", + "\n", + "The `CompositeAlgorithm` calls the `update_dataset` for each of its `Algorithm`s. These calls check that all of the required inputs are defined in the dataset, and then write the results back into the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:                               (dim_species: 3,\n",
+       "                                           dim_average_electron_density: 40,\n",
+       "                                           dim_average_electron_temp: 30,\n",
+       "                                           dim_rho: 50)\n",
+       "Coordinates:\n",
+       "  * dim_species                           (dim_species) object Impurity.Tungs...\n",
+       "  * dim_average_electron_density          (dim_average_electron_density) float64 ...\n",
+       "  * dim_average_electron_temp             (dim_average_electron_temp) float64 ...\n",
+       "Dimensions without coordinates: dim_rho\n",
+       "Data variables: (12/115)\n",
+       "    major_radius                          float64 [m] 1.85\n",
+       "    magnetic_field_on_axis                float64 [T] 12.2\n",
+       "    inverse_aspect_ratio                  float64 [] 0.3081\n",
+       "    areal_elongation                      float64 [] 1.75\n",
+       "    elongation_ratio_sep_to_areal         float64 [] 1.125\n",
+       "    triangularity_psi95                   float64 [] 0.3\n",
+       "    ...                                    ...\n",
+       "    core_radiated_power_fraction          (dim_average_electron_density, dim_average_electron_temp) float64 [] ...\n",
+       "    nu_star                               (dim_average_electron_density, dim_average_electron_temp) float64 [] ...\n",
+       "    rho_star                              (dim_average_electron_temp) float64 [] ...\n",
+       "    fusion_triple_product                 (dim_average_electron_density, dim_average_electron_temp) float64 [1e10 m^-3·keV·s] ...\n",
+       "    peak_pressure                         (dim_average_electron_temp, dim_average_electron_density) float64 [Pa] ...\n",
+       "    current_relaxation_time               (dim_average_electron_temp, dim_average_electron_density) float64 [s] ...
" + ], + "text/plain": [ + "\n", + "Dimensions: (dim_species: 3,\n", + " dim_average_electron_density: 40,\n", + " dim_average_electron_temp: 30,\n", + " dim_rho: 50)\n", + "Coordinates:\n", + " * dim_species (dim_species) object Impurity.Tungs...\n", + " * dim_average_electron_density (dim_average_electron_density) float64 ...\n", + " * dim_average_electron_temp (dim_average_electron_temp) float64 ...\n", + "Dimensions without coordinates: dim_rho\n", + "Data variables: (12/115)\n", + " major_radius float64 [m] 1.85\n", + " magnetic_field_on_axis float64 [T] 12.2\n", + " inverse_aspect_ratio float64 [] 0.3081\n", + " areal_elongation float64 [] 1.75\n", + " elongation_ratio_sep_to_areal float64 [] 1.125\n", + " triangularity_psi95 float64 [] 0.3\n", + " ... ...\n", + " core_radiated_power_fraction (dim_average_electron_density, dim_average_electron_temp) float64 [] ...\n", + " nu_star (dim_average_electron_density, dim_average_electron_temp) float64 [] ...\n", + " rho_star (dim_average_electron_temp) float64 [] ...\n", + " fusion_triple_product (dim_average_electron_density, dim_average_electron_temp) float64 [1e10 m^-3·keV·s] ...\n", + " peak_pressure (dim_average_electron_temp, dim_average_electron_density) float64 [Pa] ...\n", + " current_relaxation_time (dim_average_electron_temp, dim_average_electron_density) float64 [s] ..." + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "algorithm.update_dataset(dataset, in_place=True)\n", + "\n", + "dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plotting and interrogating the results\n", + "\n", + "That's it: the only thing left is to look at our results. We can use the built-in plotting functionality, which is configured by dictionaries which we read in from YAML files using `read_plot_style`.\n", + "\n", + "Nothing fancy is happening here: it's just reading in a dictionary from a file and not doing any conversions. You can modify the YAML file, or directly make a dictionary yourself. The structure of the dictionary is\n", + "\n", + "* `type`: what sort of plot do you want to make. Currently we only support `popcon`, but room for growth.\n", + "* `figsize`: the size of the figure in inches, defining both the aspect ratio and text size of the resulting plot. If you want larger overall labels, try reducing `figsize`\n", + "* `show_dpi`: the pixels-per-inch of the resulting figure. Increase this if your figure is blurry. This will also make the figure larger in the Jupyter notebook.\n", + "* `save_as`: a name for the figure when saving it as a `.png`\n", + "* `coords` or `new_coords`: what to use as the x-axis and y-axis. `coords` must be already in the coordinates of the dataset, while `new_coords` can be output variables (see the example below)\n", + "* `fill`: a block for a variable to be plotted as a colormesh. Inside this, we define a section `where` which we use to build a mask (discussed below)\n", + "* `points`: a block for points to be highlighted on the plot. These must correspond to points defined in the `input.yaml` file\n", + "* `contour`: a block for variables which we should plot contours for. We pick a single color per contour and then label the contour lines themselves at specific values, which lets us show multiple variables at once\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'type': 'popcon',\n", + " 'figsize': [8, 6],\n", + " 'show_dpi': 150,\n", + " 'save_as': 'SPARC_PRD',\n", + " 'coords': {'x': {'dimension': 'average_electron_temp',\n", + " 'label': '$$ [$keV$]',\n", + " 'units': 'keV'},\n", + " 'y': {'dimension': 'average_electron_density',\n", + " 'label': '$$ [$10^{20} m^{-3}$]',\n", + " 'units': 'n20'}},\n", + " 'fill': {'variable': 'Q',\n", + " 'where': {'Q': {'min': 1.0},\n", + " 'P_auxillary': {'min': 0.0, 'max': 25.0, 'units': 'MW'},\n", + " 'greenwald_fraction': {'max': 0.9},\n", + " 'ratio_of_P_SOL_to_P_LH': {'min': 1.0}}},\n", + " 'points': {'PRD': {'label': 'PRD',\n", + " 'marker': 'x',\n", + " 'color': 'red',\n", + " 'size': 50.0}},\n", + " 'contour': {'Q': {'label': '$Q$',\n", + " 'levels': [0.1, 1.0, 2.0, 5.0, 10.0, 50.0],\n", + " 'color': 'tab:red',\n", + " 'format': '1.2g'},\n", + " 'ratio_of_P_SOL_to_P_LH': {'label': '$P_{SOL}/P_{LH}$',\n", + " 'color': 'tab:blue',\n", + " 'levels': [1.0],\n", + " 'format': '1.2g'},\n", + " 'P_auxillary': {'label': '$P_{aux}$',\n", + " 'levels': [1.0, 5.0, 10.0, 25.0, 50.0],\n", + " 'color': 'tab:gray',\n", + " 'format': '1.2g'},\n", + " 'P_fusion': {'label': '$P_{fusion}$',\n", + " 'color': 'tab:purple',\n", + " 'levels': [50.0, 100.0, 150.0, 200.0],\n", + " 'format': '1.2g'}}}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot_style = cfspopcon.read_plot_style(\"../../example_cases/SPARC_PRD/plot_popcon.yaml\")\n", + "\n", + "plot_style" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Once we have our `plot_style`, we call `cfspopcon.plotting.make_plot` to make a figure.\n", + "\n", + "N.b. we've set `output_dir=None` to stop `make_plot` from saving the figure to a `.png` file. If you're using the command-line tool, you can delete the `save_as` key in `plot_style`.\n", + "\n", + "It's pretty easy to make this plot, but not entirely straightforward to interpret it.\n", + "\n", + "Firstly, the axes are for the average density and for the average temperature. These are more often the outputs of a calculation, rather than the independent variables. This is a consequence of the particular 'back to front' algorithm that we're using, which uses the average temperature and density to define the plasma stored energy and the resulting confinement time and input power required to stay at that point.\n", + "\n", + "Next, it's helpful to remember that all of the points shown are completely independent. Each represents a time-independent solution of the given algorithm.\n", + "\n", + "Although we get a solution at all $(\\bar n_e, \\bar T_e)$ points, they don't all make sense as operational points. There are a set of limits that we impose via the `where` block inside the `fill` block. For this example, these are\n", + "\n", + "1. We're looking for high fusion gains, with at least $Q>1$,\n", + "2. Since we're using the ITER98y2 H-mode energy confinement scaling, we require that $P_{SOL} > P_{LH}$,\n", + "3. We can't switch off the Ohmic power, so we neglect points with $P_{RF} <= 0$,\n", + "4. To avoid density-limit disruptions, we require that the volume-averaged density is no more than 90% of the Greenwald density limit,\n", + "5. To avoid damaging the magnets with neutrons, we impose a limit of $P_{fusion} < 140MW$.\n", + "\n", + "We mask points which don't meet these requirements, and then plot a variable over the unmasked region (in this case, we're plotting $Q$).\n", + "\n", + "On top of this, we plot contours of fields of interest such as the divertor heat-flux metric $P_{SOL} B_{pol} / R n^2$ so we can see the trends of these field as we go across the accessible parameter space.\n", + "\n", + "Finally, within the accessible parameter, we select points which minimize or maximize the values of fields, such as the point giving the maximum value of $Q$.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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N998E5mZmSMeZ/HixXjppZcAAMXFxfj73//u8lry8/OxaNEiAMCBAwckt/3617+G2WxGbGws3n//fYSFhY16rJSUFGzdulVy3d/+9jcUFxcDAF566SWcfvrpI+6fnp6ON998E4AtU+mPf/zjiNtqNBohg2Dz5s2ora0ddW2T8emnn2LdunVISkpCUFAQIiIicO655+Ivf/kLjEajZNv29nYkJyeD4zisWbPG6fHMZjOWLFkCjuMwd+5cGAwG4TaTyYStW7fiZz/7GRYvXoyEhAQolUrExsZi1apVeOedd0bsgSLu6QMABQUF+PGPf4zExESo1Wrk5eXh//2//wez2Szss2/fPqxZswYJCQlQqVSYPXs2Nm/ePOJ9iJsL63Q63H///UKflujoaKxZswY//PCDK0/vMPv27cP111+P1NRUqFQqhIWF4fTTT8fTTz+N3t7eSR3bFd9//z1eeuklZGdnO82Mm4g33ngDAHDttdciPT192O2//OUvERISIvS3coVerxd62Nx+++0IDw8fts39998PAOjp6cFHH33k2uIHdXZ24t5770VmZiZUKhUSEhJw9dVX49ChQ+Pa32q14u2338Yll1yCuLg4KJVKxMTE4MILL3T6+33kyBHh97qgoGDUY994443gOA7nnXeecF1lZSX27t0LALjnnnugUCiG7Wd/Xqqrq7F79+5xPQ5CCCHEZ3wcOCKEkIAwVsYNY4xt3rxZ2Gbfvn2MMcaMRiPTarUMAFu+fPm47stqtbLMzEwGgOXl5Q27fayMG8YYu/rqq4U+OHb79+8X1vf444+Pay3O2Pv0ZGRkjLuvxooVK4SsAHE2EmOOjJtly5Yxo9EoZC7dfPPNw44z2Yybvr4+dtVVV0l66mi1WklfjDPPPHNY5sKuXbuEniIvv/zysOM+8MADQtZFcXHxiGu239/QPkBXX301s1gsoz7e7du3Cz2VhvbyuPbaaxljtp4fMpmMcRzHwsLCJPdx3333OX1O7Bkzzz33HMvJyWEAmFKpFH5vATCe59nf//73Ufd3lnFjsVjY//3f/w3r6yTux5STk8Oqq6udHns0rmbcGAwGlpeXxziOY7t27WKMsUln3JSWlgqP47333htxu4svvlj43XLF559/Lhx///79I26Xl5cn+T1wRVVVlfAzHPqzVyqV7OOPPx4146a9vZ2de+65kp/x0N+91atXD+vxY8/au+eee0ZcW29vL9NoNAwA27Jli3D9K6+8Ihy7ubnZ6b5ms1l4nf32t78d9fFP5m8KIYQQ4g6UcUMIIV4innIUGRkJADh48CB6enoAAOvWrRvXccSZHcePH0dzc/OE12JfBwB89dVXwvkrr7zS5WMCQGNjo5BNdOWVVwqZIGNZu3YtAFtWwGjf4isUCjzxxBMAbJkM9swed/nZz36G//73v8jIyMDbb78t9Arp6+vDxx9/jIyMDHz//ffYsGGDZL9ly5bhgQceAGD7hr+wsFC4bdeuXfjDH/4AAHj++eeRn58v2Tc4OBi33XYb/ve//wn319PTg/b2drz44ovQarX4z3/+g5dffnnUtf/kJz/BFVdcgVOnTqGrqwvd3d1CVsG7776Lp556CnfccQfuuOMONDU1oaurCx0dHbjpppsAAM888wzKy8tHPP6jjz6KlpYWvPfee9Dr9eju7kZJSQmWLVsGq9WK2267DYcPHx7fEz3okUcewUsvvYTY2Fhs3rwZ7e3t0Ol06O/vx86dO7FgwQKUlZVh7dq1sFqtLh3bVY899hiOHz+On/70p1i2bJlbjllUVCScnz179ojb2W8rKSnx6PFdfb1YLBZcffXVOHXqFCIiIiQ/++LiYpxxxhlYv379qPuvXbsWu3fvxvz587Ft2zbo9Xp0dXWht7cX//znPxEbG4utW7fivvvuk+x74403AgD+9a9/jfiz//DDD6HX66HRaCR/P+3PS2xsLGJjY53uK5PJkJubC8D154UQQgjxOl9HjgghJBCMlXHT3d0tTGmKjIwUsidee+01Yb+9e/eO+/7efPNNYb8vv/xScttYGTc//PCDkB1yxRVXCNfbe2UEBQU5ze4Yj//973/Cut56661x77dnzx5hv7/97W+S28QZN4zZMo4WLVokfFMvNpmMm927dzMALDY2ltXU1Djdpra2VviG/8iRI5LbzGYzW7JkCQPA8vPzWV9fH2tra2NJSUkMAFu7dq1L67H7z3/+wwCwzMzMYbeJH+8FF1zgNMNp6dKlwja33HLLsNvNZjNLT08fMdNKnG0x9HeNMVuWUlZWFgPALrnkkhH3H5pxU1VVxWQyGVOr1ezo0aNOH3tPTw9LTk5mANiHH37odJuRuJJxc/jwYSaXy1lcXJykT8xkM25eeukl4bnr7u4ecbsXXnhB2E6n0437+L/61a8YABYRETHqdva+PVFRUeM+NmOM/fvf/x71Z6/X64XsPzjJuHnjjTcYAJabmztiv6yDBw8yjuOYUqmUZMfU1dUJf6e++OILp/teeOGFDAC7/vrrJdevXbuWAWALFiwY9fGtWbOGAWCLFi0acRvKuCGEEOIPKOOGEEI8qKurC1999RVWrlyJhoYGAMBdd90Fnrf9+W1vbxe2jYqKGvdxo6OjhfPiY4ymoaEBb775Jq644gpYrVZwHCeZZGM/Tnh4uLA+V3nj8XAch6eeegoAsHXrVnz77bcurtI5e7+g6667DjNmzHC6TXJyMlasWAEA+OKLLyS3yWQy/Otf/0JERARKSkpw1113YcOGDaivr8eMGTPwt7/9bULruvTSSwEAFRUVQi8kZ+677z6nGU6rVq0SztszcIau294fZLR+IkuWLJH0EbFTq9W49957AQCff/45uru7RzyG2JYtW2CxWHDRRRdh3rx5TrcJDQ0VssuGPt/uYjabsWHDBpjNZrz00ktO+8RMlE6nE84HBwePuJ34NvE+4z3+aMcW3+7KsQFbphYw8s8+ODgYv/nNb0bc3/6auv3220fsl7Vo0SLMmjULRqMRO3fuFK5PSkrCypUrAUDogyXW2NgoZAnecMMNkts8/bwQQggh3ib39QIIISTQjFYedP311wslNZ72zTffjLgWhUKB5557DsuXL/fKWtzt/PPPx/nnn48vv/wS991337hHiY9m3759AGwfNp2NOLezByZOnTo17LaUlBS89tpruOqqq/Daa68BsAVG3nrrLURERIx4TJ1Oh1deeQWffPIJjh8/jq6uLphMpmHb1dXVIT4+3ukxRmoCHRcXB8BWFpeRkTHqNp2dnSOu0f4herTbrFYrDh8+LAS3RmN/vnfs2DHiYwIgNCd29ny7w1NPPYWjR4/isssuw49+9COP3MdUdfDgQQDj+9kPZbFY8P333wMANm3ahCeffHLEY3R0dAAY/jO+8cYb8eWXX0pKouz+9a9/wWKxIDExEeeff/74HhAhhBAyRVHghhBC3Mz+IRgAgoKCEB0djQULFuC6664b9oFWnJUy3swZAGhra3N6DDGFQiH0sOE4Dmq1GomJiTj77LNxyy23IDs72+laurq6YLVaJ5R148nHM9RTTz2F0047DXv37sW2bdtw+eWXj3+hTtgzonp6eoS+Q6Pp6+tzev26deuwbt06YdrPPffcg3PPPXfE45SXl+O8885DXV2dcF1wcLAk88nex0iv1494nNDQUKfXy+XyUW8Xb+MsWGSXlJQ0rttaWlpG3E7M/nzr9fpRH5fdSM/3ZJSUlODxxx9HSEgI/vznP7v9+OLnvK+vD1qt1ul24sc22s9ppOOP9dzYb3fl2IDjZznazz45Odnp9R0dHRgYGAAwekBQbOjjWLt2Le644w709vbigw8+kGTW2LNwrrvuumF/qzz9vBBCCCHeRoEbQghxs9HKWYYSN6o9fPgwlixZMq79jhw5IpyfNWuW023OPvts7Nq1a9xrsR9nYGAAx48fH/G4oxn6eK677rpx7TeexzPUokWLcPXVV+O9997D7373O6GkaKIsFgsA4C9/+Qt+/vOfT/g41dXV+PLLL4XL+/btg8VigUwmc7r9zTffjLq6OqSlpeGZZ57BypUrJU2jLRaLEFhhI4zsnorsz/d9990nlL552y9+8QsYjUY8+uijiIiIGDZ63D5GnTEm3BYUFOR0vLQziYmJwvn6+voRAzf19fUAAK1Wi5CQkHGv3378zs5O9Pf3Q61Wj3p88Xo8zf7zBYDPPvsMF110kcvH0Gg0WLt2Ld544w288cYbQuCmsLAQx44dAzC8TApwPE774x6JL54XQgghZCKoxw0hhPjQaaedJnzba8/QGAtjDB999BEAIC8vb9QyE1eIe1h8+OGHEzpGYmKiMKnlww8/HHeg4YMPPgBg++C6ePHicd/f73//e8jlchQVFTntg+EK+/M4mZIcs9mMH//4x+ju7kZ2djaCgoKwd+9ePP744063r62tFXr0vPPOO7jqqqskQRvAtUCgJ432IVh820hTfIZyx/M9WVVVVQBsvX9CQ0OHnd5++20AQE1NjXDd5s2bx3188aQn8QSooey3DZ045u7juxqMtf8sx/uzF4uKihICjpP5GdsDM19//bVwX/bX+vz58zFnzpxh+9ifl5aWFrS2tjo9rsViESbgTSRITQghhHgTBW4IIcSHFAoFbrnlFgC2njTjyZB56623UFlZCQC444473LaW0047TeiT8vLLL0vKl0YzdFTv7bffDsD2ofiNN94Yc//du3cLj/vWW28VPuyNx8yZM3HrrbcCAB5++GGhNGMi7NlOn3zyyYSP8cgjj+D7779HcHAwPvroIzz99NMAgCeeeAJ79+4dtn1tba1wfsGCBU6PKc7e8SVx49iRbuN5fsTHMZT9+f7yyy9hMBgmv0A/lJ2djZSUFAC2xs3O6PV6oUfThRde6NLxzznnHCHLZqTjnzp1CsePH5/Q8e1B1NF+9l9//bXT6xUKhfD3ZNu2bS7dr9jKlSuRnJwMq9UqjAa396Cyjwwf6oILLhDOj/S87Nu3T2hK7OrzQgghhHgbBW4IIcTH7rvvPuGb7RtuuAEVFRUjbnvo0CH83//9HwBbts1Pf/pTt67l//2//weZTIbm5masW7duzAlBdXV1wtQfu1tvvVXIurnrrrtw4MCBEfevqqoSvlGPi4sbdULNSB5++GFoNBrU1NS4lA0x1M9+9jMAtuyEv/zlL6Nuq9frYTQaJdft3LlTKPl5/vnnkZeXh7vuuguXXnopLBYLrrvuumG9PsSTduylH2I6nQ5PPPHEhB6Pu+3du9dpYNFgMODZZ58FYJtgNd6pTBs2bIBcLkdbWxseeeSRUbc1Go3Dypjcobq6GoyxEU/r168HAKSmpgrXiSexjYXjOCG48O6776K6unrYNps3b0Zvby9kMtm4SwvtNBoN1q1bB8BW4ufs9WoPHoondI3XNddcA2Dkn31/fz+eeeaZEfe3v6a2b9+O7du3j3pf9gbFQ/E8Lzwvb775ppB5I5PJ8JOf/MTpPhkZGTjnnHMAAM8++6zT3k3212pqauqoPagIIYQQv+CTIeSEEBJgHnnkEQaATfTP6s6dO1lwcDADwCIiIthzzz3HmpqahNtramrYY489JmwTHR3NiouLnR5r2bJlDABbtmzZhNby8ssvM47jGACWkpLCNm/ezGpra4XbjUYj27dvH7vrrruYWq1mYWFhw45RXFzMoqOjGQCmVqvZI488wqqrq4Xbm5ub2YsvvsiioqIYABYcHMx27tzpdD3r168f8/E8+OCDwvNvP1VVVbn82G+++WYGgHEcxzZu3MgqKiqE2wwGA/vuu+/Yvffey6KioiTPSVtbG0tKSmIA2Nq1ayXHbGlpYQkJCQwAW7duneQ2i8XCUlJSGAA2a9YsdvDgQeG2b7/9li1cuFB4jgAMe4527tw55u/d66+/zgCw1NTUEbex//46e45TU1MZABYWFsYiIyPZf/7zH2YymRhjjB0/fpytXLmSAWAymYwdOHBgxP1ff/31Ybc9+uijwvpvuOEGVlhYKNxmMpnYkSNH2KOPPspmzJjB9uzZM+L6nbG/Dh555BGX9hOz/+6N57kb6Xeuq6uLxcfHMwAsPz9f+BkPDAywP//5z0ypVDIA7Pbbbx91DSP9jCsrK5lGo2EA2NKlS1l5eTljjLHe3l726KOPCq/lp59+2un+9ufJ2WM0mUxs4cKFDACLjIxk//3vf5nZbGaMMVZSUsKWLVvGwsPDR/z9NJvN7Pzzz2cAmFKpZI8//jirr68Xbu/t7WVff/01u+OOO5z+HbErKioS7mPx4sUMALv44otH3J4xxvbt28dkMpnwmqyrq2OMMdbe3s5uv/124Xj//ve/Rz1OVVXVpP6mEEIIIe5AgRtCCHGDyQZuGGPswIEDLDs7WxJ8CA0NFT6UiT+4nDx5csTjTDZwwxhjH330kRBssJ9UKhWLiIgQPggCYHK5nG3cuNHpMU6ePCl8yLKfgoODmVarlVyXlZXl9AO/3XgCN93d3ZIAx0Q/ZA0MDLBbbrlFcpyQkBAWERHBeJ6XXG//IMgYY6tXr2YA2IwZM1hHR8ew4/7vf/8TnrdXX31Vctu2bduYXC6XPEf2AJ1Go2FffvmlXwRunnvuOZaTk8MAsKCgIBYWFibcN8dxwx7X0P2dBW6sVit76KGHJL9TarWaRUVFCR+67ae9e/eOuH5n/CVwwxhjBw8elPx+hoaGMoVCIVy+8MILmcFgGHUNo/2MP/30U+F3xh5kEz9/N998M7NarU73HS1wwxhjFRUVbMaMGcKxxD97pVLJPv744xF/PxmzvTYvu+wyyc9Sq9Wy8PDwYX9LRmMPINlP77zzzqjbM8bYa6+9JnltDb3P8fxuUOCGEEKIP6BSKUII8ROLFy9GcXEx3njjDaxduxapqanCVJuMjAz85Cc/wQcffID9+/cjMzPTo2u54oorUFlZiddeew1r165FWloaZDIZ9Ho9YmNjcd555+H3v/89Kisr8fzzzzs9RmZmJvbv34+PPvoI1113HTIzM8FxHIxGI1JSUnDllVfin//8J0pKSlxqSOyMVqvFAw88MKljAIBSqcRrr72Gb7/9FjfddBMyMzNhsVjQ29uL2NhYLF++HA8//DAKCgqEEcmbN2/G1q1bwfM83nrrLURERAw77vnnn497770XALBx40ah5wgAXHbZZdi9ezcuvfRShIeHw2w2Izo6GjfffDMOHTokaRrtSxEREdi/fz9++9vfIiUlBQMDA4iMjMTll1+Offv2Cb2GXMFxHB577DEUFBTgjjvuQF5eHmQyGbq7uxEREYGzzz4b9957L7799ttxT1zzR4sWLUJxcTHuvvtuZGVlwWQyQaPR4JxzzsFrr72Gzz77DEFBQRM+/iWXXIKCggLceuutSEtLg8FgQEREBC644AL897//xT/+8Q9wHDehY2dkZODo0aP41a9+hfT0dDDGoFKpcNVVV+Hbb7/F6tWrR91fq9Vi27Zt2L59O6655hrhd6evrw9JSUm48MIL8Yc//AFlZWWjHkfcz0ar1eKKK64Yc+233HILfvjhB/zkJz9BUlIS+vr6EBsbizVr1uCrr77Cpk2bxvUcEEIIIb7GMRZAs0UJIYQQ4lZpaWk4deoUXn/9ddx0002+Xs64LV++HN988w0eeeQR+oBOJqy6uhrp6ekAbD250tLSfLsgQggh0xJl3BBCCCGEEEIIIYT4KQrcEEIIISRgPfroo+A4DhzH4YUXXvD1csgU0NXVJfzO2LNtCCGEEF+S+3oBhBBCCCHuFhkZibi4OMl1Go3GR6shUwnP88N+dwBAJpP5YDWEEEIIBW4IIYQQEoA++OADXy+BTFFarRZNTU2+XgYhhBAioObEhBBCCCGEEEIIIX6KetwQQgghhBBCCCGE+CkK3BBCCCGEEEIIIYT4KQrcEEIIIYQQQgghhPgpCtwQQgghhBBCCCGE+CkK3BBCCCGEEEIIIYT4KQrcEEIIIYQQQgghhPgpua8XQBzi4+Oh1+uRkpLi66UQQgghhBBCyJRWU1MDjUaDpqYmXy/FbVavXo2KigpfL8OpzMxMbN261dfLCEgUuPEjer0eJpPJ18sgZFzM5nKv32eNIdyr92cZkE1q/22hWgRzHH6h74WOMYRxHFTgEMwBGo5DMMdBw3HQwHY+hOMQowrCfAaEAriT59DCce55MIQQQggh04zJZIJer/f1MtyqoqICJ08ex8w0ha+XInGymj7HetK0Cdy0t7cjLy8Pra2tyMzMxMmTJ10+RmdnJzZt2oSPPvoITU1NiI+Px5VXXolNmzYhPDx80mu0Z9oUFxdP+liEeFpTfaLX7/Pygpu8en+dRdGT2t/84fuI7OjAO6Hace/DgwMGYzXb//0e1HNmT2oNhBBCCCHT1axZs3y9BI+YmaZA4Tepvl6GxJxlp3y9hIA2bQI3v/71r9HW1jbh/dva2nDWWWfh5MmTyMjIwJo1a1BcXIwXX3wRn332Gb777jtERka6ccWEkKnOoLB9E9IcGoreoCAMyOToVyjQr1CgT6mU/NuvUKBPocDLP74GfHAwOIUCQdlZPn4EhBBCCCHE/zBYYfX1IoZgvl5AQJsWgZuvvvoK//znP/Gzn/0Mr7766oSOsXHjRpw8eRJr167Fv//9b8jltqfu//7v//CnP/0Jv/rVr7BlyxY3rpoQMtUZ5HJYeB4PXHwpWkNDx7VPyLnnenhVhBBCCCGEkKkk4KdK9ff347bbbkN+fj7uueeeCR2jsbER77zzDpRKJf785z8LQRsAeOaZZxATE4O33noLLS0t7lo2ISQAGBQKyKxWxAzWVsstFvBW66gnZj8x+taCEEIIIYQQMg0CN48++igqKyvxyiuvQKGYWAOnzz//HFarFUuXLkVcXJzktqCgIFx++eWwWCzYvn27O5ZMCAkQPUEqWDkO9tRRM8/DOsaJs5+oKTEhhBBCCHGCAbAwq1+d6CtHzwrowE1BQQGeffZZ3HzzzVi6dOmEj3Ps2DEAwMKFC53ebr++oKBgwvdBCAk82/Py8ceV56EuLByA0HPYOcZsGTeUaUMIIYQQQggRCdgeN1arFbfccgvCw8Pxxz/+cVLHqqmpAQAkJyc7vd1+/alT1EmbEOJQFRWFqqgo4TIbzKKRWa0IMpsht1jAATDKZOhXKmHlOMq0IYQQQgghhEgEbODmT3/6Ew4cOIDXX38dUaIPThPR29sLAAgODnZ6u0ajAQDodLpxHW+ksXQVFRXIzMycwAoDj757ALXHO5BzRnzAfpDt7e3FyZJT4HRazFkaB1gsYGazbaKQTOb19RiNRnR2diIqKkrSx2ksZiuPhp5oqOQmKHtD0VC2CPnLPhz3/hYrh57uMCiVRmg0fRNZ+pSgMpkQ26tDclcXUjs6kKjvhdpkhpVZYeF59MsV6Far0bt7NzRLl4LjODCrFRwfuImRFosFNTU1UKvViI+P9/VyAACMMTCjEay/H1xwMHil0tdLIiSgMcbATCawvj5wQUHg1WpfL4lMEmOMskcDHDMaYfXya5ajL7eGoeKk6SUgAzc1NTV48MEHsWzZMtx0002+Xg5xgdlowccvHEVTVTfAgNgULSITNb5ellv19/fjH397HQMnYqE0RoBDMwz3/wzanmoAQOaOL6BMSfHaehhjeP7559HT0wMAuOOOOxAbGzuuff+0bx3eO3oeYFHg58oOqFqTAACx6cWITikfc/89+5bgeGkurFYZTj9tPxbOPzrhx+HPEru7sLq4GBcfLwEgLZka+l9u/b2/QciSJYj62a1Q5eaCMRaQb1QOHDiAr7/+Gv39/Zg3bx6uvPJKXy8JAFB5+eUwnqwAAMx49a805YsQD6u7/Q707toFAIh78EFEXn+dbxdEJsRisaC9vR06nQ5Go9HXyyEeZKyuhnXwS215YiLkkZFeu2+ZTIbg4GBotVqEhoYG5PsjQkYSkIGbX/ziFzAajXjllVfccryQkBAAQF+f82wA/eDEmNBxjvstLi52ev1ImTjTiVwpg8VsFT7NVh5tQWRium8X5WYqlQoDJgM4xoMb/Ahfn3SuELhhZotX18NxnCTDprOzc9yBG43CAJPV1vTb1BcC1eD1Jd+sw7k3/GHM/RUKE6xWW3ZRR0eEawufIjLb2nDf118iTqdDQ1gYOkNCEKQJRp86GAaFHN+pQ2DlOSgtFkTq9djQ24Oezz6DVa9H/KZHoEhI8PVD8Ai1Wo3+/n4AQHl5OSwWC2Q+yDQbilcGCeet/QYfroSQ6YELEr/mAjfrMpDZsycNBvqbOR0oEhPBLLb3qtwEB79MlMVigU6ng06nQ3h4OOLi4sAHcGYyIWIBGbj55JNPEB4ejp///OeS6+3/odTX12P58uUAgHfffXfMFP2UweyHuro6p7fbr09NTZ3MssmgjPkxaK2xlZ1VHGnF4ksCK3DDcRzS09NR2twAZXc4AKA5egFmyv8DhbkfzGzy+poiIiLQ0dEBAMK/45EW2Wg7wwGHQvVYrg8DALRWz0LrqRzEpJaNun9kRKdwvrMz8AI3IQMGrCkqQJxOh6+zsvH+3LloDAvHNX06oTP8EZUGnaKAxcPXXIWON95E59tvo/uTTxB9662+WbyHzZw5EzzPw2q1or+/H7W1tUhLS/P1ssCpVMJ5Zuj34UoImR7EZRasn15zU1F7ezsMBgNkMhni4uKg0Wjow3QAM9bXw9LVBQCQx8RAMc4v+yaLMYaBgQHodDp0dHSgq6sLKpUKERGB9/5xPBgAK6y+XoYEwxiDOMikBGTgBgC6urrwzTffOL3NYDAIt43n24F58+YBAA4fPuz0dvv1c+fOnchSyRAZC2Lww9ZKAEBbbS962vqhjQ6smvf09HQcO1oAa48RPFPCKlOiKe4MzKjfBZjNXl+P+D+9zs7OUbaUSo1oEs4fHgjFuhllaK/NAQAc370WMWNk3URGOIJEXd3hsFo58Hzg1OtG6fuwpKoKh2bMwIvnLgMAcIyhE0C01fafbazFjO7BVF8rz0OZkoKI636Cns8/R98P+4EADdyoVCqkp6ejosJWllRaWuoXgRteFLihjBtCPI8X9Q+09lHgZiqy93iMi4tDWFiYj1dDPI3nZcKwBR7wapAuODgYwcHBkMvlaGlpQWdn57QN3JDpJyDD4famaENPVVVVAIDMzEzhuvF8ULjooovA8zz27NmDlpYWyW0DAwPYtm0bZDIZLrnkEk88nGknMkGDiHjHG7nKo60+XI1npKWlARyDIbhZuK4+8RwwQEg/9aZIUX2yK4GbGeEt4DlbAMLC5Iha+LVwmy3rJnfU/cPDu8DZ97fI0dOjdWXZfk9mtUJmtaI0Nk64zDgOLXIlGM+D8TxirBZYeR5Wngc/GMyRabWQR0TAouvx5fI9LjfX8ftRWlrqF80sOdG3/1bKuCHE4/hg0WuOMm6mHMaY0NPGPqyDBDbx0ARm9U3Gh1Zre784MDDgF+8dCPGGgAzcTNTLL7+M3Nxc3H///ZLrExIS8OMf/xhGoxF33HEHzKKMiN/85jdobW3F9ddfP+6+IGRsGfNjhPOBGLgJDw9HREQE+tWNwnV9mgR0h2WCmaZOxo1SZkZSmOPn0xbch+iU48Ll49+sHXV/udyC0FDHNLZAK5fqG5xIFDPYxM8y+GanlecBxgDGEGc2gbdYwDEG6+DtpoZGDFRVQZk8wzcL95KcnBzhfFdXF5qbm0fZ2jt4SanUgA9XQsj0IAmWUo+bKUf8oZnKo6YJ8c/ZR4EbcU+86Ru4YbAw/zoNH7lB3In+woq0tbWhrKwMjY2Nw2574YUXkJmZiffffx+5ubm49tprMWfOHLz00kvIysrCc88954MVB66MBY7ATWNFN/TdgfcBKj09HVa5AUalI1BSn7jUZz1u7Do7O2F14T/itAjH6+VUZwLyl30gXG49lY/W6rxR9xf3uekIsMBNj0qF0rg4rDh5AvPr66AZsP0et8jlAMcBHAf14IlxHLT9/ej++GM03P9bwGJBxI+v9fEj8CytVoukpCThcmlpqQ9XY8OpRI1SKeOGEI/j1eJSKQrcEOLvOD8I3BAyHVHgZpyio6Oxf/9+/PKXv4TRaMSHH36I7u5u/N///R/2798vKTUhkxeTEoqQyMEPUAyoOtbm2wV5gL1Mrz/YEfhoiZkPg963GTf2jv3jJe5zU90Zj5i044hJLRGuK/lmLUb7MkTc56ajM7BeR31KJf65+DQwjsOjn3+Gjbu/weXFRZhXU4PwhkYk19QivbIS1x47itu+3Yf7dn6FxocfgbGiEnH334/gxYt9/RA8bmi5lK/xKnGjVOpxQ4iniUulGPW4IcT/yXxfKkXIdBSwzYmdSUtLGzWdbtOmTdi0adOIt0dGRuKll17CSy+95IHVETGO45A5PxbHvq4FYCuXmn1u0hh7TS3p6bZpWcagdlj4AcisQWC8AifKjYha4d21BAUFQaPRCKPtOzs7x91gUJgsBVvGDQDkLfsArW/kAwDaavLQeioPsWnHne4fEeCTpUriE/DohauwYf8PmN3UiNNrTgEY3nWfATDLZAhZuQLh11wLzemneX2tvpCbm4uvvvoKANDU1ISuri6Eh4f7bD28WtScmEbbEuJxvJp63BAypYgzbiwUuPElK5UmTSvTKnBDppaMBTFC4Ka+tBMGvQkqjcLHq3Kf0NBQREdHo62tDQZ1EzR62zj58hNWnGFl4HjvDtSLiIiQBG7Gatyt4mz1xTmRjr4kpzrjEQQZZqSdQFxaCZqrbcGb0m+uwoy0J8E5eUjxkd3C+a7uMCiYHLIRJkuNdL2nMDf9CAoTE3H3miuxuKYGuS0tiOrTI8JkQhRjMCvk6FKpsSciEs2hofjgt7+BPCZm7IMGiOjoaERFRaG9vR0AUFZWhjPOOMNn6+HEGTcUuCHE4zgK3BAypUhLpbw/UIOQ6YpKpYjfis8MgzrUFqixWhlOFQZuuZQhuAn2eiJdL1BXNv4Gwe4iLpfq6OgYZUupNFGpVJ9JheZe23HmLPtIuL61JgfNVfnO7ze8W5gsZbXK0N0dWJOlBIzhYEoK3lq8GC+euwzPrliB/WeegcOLFqFyVj72Zs1EcULCtAraALbsOnGTYl+XS/GSHjcUuCHE0yQ9bqg5MSH+zw+mShEyHVHghvgtnueQLpouVXEk8KZL2culrLIBmBWOwFTxnnqvr2WiI8FDgwyI0XQJlys74gEAcalliEsrFq4v+GaN0143cpkV4VrH2Ov2ACyXAgAh3YgxcIxBBw7Cd8uMIdZsxqjNgAKYuM9NdXU1+nzYoFSccUPNiQnxPOpxQ6YLk8mEt99+G5dddhlSU1MRFBSE6OhonH/++XjzzTddGgzhS9Sc2D8wABYwvzq5613soUOH8NRTT2Ht2rVITk4Gx3HgnKXtizQ0NODOO+/EzJkzERQUhODgYMydOxePPPKIS707/RkFbohfyxQFbmpLOmAaCKyUTHE5kj7EUXJUdbTN65O0JjoSHADSRVk3VYN9bgBg7vIPhfOttTloGiHrJirScX9tHQEauLEbnCAFnkeLTC5cF2u1wmkt2TSQnJwMjUYDwDbW88SJEz5bi7jHDTUnJsTzqMcNmQ4KCgpw2mmn4frrr8fOnTuRkpKCtWvXYs6cOdi9ezduvPFGXHrppeifCq8B8ShuCtwQD3j88cdx//3348MPP0R9/dhfZp84cQLz58/H5s2bYbFYcNlll2HFihWora3FY489hjPPPBPd3d1jHsffUeCG+LWknAgo1bYPt2aTFTUl7T5ekXtpNBrExsYCAIxBHZCZbRFhq5Wh9LvhY+k9aVKBm0jxZKk44XxsygnEpxcJlwt2OZ8wFRXAI8FH0yp68xNjCaygpCt4nvebcikuiJoTE+JNfLB0HPhoQyQImYoOHjyIc889F8eOHcM999yD2tpa7NmzB++88w527tyJ4uJiZGVl4fPPP8fdd9/t6+WOTZxxwxgFb4jbnXXWWXjooYewdetWNDY2IigoaNTt77vvPrS2tuKOO+7AyZMn8f777+PTTz9FdXU1zjzzTJSUlOC5557z0uo9hwI3xK/J5DzS5kYJlysOB265FDgAXJVwfcneBjCr997AigM3fX19MLjwoTU9whFkquxIkNwm7nXTVpeFpspZw/aPiugSzrd3ho/7fqc6IeMGQJTVAtk0/sAiLpc6efIkTCaTT9YhybihwA0hHseJetzAagUzGn23GELcrKmpCRdffDG6u7vxyiuv4JlnnpGUpgNAVlYW3n33XQDA3/72N9TU1PhiqeMmKZUCqFzKh6xgfnVyl/vuuw+PPfYYLr/8csTHx4+5/e7duwEADz30EGSiL0XDwsLwm9/8BgBw4MABt63PVyhwQ/xehqhcqqa4HZYAGz0oBG4AdEV0ghv8w9fTZkDt8fE3CZ6s0NBQyOWOQIIrWTcZooybqg7pH9jYlBOIzxBl3Xxz5bCsG3HGTVd3GCyW6fGnqYPnYR48L4MteDNdpaenQ6GwNSM3mUyorKz0yTo4FWXcEOJN4h43gC3rhpBAceedd6KtrQ0/+clPcNttt4243cKFC7Fw4UJYLBZ8/vnnXlzhBAwJ3FDGDfG1sTJyACAqKmrMbfzd9Ph0RKa0GXmRkMltv6oDfWY0nujy7YLcLDU1VWhKawjmEB3meNNavKfBa+vgOG7C5VLiyVId/Vp0G4Ilt89d5uh101aXhcaK2ZLbw8N6wNsnSzEend1hLq19qmIcJymXip3G5VIKhQJZWVnC5bKyMp+sQ9xvg02FXgOETHHi1xxArzsSOAoLC/H+++9DpVKNq0wjP9/WB7CiosLTS5sUbrBPn4ACN8THLrzwQgC23jgW0Xvp7u5u/PGPfwQAbNiwwSdrcyf52JsQ4ltKlRzJeRE4VWjrb1NV0Ibk3Mgx9po61Go1os1mtA1mGwSFtgLdtkatVQVt0HcNQBM+diTZHSIiItDaaitHcyVwE6PpRoiyH71G2xvwyo4ELEh0vPGImXESCRmFaKycA8CWdZOQWST04pXJrIgI7xYmSrV3RCA60vsj0X2hhZchYfA/mekcuAFs5VIlJSUAbIEbq9UKfmhKtodxQTQOnBBv4uRycAoF2GB5JDUoDkzWgQGwAe8OXZgILigI/Di+vR+PV199FQDwox/9CHFxcWNsDSHrdCo0KOZ4Xsi0YdP8vYuvMAAWPyux99Vq/vCHP+DQoUP485//jO3bt2PRokUwGAzYt28fVCoV3nrrLaxYscJHq3MfCtyQKSF9brQjcHO0DedcnTXmWLipJMFiRZvt/2t0yloQEpmD3o4BMCtDyb4GnHZp+ugHcBNxxk1Hx/jLtDjO1uemsDkDgK1cShy4AWwTpuyBm/b6mag/MQ/J2ceE2yMjOh2Bm+nW58Zk6+kQYzH7JFjhL7KybK9rxhj0ej1qa2ttGWleJJlwQ4EbQryCCw4GG5z4YaWR4AGp/dXX0LZ5s6+XMaboX/wCMb+80y3H2rFjBwBg9erV49q+udk2XXRoDxy/RBk3ZAQVFRWYNWt4P0sAKC4u9sh9xsfHY9euXfjxj3+MHTt2oLq6Wrht7dq1WLRokUfu19um56cDMuWkzY22Ne8FoOswoK2217cLcrMEUcS802zCrHMShcvFu+u91tdH/GbBlcANAGREjdygGACikyuQOPOocPnYzqvAmCP4Fi0ZCT4F3rS4QGUyIUrfi+SuLoQP6d/QJpPB/tNVwtbIcLpSq9WSnk/27Btv4kU9bmAygZnNI29MCHEL6Uhw6nFDpr6BgQGUl5cDABYsWDCufQ4fPgwAmDNnjsfW5S4cBW6IHykoKMC8efNQVlaGjz/+GJ2dnairq8MLL7yAzz77DEuWLPFZCb47UeCGTAmasCDEpzv6nlQeDazpUiGi7CG9xYK8sxPAy2zX6buNqDra5pV1iBt3uRq4yYx0BG5Otic63WbeiveF813NKThVfIZwOTrScX+BFrj5xd69+Oc77+CV//4HF5VJR12bOQ7tvKPPTVVV1dDdpxV7jT9gC9xYvfyGUNycGACsBv9P7SdkqqPeUiTQtLS0COdjYmJG2dJm//79aGpqgkKhwLJlyzy5NPcQvW+h5sS+Y/WzEwBkZmaiuLjY6ckTTCYTrrrqKjQ0NOCDDz7A6tWrER4ejqSkJNx111144okn0NHRgYcfftgj9+9NVCpFpoyM+TFoqrSlUlcebcUZqzN8vCL3CZY5YqhmADIVMHNRLMr329JmC3fVYeaiWI+vQ5xx093dDZPJJNRcjyUz0tFIuaLDeeAmMqEGKfk/oKbEFrA5tnMtUvIOgJdZEB3lCNz06EIxYFQgSOmbkdDuZlA4/tSqnIy5bpLJEDM4Uaq6uhpLlizx2tr8TW5uLj799FMwxqDT6VBXV4eUlBSv3T8/JHDDBgxAiMZr90/IdCTNuKHATSCK+tmtiFx/o6+XMSbOTf1tlEqlcN7k5P/9of70pz8BANasWYPo6Gi3rMGTONH7VgTYtFcytXz//fc4ceIEMjMzsXDhwmG3X3311fj1r38tjAyfyijjhkwZGQsc/5F1NOjR1Rw46dTBMjk40TcWvb29mLM8WbjccKILbXWeLw8LCwuT9FdxpUFxpqhUqlUfjp4BtdPt5q14HxxnC1L0dsah4uhSAIA2pBdKhVHYrr0jwun+U1GfwvEGTu3kDVyzzBHYOXXqlKQj/nQTEhKCtLQ04bKnvqEZybCMm37qc0OIp3GikeDU4yYw8UFBkGm1fn9yV2PimJgYaLVaAGOX/e7btw//+te/IJfL8dhjj7nl/j1O9F6RWafvexbie3V1dQBsn2GcsV/vymcaf0WBGzJlhMUEIyo5RLgcSOVSvFwGlagRqk6nQ1y6FjEpocJ1hbvqPL4OmUw24QbFcSGdCFE63nBXjFAupY1qRsb8PcLlwt1rYDYpwHHScqnWACqXEmfcOAvctMpksL/tMRqN07rPDeDbcimO58GJvillBvoQSYin8epg4Tz1uCGBgOd5XHTRRQCA119/fcTt6urqcMMNN8BqteKxxx5Dbm6ut5Y4OdTjxucYAAuYX518MVUqPj4egG0aqU6nG3b7gQMHAEDypeBURYEbMqVkzHfUCQdS4AYyuSRw09vbC47jMHeFI+um/IcmGPSeLx0Sl0u1t7ePez+OAzIk5VLDGxTbzTn3Y/AyW3ZNvy4C5QfOBwBER4kaFLcHUOBG7ig3U5mGN7ulPjdSeXl5wtQ4e7mUN3GSyVLU44YQT6MeNyQQ/e53v4NSqcTrr7+OzZs3g4kGUTDG8Omnn+LMM89EVVUVfvrTn+K3v/2tD1frGmpOTPzFWWedhdjYWOj1etx5550YGHC8b2toaMDdd98NALjqqqt8tUS3ocANmVIyFzgCN81VPejtDIwPVZxMBrXozao9YjxzcSxUGtuHfrPJitLvGp3u706TmSwlLpcaKeMGADRhHche/LVwuXjfZTANqAK2QXG/qE+Qs4wbAGiWOQI34jGG09HQcilvT5cSp8pTxg0hnifpcUOlUiRAzJs3D//85z+hVCpx5513Ijs7G9dccw0uu+wyZGRk4LLLLkNrayueeuopvPbaa8IXFlOCpFSKAjfEvexBTfvJaLR92Su+7tNPPwUAqFQq/PWvf4VcLscbb7yBzMxMrFmzBqtWrUJubi4KCwuxcOHCKRUYHQkFbsiUEpmogTbG8Qav6lhgZN1wQ0qlentt/WzkChnyRaPBC3fVwWr1bCKieLKUKxk3wJAGxaMEbgBg1jmfQD5YWmXsD8Hx7y4eEriJAPNFzqUHSAI3ZueBmyZRn5uamppp3ecG8HG5lNrR54YybgjxPEmPG8q4IQHk2muvxbFjx3DbbbeBMYatW7fi008/RXV1NRYuXIjy8nLcd999UytoA4ATZQlTxo3vWJh/ndyltbUVP/zwg3CyZ6uJr2ttdXwGXLNmDfbv34+f/OQn4DgO27dvx759+5CZmYknn3wSe/fuRUhIyEh3N2VQ4IZMKRzHIVNULlVxJDACN5DJoeofHrgBgNnLkmD//7ynzYCaYteCKa5yW8bNKKVSAKDS6JB35hfC5ePfr0KoyhHUMJmU6NGFOtt1yhEHbpxNlQKG97lpbPR8dpU/E5dL9fT0oL6+3mv3zatEZRuUcUOIx1GPGxLIcnJy8Morr+DkyZPo7+/H8ePHoVarUVRU5PL7LL8ho4wb4jk33XQTGGOjnm666SbJPgsWLMDbb7+N2tpaGI1G9Pb24siRI7j//vuhVjsfmDLVUOCGTDkZonKphhNdMPRO/ZHRnEwGtWF4qRQAhEaqkD7P8Zg93aRYnHHT09Mz4hjLIE4+7JQf1SLc3t4Xhj5DmNPt7Kd5Z/8PQWrbYzUb1aj44RKEax2PvasjWrK9jLd69QQebjkZlKJx4GaT020sMg5tMupzYxcSEoLU1FThsjenS3EqR6kUTZUixPOoxw2ZTnJzc/HMM8/AaDTiJz/5Cfqn4u+8uMfNNM8QJsRbKHBDppy4NC2Cw2xTX5iVoaqgzccrmjxOMXLGDQDMETUprinu8OgodK1WKxkJ7sq3QTGaboQF6YXLJzviR91eGWTA3HO2C5ePH1yBKI2jNKU1QEaC94vHgRtHDjRSnxupWbNmCee9WS4lybgZoMANIZ7G0zhwMs384he/wHPPPYdrrrkGRUVFvl6Oy6g5sX+w+tmJeBYFbsiUw/EcMuYF2HQpmdxpc2K7pOxwRCRohMuF33gu62YyI8E5DpgpKpc60TZ6nxsAyDttJ4JDbfdhtSiA1hzhtpb2QAnciMaBm4dPlbJrklOfGzFflUtRxg0h3iWZ5DYVsw8ImYC7774bmzZtwmmnnebrpbiOmhMT4nUUuCFTkrhcqrakA0bDyB+GpwJOJm1ObDAYJCVKHMdh7vIk4XLpt40efczicilX669nRjYJ50+O0ecGAOQKE+Yv2yZc7qnPg8xsexMfKBk3BlGPG6XFAtkIb3LaZDLIBrNuTCYTGhoanG43XQwtl/LWdClxxo2VetwQ4nHSHjf0miPE31FzYkK8jwI3ZEpKzA5HULAtO8FitqKmeIo2dxs0dKoUMLxcKvuMeChVtv8ojQYLyvc3e2w94gbFrk6WEmfcnGwfO3ADANnz90EbOfh4GI/gXtuH9c5uLYwm+Sh7Tg3i5sTAyA2KLRyH5GRHWdx073MDDJ8uxbwwaoxXOaZKMZoqRYjHScaBU3NiQvwfNSf2OQbAAs6vTgEyDNZvUeCGTEkyGY+0udHC5SlfLiWTQ2a1Qjng+JA4NHCjVMmRe7YjEFK4q85jH2InM1lKErgZo8eNHS+zYMHyj4TLKkMs5KYQABzaOsJdun9/ZBgSuFGPELgBgLS0NOE89bmxlUvZdXd3e6VcilOJx4HTt/+EeJq4xw2jHjeE+D9xjxvGKHhDiBdQ4IZMWRmiseDVhW2wmKbufxqc3JZJI+5zMzRwAwBzljmyMToa9Kgv7/LIesSlUq5m3GRFOcp7OvtD0d4XMq79MmYfQGRcjXBZo0sDALQEQLmUhedhFDUeHinjBgDS09OF87W1tTCP0hNnOggNDfV6uRRl3BDiXZKMGwP1lSLE30maEwNULkWIF1DghkxZM/IjIVfafoVNBgvqyjp9vKJJGPxQLy6XGtqgGADC44KRMsuRDeOp0eDijBudTgej0TjufaOCexGhdqz9RPvYDYoBgOMYFq38ULisNEZCYQxDa6A0KBY1HlabRg7GJCUlQT64LfW5sRGXS5WXl3v8/jg1ZdwQ4k0c9bghZGoZErihjBsfYIDVz05UK+VZFLghU5ZCKUPKLEdmSOWRFh+uZnI4me2D+mgjwe3mLBf1QDnaCl2H+7+dDAsLE5rkAkBnp2tBMUmD4nH2uQGA5KwCxM44IVzW6NICZrKUuFxKZR4540ahUFCfmyGys7OF821tbS5ngblKknFDU6UI8ThpqRT1uCHE33EcJw3eUOCGEI+jwA2Z0sTlUpXH2mC1TM3/OIRSKcPII8HtUmZFQRtt+2DJmGeybniel4wEn0yD4hMuBG44Dlh83gfCZYUpDJ11OfBCP1qPEzcoVhtHDtwA0nIp6nMDREREIDY2Vrjs6awbaY8bCtwQ4mniUilmMoGNUk5KCPEP4nIpNkXffxMylVDghkxpaXOjwcs5AICh14T6si7fLmiiZMN73IwUuOF5TpJ1U7y7HsZ+9/dBmUyfm2xRnxtXAjcAEJ9ajoSMIuGysjMbnV1hLh3DH4kzbtSjZNwA0gbFNTU1LpWqBSpx1k1ZWZlH70va44YCN4R4mjhwA1DAlJApgTJufIqmSk0/FLghU1qQWo5UUbnUiYOeG5HtSfZSKXXf2IEbAMg/JxFKtW0fo8GC4r3u74MiDty0tbW5tG9OtGPyT3l7IqyMc2n/M1f9Gwy2NwFyixpH961yaX9/JM64Ga05MQAkJydDqVQCACwWC2pqakbdfjrIyckRzp86dQp9HiynkGTcDFBzYkI8jQsOlly20mQpQvyepEGx1eK7hRAyTVDghkx5WYvjhPOVR1un5HQpZ1OlRgvcKFVyzD7X0fS34OtaWNycphod7Ri37vpkKUeplN6oRkNP5ChbDxcR2wBVnKMcpubYchjGOZ3KXxkU4ubEowduZDKZpFyqoqLCY+uaKpKSkhASYvsdYIzhxIkTY+wxcdIeN/QBkhBP4xQKybf3rJ/63BDi98SvWcq4IcTjKHBDpry0udHCdKmBPjNqjnf4eEWu44JsHxTFPW76+vpGHQU9d8UM8DJbJktv5wBOHnRvc2Zx4KatrQ3MhUYzIUEGJGkdWTplbeObLCWWMm8XrJzt8VvNQTi88wqXj+FP+uXijJuxS9syMjKE8xS4sfVdEpdLlZaWeuy+KOOGEO/iOE46EpwCpoT4PyqV8jlfl0YNPRHPosANmfIUQTKkzXUEGU4cmHrlUrLBRsCqIRNsRposBQCa8CBkn+7INjqyo8al4MpYxKVSBoMBer3epf1zoh3lW2VtSS7ff2JSA/pCTjmOcWgZtD0al4/jLyQ9bsbReDMzM1M439LSMmoG1nSRm5srnD958iRMHmpgShk3hHgfFywO3FCPG0L8HSeaPkoZN4R4HgVuSEAQl0tVFbTBZJxatbbySFvgRma1IkjUlHGsD+vzL0gRzrfX96LWjdlGGo0GatE3oC43KBb3uZlAxk1cdDv6gxtgltk+ODMmw8KCnDH28l/9LgZuoqKiEBbmaMpcWVnpkXVNJenp6VAMPo8mk8ljo9J5yrghxOt4taPPjZVKpUgA2bhxIziOk5wUCgXS09OxceNGdHd3+3qJEtnZ2ZIhCYDzx6DJyEDeRRfh3qefRndXl0/WSsh0QoEbEhBSZkVCqbJF/s0DFpwqdC3I4Gsy0ehtcdbNWIGbqMQQpM52ZMYc2eHeJraTa1A8uYybkGADQjR66EMdAYvE5hgkNEWPspf/cqU5MWArHaByKSmFQoGZM2cKlz01XYqjjBtCvI4y3UigOnbsGADg4osvxvr167F+/XpccMEFaGxsxIsvvoiVK1eOWhrvTaWlpThx4gQuv/xyyfXOHsP5556LptZWbH7rLVy4bp3fPIbpggGwMs6vTjRVyrMocEMCglwhQ/r8GOHyVJsuxavV4AazW8QNint6esbcd4Eo66autBOtNe4rqRna58YV4slSNd0x6DcpRtnaudjoDhiD2mFUdgnXLSzIAWedenW0kubEY4wDtxOXS1VWVrq1FG6qEk+XKisrg9UD6dmUcUOI91GPGxKo7EGPV199FVu2bMGWLVuwfft2fPfdd1AoFDh8+DA++eQTH6/SZuvWrQAwYuBG/Bi2/utf2PnWW1DI5ThSWOg3j4GQQEWBGxIwxOVSpwrbYeyfWpF/+WDWjbhB8Xj6miRmhyM2NVS4fOR/7su6mcxkqZSwVgTJjAAAK+NR0ZHg8v3HRbcDHNAbWgEMxvHDdCGYWZXs8rF8TZpxM77fTXHGTW9vL1pa3NuAeirKzs4Gxw025e7tRUNDwxh7uE6ccQOLBcxDvXQIIQ6SHjc0DpwEiJqaGnR2diI8PBzJydL3LgsWLMCKFSsAAEeOHPHF8obZtm0bQkNDsXz5cuG6ER8Dz2N+Xh6WnX46AP95DIQEKgrckICRnBeBII0tq8FitqLqWKuPV+QaWaRtZLa6z7XADcdxkl43Jw+1oKfdPW96RyuVCuIUo56CZXJkRzcJ21e0zxhzn6Gn5Ghb3bdFoYdVWycca27JTKjMPGS81aMnxsFtp6GlUiNtJxYcHIyEBEfAi8qlbM9JSorj990T06XEGTcAYDVQo1RCPI163JBAdPToUQDA7Nmznd6u0fjP0IW2tjZ89913WLVqFZRKpXD9SI+BG5wqFSzKliPe5espUjRVyrsocEMChkzGI3NhrHD5hJvHY3uabLBBsbhUaryThDIXxCA0yvZhk1kZCr6qG2OP8RFn3HR2drpcv5wr6nNT2up6g+KE6E7hfEdQHUxy2/0HGZWYVTJzpN38kmSq1DhLpYDh5VJEOl3KE31uuCFvQhkFbgjxOHGpFL3mSKCwlxiNFLgpLy8HYGu+72vbt2+HxWLB6tWrJdeP+BgGAzcnT9kmgPrDYyAkkFHghgQUcblUbUkHDPqpU+IgjxjMuJlA4IaX8Zh//gzhcvG+Brc89oiICKEshTGGzs7OMfaQyolqFM6XTWCyVFioHqogW48RJjOhKs0RuMg6mYoQXfBIu/odyVQp48QCN9XV1R4bgT2ViPvctLa2ulzGNxZOqQQ4xzdH1G+DEM/j1KLeUlQqRQKEPVtlzpw5w27bsWMHiouLoVKpcNFFF3l5ZcNt3boVMpkMl1xyieT6kR4DJ5Phy2+/RcnJk1AFBfnFYyAkkFHghgSUxKxwBGtt6Z1WK0PlkalTLiWUSk0gcAMAeWcnCqVi5gELivfUj7HH2ORyOSJEE69cbVCcGyPKuGlLgKu9dTkOiBdl3bRH1UIfbEuh5xmP+QW5I+3qdySlUi5k3MyYMUMYgW02m1FbW+v2tU01kZGRiI11ZNe5O+uG4zjwweKyDfoQSYinSUul6DUXaAwmC7r7TX5/Mpgsbn3cQ7NVGGOoqanBX//6V1xzzTUAgAcffBDx8fEAAJPJhKeeegr5+fkICgpCREQEFi9ejJdfflly3P7+fjz++OOYNWsW1Go1YmJicMMNN6CubnjG9Y033oi5c+eOuk6j0YgdO3bg7LPPlpTJj/YYXt2yBTfecw8A4Le33y48hrHub8OGDcjPz3d6W1RUFB544IFR10psGDhYwPvViVG5lEfJx96EkKmD5znMXBSLgp22/7hOHGxG/jmuZ3r4grNSqYGBAQwMDCAoKGjM/RVBMsxZloyD26sBAAVf12H+eSmQKSYXn42KikJHRwcA1xsUizNuOg0haO3TIlYz9qQssfjoTlTX294MhPRzODa3DGd/vwAAkNQQh9iWSLTEdrh0TF+QTJUaZ3NiwBY8S01NxcmTJwHYyqXETYunq5ycHKFZc2lpKc4++2y3Hp8LVgN6PQDAqqd+G4R4mnSqFL3mAs1fdlXgxa9O+HoZY7rrvCzcfUG2W46l0+mEEudly5YNu12tVuPJJ5/E/fffD8AWEFm9ejUOHz6M++67D/PmzUNbWxt27Nghafzb3NyMlStXQqfT4Ve/+hXmzJmD6upqbNq0CWeffTaOHDkiCb4UFRWNWKplt3PnTuh0umHTpMZ8DCoVHr3rLvzmttvGfX+FhYVOb29oaEBHR8eYayVkuqLADQk4WafFCYGb+rJO6LsHoAkbO/Dha/LBjJuggQFwjIENlmrodLpxBW4AYM7yZBzZUQOL2Yq+HiPK9jchf8nkAlfR0dE4ccL2ZsvVjJuoYD1iNd1o0YcBAEpbE1wO3CREO4IyIb08SrKb0BrVgZh22/O14Ggedlywb1hjX38jzrhRWiyQWaywyMYXVMvMzBQCNxUVFTj//PM9ssapJDc3F3v27AEA1NbWQq/Xu7XJIx8cDPv3rtY++hBJiKfxoqlSjEqlSAAoKCgAYwzR0dG49NJLAQAymQzh4eGYO3cuLrvsMkmA5YMPPsDnn3+OH374AacPTmoCgGuuuQZsMGXZbDbjsssuAwAcOnQIMTExwnZLly5Ffn4+nnnmGTz11FMAAKvViuPHj+Oqq64ada3btm0DgGH9bUZ7DLPz8nBBbi6iwsPBLNZx3R9jDCUlJcMCRIAt4AOM3A+IkOmOAjck4MSlaxEaqYKuwwDGgIrDrZi7wv/HR8sGe9zwjEFlMqF/sKO/TqeTNAkeTbBWiZyz4lGyx1aidPR/Ncg7KwEcP/GoxmRGggO2BsVC4KYtEeemuVbWIi6V0vRx4K3A0fmluOArW4ZFeLcW6VXJqMxwT0NmTxE3JwZs5VJ62fgCcuIMm8bGRrcHKaaihIQEhIaGQqfTgTGG8vJyLFiwwG3H54Mdz6+1T++24xJCnJNm3FDghkx99t4wK1euxJYtW8bcfvfu3VCr1ZKgjZ293+DmzZtx+PBhHDhwQBK0AYDs7GwsWbIEO3bsEAI3J0+ehMFgGDMYsm3bNmRlZUl6yI31GKxGIwYGmyuDWcEYG/P+Kisr0dfX5/T24uJiKBQKyQACMjqrv39rSdyKAjck4HAch5mLY3FkRw0A4OTB5ikRuJFHOnrJqPv7JYEbV8w/bwZK9jYADOhs6sOponakzR1f4MeZ0UaCj0dudCN2n8oDYAvcuHz/YToo5GaYzHJw4BCi59ER2Y3q1HqknUoCAMwpykbNjCaYFa5NvfKmfvmQwI3JBP04M6liY2MREhKC3t5eAEBVVdW0/0aK53nk5OTg4MGDAGx9btwbuBH126CMG0I8jlOJAjcGCtwEmtuXZ2LDOf4/dShI7r72n/beMPPnzx/X9iEhIejv78cDDzyAX/7yl0LPGLEXX3wRK1euxMKFC50eY8aMGfj666+Fy+PJYjl27Bhqamrw61//2qXHYB8HLrBax7y/wsJCYZ1dXV2S244ePYrs7Gyhrx8hRIqaE5OAJJ4u1VjRDV2H/48WtTcnBgC1rlc472rgJiJeg3RRoObI/2omtS5xxk1/fz/0eteyDyQjwdsSXL5/nmeIi3Jk3YT22v5sFcwuh1lmK2ZRDQQhr9S/+75YZDyMMplw2ZU+NxzHSaZLVVRUuHVtU5X4m8GKigq3TtySBG5c/J0nhLiOSqUCm0ohQ5ha4fcnlUI29oMZJ3u2yni/VLjtttuQnZ2NJ598EomJiTjjjDPwyiuvwGKxvdcpLi5GVVUVfvzjH494jNbWVoSGhgqXi4qKEBwcPOqo7q1btwKA0/KlUR/DkMANGwzcjHZ/9sDO6aefjoiICMnpjTfemPZfShEyGgrckIAUPSMEYbGON4EnDjT7cDXjIxNNb1KJ0sR7elzrCQMACy5IEc43nOhCY0X3hNel0WigUjnGtLqadZMjCtxUdMTBaHH9TZG4XCpUb/uz1R9sQGmOYzx4Tnm6348H75c0KHYtyCAul6qoqBDq3aez9PR0KAcz00wmk1sDWpRxQ4h3UakUCSQWi0UIUow34yYlJQVFRUX4+OOPcdNNN6GiogK33347rr/+egC2wA2AUUuJysrKMGvWLOFyUVER8vPzhVIrZ7Zt24bIyEicc845Lj0Gjudt4z/tBgM3o92f/fadO3dKTl999RXkcrnTsenEOQbAAs6vTvTO1LMocEMCEsdxyD7NkXVT+n2T33/Q5UNCgMH00GDRRA1XM24AIGFmOBIyw4TLB7dXTXhdHMdJsm5cDdxkRrZAwduyS0xWOSo64sbYY7iEGEeD4lCd489WaU4V+tS2N/gyK4+FR/Lhz/9rGETlUq4GbsQZNz09PWhu9v9gpKfJ5XJkZWUJl+1vat1BHLhh9CGSEI/jKHBDAkh5eTn6+/sRFxfntORpJAqFAqtXr8Y//vEP1NbWYtmyZXj33XfR29srlEtHijK0xb777jucOnVKaF4MjD3hqbGxEQcPHsTFF18MmUz6xdp4HoOkXMpiHddEqdNOOw3Lly+XnFJSUmA2mynjhpBRUOCGBKycMx1lOZ2NerSccj0A4k0cx0E+mHWj7ptcxg0ALL4kTThfU9yB5uqJHQeApAFea2urS/sqZRbMjHQEGUpak1y+/8QYR1NkjZ4HPzjuxyK34Mj8UuG2hOYYJNW7HhjyFvFkqSCza4GbkJAQJCY6egTZJ31Nd+JvFsvKytxWLiX59p/GgRPicZLXHPW4IVOcq/1tnFGr1UIWzMDAABISbO9r6+qcD2N49tlnER8fL5RSGY1GnDhxYtRgyCeffCKMIZ/QYxAFbgYMhlHvz2Qy4cSJE06zamiiFCFjo8ANCVhhMWokzHRknZR91+jD1YyPvVxKnHEz0cDNjPxIxKY66pwPbq+e8LomE7gBgPyYeuH8RAI3MRE9UMhtWTv8YINiu7qkJjTFObKAFhzNg8zsvhp1dxJPlnKlx41ddna2cJ4CNzYzZ84UGhkajUa3lUvxGiqVIsSbxIEb6nFDprprr70WjDF8/vnn49q+paVl2HVmsxk7duzAnDlzEBUVhSVLliAkJARvvvnmsG3/8pe/4IMPPsCf//xnqAdfS6WlpWNmsWzduhUKhQIXXXTRxB6DKHBTWnp81PsrLS2FyWRyenthYSE0Go2kLJyMzcJ4vzoRz6KpUiSg5Z6VgMaTtv4u5QebseSqLMgU/vuHRRY5PONGp9PBarWCH9q9fwwcx+G0S9Px6Z8LAADVBW1ordEhJiV0jD2Hm2zgJi+mHjhuO3+81fXJUjzPEB/dgdqmWACAVsejR2u13cgBhxeUYNUX50DGeGj61cg/nonCOeUu34+nGUQ9blQTyAzJysrCrl27AAC1tbXo6+tDcLB/9/XxNKVSiezsbKFMqqSkxC2jRKnHDSHexYl6qVkNBjDGRu3LQUggWbduHaKionD11VdjxowZqK+vx1/+8hcUFRXhf//7HwBAq9XiiSeewMaNG6FQKLBu3ToMDAzgvffew3vvvYfnn38eV155pXBMexZLVVUVPvroI8n9nXvuuYiMjMTSpUtx2WWXQavVTmjdHM8LFepFg/8Pj3R/9olSI2XcjNWLh5DpjgI3JKDNXBiLPe+Ww2yyYkBvRnVRGzIXxPp6WSMSSqVE9f2MMfT29k7oP9XUOVGInhGCtlpbXfTBz6px8W2uN34TB256enpgMBigdGF/ccbN8dZEMCbtZzceibHiwI0MgCNjRReqR1lOJfJLZwIAcsrSUZ1aD53Wv6YBTabHDQAkJCRAo9FAr9eDMYaKigpq5AcgPz9fCNzYy6UmO06UAjeEeJf4NQeLBcxkAqd05X8aQqaum266Cf/+979x7733oq2tDREREVixYgUOHjyI/Px8Ybu77roLUVFRePbZZ/HWW28hJCQES5Yswe7du3H22WdLjmkP3Nx+++3D7u/UqVOIjIzEb37zm8ktXPSlYnFJyaj3V1RUhMjISEnZt11hYSHOPPPMya1l2uFg9bviGQq8eZK//bQJcSulWo70+Y6gQ+l3TT5czdhkEbaGcwqzWRIYmWi5FMdxOO0Sx0jGyiOtaK/vHWUP57RareSDsKsNivNiHJOlugc0aNCFu7yGJFGfG/tIcLGSvErogwcbFTP/bFQsniqlcrHHDQDwPC9pxkvlUjZZWVnC7+fAwIBbyqU4ceCGGqUS4nHiUimAmoKT6eWnP/0pduzYgYaGBhiNRjQ3N+Pdd9+VBG3srr/+ehw5cgQGgwFtbW34+OOPhwVtAODJJ58EY8zpKSUlZdj2E8HxjtL0Jx54YNT7e/LJJ9He3u70OCUlJfjHP/7hljUREqgocEMCXu5Zjk74NUXt6NcZfbia0YlHgmusVuH8RAM3AJA+LxqRiRrh8sHPql0+Bs/zkyqXClP1IynUMRnq+EQaFMeKGhT385APaRFja1R8XLgc3xKN5LrxT3Lwhsn2uAEwLHBjFf2eTFf2cim7ksFv/SaDMm4I8S5eVCoFUMCUkClBlHHD6P0IIR5FgRsS8JJzI6EJDwIAWK0M5fv9d4yyLCJcOB9sdASYJjIS3I7jOcmEqZOHWtDZ5HoJka8bFEdoe2GSO1JoxGPB7eoTm9EY71jbgmN5kJv8p1GxeKrURHrcALax4PZ+R/39/aivrx9jj+lB/K1kWVkZzOaJBcbseLU4cONfJXeEBCJOqQTkjqxEKzUoJsT/yUTvxShw41UMgAWcX538LNE94FDghgQ8nueQc4ZjRHTp9/47XUoeGSmcD+6b/GQpu8yFsYiIH/wgyiaWdeOWBsWDJhK44ThAF+J4U6DtdRKQGWxUbOFt2wX3q5B/fKbL9+Upk+1xAwAqlUqS4kzlUjbuLpeijBtCvE8yWYpGghPi9zjKuCHEayhwQ6aFnDMThPNttb0T6vPiDeJSKZUoy2aygRue57Do4jTh8on9zehqce3D6NDADR9f7tJpVvYDwv7HO89weX8+vhy6UItwDK2OBw827NQXokdZjuNDe055GsJ6NE63HesEDm499SvFPW7MzrcbB3G5VHm5/03P8gWlUil5XuzNiidKPA6c6SlwQ4g3iMulqFSKkCmAp4wbQryFAjdkWohM0CA21TEGu/Q7/8y6sTcnBgBVR6dwfrKBGwDIWhyLsFjbt5mMAYc+P+XS/uLATVdXF4xG13oF5cY7nv/ajn7oB1wvZdGFOAI3zhoU25XmVkAfbPuwzTMeCw/P8otGxdIeNxPLuAGkgZumpia3/H4EglmzZgnnJ1suxVNzYkK8jgt2ZNxY+w0+XAkhZDw4Ctz4lIXxfnUinkXPMJk2cs9yZN2U7W+G1eJ//8GIe9you7uF8+74YM7LeCy6KE24XP59E3raxv+BNDw8HHJR/wFXJ0vNiAiGSuH4k3OyxfWsp55Qx89MNcBDaXSeomKRW3FkgaNBbWxrFFJqho+f9DZ39LgBbEG08PBw4fLJkycns6yA4c5yKXHghhmNYJP4eRFCxodXiQM3lOlGiN+jUilCvIYCN2TayFocB15m+6Df32NETUnHGHt4n1xUKqUWfcvf09MDxiafMpJ9Rhy00bZUdKuV4dAX48+64Xke0dHRwmVXAzc8z2FmbIhwubzZ9YbLxiCGAaXjjYGzBsV2jYktaEhwNKKedywPCqN8xO29wSAaBz6ZjBuO46hcygl3lkuJAzcAZd0Q4g3SHjeUcUOI3xNn3FgsI29HCJk0CtyQaUMVokDaXEfgoez7Jh+uxjlOoQAfaispEjcntlgs6HNDg1SZjMfCVanC5dJvG6HrGP+b48k2KM6OdZRLnZhAxg0gbVAcqht9YtSRBSUwy2xvJFQDQZhTmDuh+3SXfrk442ZyU4/EAYrKyspJT1EKFO4qlxJ/gASoQTEh3sCLS6VoqhQhfo9KpXyHAbCC86uTH3QlCGgUuCHTSu6Z8cL5qmNtMOj9r/xBFmnLulGYTFDIHIEJd/UxyT0rASERg+PRLQxHXMi6mXTgRtTnZiIZNwAkDYpH63MDAH2afpTkO6YuZVamILI9fEL36w7u6nEDAOnp6ULpmtFoRE1NzaSOFyiysrKE52Uy5VKcUgmIfl70IZIQz+NUNFWKkCmFSqUI8RoK3JBpJWV2FNShtg9jFrMVJw+1+HhFw8nDbYEbDkCIqKeMuwI3Mrk066ZkXyP0XQPj2nfSgZs4R6nUieaJZdyI+9xodbIxmw6XZ1ehW+sIEi06NBucdZzjm9zMXT1uAEChUCA9PV24TOVSNkqlEtnZ2cLlkpKSUbYeHY0EJ8S7xJluVJ5IiP+jjBtCvIcCN2Rakcl4ZJ0WJ1wu+97/pkvJIh2TpTScI8DgzslBeUsSoAlTArAFsA7vGF/WjThw09HR4XIZSpaoVKq+qx+9k5wspTBzUA2MHoRhPMOhRUXC5fBuLbJOpLl8v+4g6XFjNoObZN8icbnUiRMnRtlyesnPzxfOl5aWTrxcShK40U96XYSQ0VGpFCFTDGXc+BAHC3i/Otm+diaeQoEbMu3knumYLtVU2YOuZv/6Jl0malCsETV6c2fgRq6QYYEo66Z4TwP03WNn3URERIAf/E+aMYb29naX7jcpXI1gpaP868QEyqXMCqBfNf4+NwDQHt2JynRHKdGs4iwE61Uu3/dkiTNuACBokn1pxIGb9vZ2dHT4X8NtX8jOznZLuRRl3BDiXeJSKSuVShHi/8QZN4xR8IYQD6LADZl2omeEICpJI1w+/m2DD1cznHgkeLDRKJx3Z+AGAGadk4hg7WDWjcmKw+PodSOTySSTpVpaXCs143kOWbGTL5cSZ91oR5ksJVYwtwyGIFtwSm6RY+Hh2WOWWbmbYUjgZrJ9biIiIiRZUFQuZTO0XKqoqGiUrUcmGQlOgRtCPE4yVYpKpQjxe5JSKYDKpQjxIArckGmH4zjknZ0oXD7+bSMsZv/5j0YuKpUK1js+LHZ3d7v3fpQySa+bot316O0ce8KUOFDgauAGALLjHOVSpU0Ta1Dcox3S52YcTEoTjs07LlxOaIpF6qmkCd3/RBllMoh/04ImOVkKGD5ditjMnj1bOF9aWoqBgfH1cRKjfhuEeBevdmRCWvtpHDghfm9I4IZNsgScjB8DYGG8X53op+9ZFLgh01LOmfGQyW2//v06E6qOtfl4RQ6ycEeplFqUZePujBsAmHVuIjThgxOmzAwHPxs76yYuztEjaCKBmxzRZKmy5ok9ph7xZCkdD26ccbealAY0xjvWPP9oHoIMygmtYUI4zq2TpQAgIyNDOH/q1ClYROV101lWVhaCgmy/2yaTCWVlZS4fQ1IqpaeMG0I8jaNgKQlAGzduBMdxkpN9wMDGjRvd/sWcN3E8D4j6MVLGDSGeQ4EbMi2pNApkLnJkjhTvqffhaqTEpVKqTkfPku7ubrd/kyFXyLD4YkfWzfF9DehpG/3NcmxsrHC+ubnZ5fvMjdcK58smmHGjC7HCytmeC55xCBljLLiAAw4tKoJJbst0UZqUWHBk1oTWMFHunCwFACkpKULfoYGBATQ0+Ffpn68oFArMmuX42RYUFLh8DOpxQ4h38SoqlSKB59ixYwCAiy++GOvXr8f69etxwQUXoLGxES+++CJWrlw54Sb6/kBSLmWhwA0hnkKBGzJtzVrqKJOpK+1EV4t/fDATZ9yoWhwjty0WC/R690+2yVuSiNBIW3q61cJwYHv1qNuLM266urpcLkERZ9y09RrR1ut6CQvjbcEbu7BxlksBQH+wAQVzS4XLM+oSkFQXN8oe7iWdLDX5wI1SqcSMGTOEy1VVVZM+ZqCYO3eucL6iogK9va71VOKC6dt/QryJp9ccCUD2wM2rr76KLVu2YMuWLdi+fTu+++47KBQKHD58GJ988omPVzkJNFnKZ6zg/epEPIueYTJtJWSGISLB0aS4ZI9/ZCqIM25kbW1CuQfg/j43ACCT81h8aZpwuez7plEnbYWFhUGpdJQXuVouFRMahCiNY/+JZt30aEUNintc+1NWmVGD1mjHRKyFh2dDYVSMsof7SDNu3PMNW3p6unCe+tw4pKSkQKu1ZXgxxlxuUkwZN4R4F6cS9bgxUI8bMvXV1NSgs7MT4eHhSE5Olty2YMECrFixAgBw5MgRXyzPLSQZN1Yq1ybEUyhwQ6YtjuMwa6moSfF3jbCYfP9NgVw0DhwWC7QhIeA4DlqtFiY3lNY4k3tmPMJibN90MivDgU9HztrgeX7SDYrtWTdqhWxCGTeAtM/NeBsUCzjg4OJCWHjbMVQDQZh3LG9C63CVQe7IuHFHqRQg7XNTW1vrsd+TqYbneUnWjavlUtLAjfuz3QghUjRVigSao0ePApA2zBfTaDROr59SKOOGEK+Qj70JIYEr54x4fPdhBSwmKwy9JlQebUXWad4rm3GG12pt/wkO/ud33YUXInTmTMhkLgYnXLlPGY/TLkvHl6+XAADKDzRj4UWpiEoMcbp9XFwc6uttfYEm0ufm4cvzoZLLkBIZDJ7nxt7BiW7RZCnVAA/lAAdj0Ph7APWG9qFodjnmFdgCNunVyaid0YDmeM82qpY2J3ZPxk1SUhKUSiWMRiMsFgtqamqQmZnplmNPdXPnzsXevXsBAA0NDWhtbZUEHkfDq0XjwOlDJCEeR5PcSKCxl0mNFLgpLy8HIM2cnXIkGTcUuPEWxjhY2MTeQ3sK87P1BBrKuAkQZpPFb3q0TCUqjQJZixzNdv2hSTHH85CFhwuXg/r7PRq0scs6LQ4R8YMfVBlw4JORs27EDYonknGTG69FWrRmwkEbADAGMRiCRH1uXCyXAoATWdXoiHCUny06NAdyk2efa4ObmxMDgEwmQ2qqo8k09blxiI2NRXx8vHDZlawbmipFiHdxoubEVCpFAoE942bOnDnDbtuxYweKi4uhUqlw0UUXeXll7sPxovdNFLghxGMocDPFtZzqwYfPHsbf7t6Dz/9a6OvlTEmzznU0Ka4v70Jnk+9LImSicilzZ6dX7pPnOZx+uaPkpuJwK1prnfefETcobm5udvu0q/GaVLkUAMYzHFxcAOvgPHFNnxqzi3Lctj5nxD1u3NGc2I763IxMXC5VWFgI6zjfWFKPG0K8S9ycmNFrLqCYTCb09/f7/cndpcZDM24YY6ipqcFf//pXXHPNNQCABx98UPIFw5RDpVKEeAWVSk1xiiAZGk50AQDa6/Xo7zVCHaIcfSciEZeuRVSSBu31toBN8d4GnHNVlk/XJG5QbOns8tr9Zi6IQVRyCNrrbNN39m+rwqV3zB22nTjjpr+/H729vQgNDR22nbvJeOkbAl2YBbFttkBImI4fdvt49EZ2oyz/JPKKswEAWSfT0JBSj/aYTsADGZ/iqVJBZvOw+5h79/MTOm4Yb8F5gz+C+voGLLr7OZjG8QAKnr97Qvc3lcyePRv/+9//wBhDV1cXamtrJRlKI6EJN4R4Fy9qTsxMJjCzGZyc3qoGgr179+Kbb77x9TLGtGzZMqFh8GTpdDrhi5Rly5YNu12tVuPJJ5/E/fff75b78xkqlfIZC+VgTCv0057iwuOCEax1BGrsQRwyfrYmxY6sm7LvmmA2+bYrvrhUyuKljBsA4HgOZ1zuyNyoLmhDc1XPsO00Gg1CQhz9byZSLuUOPVpHj5gQnQzcBN8vlOWdRI/WkV208MA88BbP/HmU9rhx3zd73VYeA1ZboIbjgGi5e/rnBAKtVivJSBpvuRRl3BDiXZyoxw1A5VJkaisoKABjDNHR0Vi/fj3Wr1+PDRs24Fe/+hW2bNmC2traqR+0wdCpUhS4IcRTAjpw89xzz2Ht2rXIyspCWFgYgoKCkJqaihtvvBGFha6VFaWlpYHjuBFPpaWlHnoUo+M4DknZ4cLl+vIun6xjqss+Ix5ype3lYNCbUHmk1afrEU+WsnR5L3ADAGlzoxGb6sie+WGb87IbcdbNRBoUu4Ixhpr2PvS1RcIiGtutD7HCwtvKtHjGIaR3Yv1prDIrDp1+DAy2Y4XqQoQMHHfrV7h/qpQNh1az49ixFLiREJdLFRcXw2we+/mhwA0h3sUPCdxQU3Ayldn726xcuRJbtmzBli1b8Pe//x3PPvss1q9fj6ioqGH7vPrqqzjzzDMRHh6OsLAwXHLJJaiurhZuLy4uBsdxOHHihGS/008/Hb/73e8AAJ999hk4jsPBgweF27/55hsolUq8+eab7n+gVCpFiFcEdP7pk08+Cb1ej7lz5wpNwYqLi/Hmm2/i3XffxQcffIDLLrvMpWOuX7/e6fVhYWGTXu9EJeVE4MRBW8ZDQ7l3P+QHiiC1HFmL43D820YAQPGeBmSf7rt6Y1n4xHvcMMbQ0NCAlpYWpKenI1yUvTMeHMfhjNUZ2PYnW112bUkHGk50ITFLepy4uDghBdjTGTdWBvxjXxWaj81GZFYFwlJsTaQZD/SGWBDWY/tTFtojg047sWypzqgunMyuQla5rc9PVmkGYlNPoEXt3g8OBrn7p0rZtZjlSFbagkExFLiRyMvLwyeffAKz2QyDwYATJ04gL2/0EfCcaKoUlUoR4nlcUJAtZXCwbxq97gLHOeecgzPPPNPXyxiT3I2lefb+NvPnzx/3PqWlpbj99tuRmpqKrq4uPPXUU/jpT3+Kr776CoCtT5tarZZMjrRarSguLsbGjRsBABdffDEWL16Mp556Cv/9739RVVWFq666Cr/+9a9xww03uO3x2VHGje9YWUDnYJAhAjpw8/HHH2PRokVQiWqmAeDPf/4zfvGLX+CWW25BXV2dS3+kt2zZ4uZVTl5StuNDPvW5mbhZS5OEwE3DiS50NOoRmaDxyVqkzYm7YLVawfPj++NszwD77rvvsHz5cpx99tnj3tduRn4kEjLD0Fhhm7j0w9ZKrPnVAnCco2fKZDJuLFYGk8UKlWLsDBnGGGQ8hwUp4fjn9zx6m+IQEt8MmdIWmNBpHYEbbY8MDS6tRKpkTikS6uMQoteAZzxWNabg7fQyWN3Y66bfA1Ol7FotjudTK7NCxVlhoP/UAQBBQUHIzc1FUVERAFsK+1iBG8q4IcS7OI4Dp1YLjYmt/VQqFSgUCgUUov//pgN7xs2CBQvGvc9zzz0HwPbex2KxwGq1SoItBQUFyM/Pl7yvq6ysRF9fn2Tk+EMPPYQrr7wSBw8exE033YQlS5bgySefnOQjGoGMMm4I8YaAfke/ZMmSYUEbALjjjjuQmZmJ5uZmlJSU+GBl7hUWq0ZwmKjPDZVLTUhsWiiiZzj6tpTsmUwIYHLEgZsCMOzbtw8Wy+iZJFarVdgmKSkJHMehvLwchgn0COA4DqevdkyYajjRhboyaeaPOHDT2to67kk9APCnr0/gye3H0TsgzQphjMFiZTBbrLBYmbAWALhifhJUEV0wdIbDqHOUcvWIMmy0PZMb5W2RW3H4NEf/k9gBNU5rjxtlD9cNSEql3JsVo7fy0IuiTJR1IyUulyovL0f/GN/m8xpH4AYmE5jR6KmlEUIGSRoU91PAlExNFotF+KJgvBk3er0ejz/+OPLy8hAcHAyFQoF169YhWPQlQmFh4bDR4oWFhZDL5cjNzRWuu/zyyzFnzhwsW7YMMpkMb731luTLN7eijBtCvCKgAzejsUf9lcqpn5li63Pj+KBPfW4mZmiT4tLvG2E2+qZJsXiqVIlWi2+++QY9PbYmwWazGVardVighOd5yGS2wEVubi7i4+NRU1ODrq6uCa0hOScCSTmO36v9WyslY79jYmKE82azGR0dHeM+9s6yVrz5/SmcaLY1BDZbbI+F4zjIeA5yGQ8Zb3uD0d1nwqFTHfjwSB2sgz1c+jvDhWOJAzdBAzyUA5N7Y9IW146qjFPC5TPb4hA5EDSpY4p5MuOG+tyMLjMzU3gDbLFYxgzcD+23QWUbhHie+HVHzYnJVGX/ciAuLm5co76tVitWrVqFf/7zn7jzzjvx6aef4sCBA1i1ahVycnKE7QoKCiSZNYAtcJOVlSX5TMNxHDIzM9HX14fnnntOMlDC3ahUyjcYOFjA+9WJeWIcKxEEdKnUSN58802UlZUhKysLWVmujX1+5plnUFFRgaCgIMyaNQtXXnml5AOsryRlh+PEAVu5Sj31uZmw7NPisO/9kzAPWDDQZ0bF4RbknJng9XWImxNrdb1o02iEb0qGlvaZTCbo9Xr09PSgp6cHnZ2d6O3tRW+vbaR3a2srEhMTJ7SOM1Zn4INnDgEAmip7cKqoHWlzogHYgp6RkZFCwKalpQXR0dHjOu5pqREoqOtC/2BgTC7j0W+0oKpNj/JmHYobunG8UYfyZh1aeweE/RjTAgAMXY6eUqYgBkOQFaoB2xsHbY8MbTGTC1gUzjuO+MY4qPtVkA+WTL2begLMDf8fSaZKmd0duLH1uUmT9Llh8Mhc8ylIJpNh9uzZ2L9/PwDbG+BFixaNuP2wwE1fH2Q+7GdGyHTAqR0ZN9Y+CpaSqcnV/jY7d+7Evn37UFZWhuxs23AEq9WKgoICrFmzBoBtvHhNTQ1mzZol2XfPnj3DgjlPP/00vvzyS2RlZeH111/HeeedN7kHNBpqTkyIV0yLwM0zzzyD4uJi6PV6HD9+HMXFxUhMTMQ777wjZCiM129+8xvJ5bvvvht/+tOfsGHDBncu2WXijJuOBj36dUaoQ6d+NpG3KdVyZJ8Wh5K9tjKp4j0NPgnciEulgnu6YY6OwpEjRxASEoLW1lZ0dXWhu7sbOp0OfWP03mhra5vwOhIyw5AyKwo1xe0AgP3bqpA6O0oIIsXFxQmBm+bmZuTn54/ruLOTbB9+N+86iTe/P4XC+m7Udzl/g65VKZAdF4L8BC226z6DUqOHMqRXsk2P1gJVq+2NQ2j35AM3ZqUZRxYV4Oy9pwMAEvs1WNAZg8ORk5825tmMG0gyboJ5Bg1vhd46uRKyQDJ37lwhcHPq1Cl0dXWN2MCbUyjAKZVCiRT1uSHE83iVI2DKDBS4IVPTtddei2uvvXbc29fV1UEmkyEjw1GmvnnzZjQ2NgqlUa2ttvcg4lL14uJifPPNN3jwwQeF67Zu3YoHH3wQH3/8MXQ6Ha677jo88sgjLn9ZPV6UcUOId0yLwM0XX3whdGMHgNTUVLzxxhujftM61OrVq7FixQosWrQIMTExqKysxD/+8Q+8+OKLuOWWWxAVFYUrrrhiXMcaGim3q6iokHSJd0VYrBqaMCX03bYPGPXlXZi5KHaMvYgzs5YmCoGbxoputNf3IirJcymmzshEHyRDdLZyom+++cbptgqFAqGhoQgLC0N4eDjCw8MRERGBsLAwhISEuDxVaqgzVqcLgZvWGh1OHmxB1mm2vi+xsbE4fvw4ANcaFOcn2jJnvq1oF65TyWXIjNVgVkIYZiVpMStRi8yYEIQHOwKQe3f+w+nxdFoLYlttARFtjxzAgNPtXNGU1ILj2k7k9diCaOe0JKBa04OOoMkd2yDKmHL3VCkAGGA8ui08wmS2N09xcjMqjRS4sUtKSpJkih07dgzLli0bcXterYaFAjeEeI2kVIrKE8k0sWDBAlitVmzcuBFr1qzBV199hf/85z8AHP3ZEhMToVar8c477yAtLQ1HjhzBb3/7W5hMJiHjprCwENdddx3+8Ic/4JJLLoHFYsGDDz6IJ598Eq+//rpnFk8ZNz5jcUcqOJkypkXg5ssvvwQAdHV1obCwEI899hiWLVuGJ554Ag888MC4jvHSSy9JLs+aNQvPPvsscnNz8bOf/Qz33XffuAM3nsBxHJJyI1D+g+3Dc11pBwVuJig2VYuYlFC01tgCJkW767Hsxzlj7OVefGgoIJMBFgs0vXoAtv+w8/PzERwcjIiICGi1WoSGhnq8T1NsqhYZC2JQecT2Tc93H1YgfX405AqZpG7blcBNWpRtWldSuBpPrZ2L7LgQxGqHNxK3s1gZGGP2CbEY2l+vO8wRAAnp5cFbAHckmeyMq0OKPgQaiwIKxuPS+lS8nX4CVo6NvfMIxKVSSosFvNUKq4tTv8bSYpYjTGYLNtgCN+7r0TPVcRyH+fPn4+uvvwYAHDlyBEuXLh1x8hqnCQa6bdPVqGyDEM+TlErRVCkyTcydOxfPPfccfv/73+Odd97BunXr8Ic//AE/+tGPhKCMSqXCK6+8gvvuuw+vvPIKVq5ciYceeghXXHEFZs+ejdbWVlx++eVYu3Yt7rnnHgC2EuHf/OY3uOOOO/Dwww8jPT3d/YsfknHDGPNcI2RCprFp1Zw4PDwcS5cuxfbt27Fo0SI89NBDOHDgwKSO+dOf/hSxsbEoKytDdXX1uPYpLi52eppoto3djNxI4Xzt8fE3iiXDzV7maFJc9kMTjAbvNnnlOE7IutHobYGbjIwMnHPOOVi4cCHS09MRFRUlBG3szYotFoswPtKVKU9jOWtNJvjBZsG6DgMKdtYBgCRw09nZOe4JVko5j8QwNTgOOC09ArFa1bCJUlarIzhib1jMccODNgCgD7HCLLNtzzNu0tOl7PrlFnyRUCtcjh0IxpLWsZsMjnpMhTRe7u7JUgDQLCqXipGbwWPigaZANH/+fOFNZVdX16h/u3m1eCS43tNLI2Tao1IpMl1t3LgRra2taG9vx6uvvoqrr74ajDGEiXqr3XjjjWhsbIROp8PHH3+M1atXgzGG7OxsxMTEoLq6Gv/85z8lx7311lthMpk8E7TBkFIpgMqlCPGQaRW4sVMoFLjmmmvAGMO2bdsmdSye54WAS2NjozuWN2HJuY6+KD1tBnS30hueicpaHAel2vbh12SwCI2fvckeuFEPporbM1rsgRnxhCee54WpUjKZTLjsLuFxwZi93BHMOvTZKfT3GhEeHo6gIEc2R1NT07iPmRIZjLrOfhTU2bIZGINkopQ9UDQu3JCx4N3uSyasCu3B0XBHn6DT2mORrNdM+HjijBsAUHmgQXGbWQ7z4K+HnAOiZL6ZjuavtFqtpNb/8OHDI27Li8awMirbIMTjpKVSlHFDiN+jwI1PMABW8H51oq8JPWtaBm4ACNNv7I2+JqOz0zbFSaOZ+Ic5dwiJUCEi3vEho66Usm4mShEkQ86ZjsyKot31kkCJN9gDNyqDARq5HOrBN7P2wIy301BPuyQdQcG2gIix34wDn1SD4zhJ1o0rgZvz8mIxNzlcGPvtUqDGiR5RuVRYt3t7unwTV48Ope0DBAcOFzekIsgysfsw8zzMosfqiQbFVnBoE2XdxCncfx9T3YIFC4Tzx48fH7HJN/XbIMS7JKVSlHFDiP8b8n6U+twQ4hnTNnBjb/Q62fKk4uJilJWVITg4GLm5ue5Y2qQki8ql6kppLPhkzFrqGKHdVtuL5uoer96/LCIcAMAzhosjo7B06VKv3v9QqhAFFl2cJlwu3l2Pzib9hAM3Vy+aged/NA/5CVq3rK873JFVEtojA+fG9w1mnmF74ilYBr9L0JqVWNmUNMZeI+A4GOTiyVKeKcNrEgdu5N4t9ZsKsrOzhWC7xWJBQUGB0+3EGTdWPTUnJsTTJKVSlHFDiN/jOI4mSxHiBQEbuNm3bx8+//zzYX0+TCYT/vSnP+HNN9+EWq3GNddcI9z28ssvIzc3F/fff79kn+3btwuNLMUKCgqE+tNbbrnF401ix0NcLlVX2glmpaS1iYpKDEFiVrhwuXh3vVfvXzxZKra/HzExMV69f2fmLk+GNtr2bajVyvDdhxVC4EYul7uUlRQWrEBGTAhUCvdkx+hCLULTYJmVQ4jOvVk3zep+fBvjKIfM74lEbnf4hI4lLpdSeyDjBpD2uQmTWaF2ZyQrAMhkMsyfP1+4fPjwYae/v3wwZdwQ4k3S5sT0miNkSqDJUj5hYbxfnYhnBexUqRMnTuDmm29GdHQ0Fi1ahKioKLS1taGwsBCNjY1QqVTYsmULZsyYIezT1taGsrKyYb1q9u/fj0cffRSpqamYN28egoODUVlZicOHD8NsNmP58uV46qmnvP0QnUrKiQDHc2BWBoPehLa6XsSkhPp6WVPWrHMT0XCiCwBw4mALllyVBZVGMfpObiIXBW4sXf6RPSVT8DhzTSZ2/K0YAFB1rA25S/Lxi1/8AlFRUW7tq+MqxtvGgocN9rcJ65ZBF+be3i4HolqQ0atFUr9tPPx5TTNQH6yHzsVSJPFIcE9l3OitMvRaeISIxoJXm3wfXPYnCxcuxL59+wAALS0tqK+vR3JysmQbTpxxQ+PACfE4SUNwKpUiZGqgjBtCPC5gQ2PLli3D7373O+Tk5KCgoAD/+c9/sG/fPkRGRuKXv/wlCgsL8aMf/Whcx1q1ahU2bNgArVaLffv24b///S9OnjyJc845B6+99hq+/PJLof+IrwWp5YhLcwRqaqnPzaRkzo+FOtQWqLGYrCj7fvylQJMli3BkT1m6urx2v2OZuSgW8RmO8qaDn9QiOirap0Ebu+4wcYNi92bcAADjgO2JNRjgbfejsspwUUMKXO3GJs648URzYrtm6nMzqqioKKSmpgqXnTUplnyI7KfADSGexqscGTdUKkXI1EClUoR4XsBm3KSnp+P3v/+9S/ts2rQJmzZtGnb9WWedhbPOOstNK/O85NxINFXa+rHUlXZi4YWpY+xBRiJT8Mg7OwGHv6gBYGtSPHdlslcaA4tLpSydXR6/v/HiOA5LrsrC+388BABordGh/EAzcs6Y3Jhsd+gOMwOwTbkK65bbAipu/lH1KI34Oq4OFzfaXlcpfaFY3BGDg1Hjb3QuHgmu9lDGDWAL3GQGGQEAsXIzODAwdz8hU9zChQtx6tQpAEBRURFWrVolmZTGU8YNIV4lbU5MgRtCpgQqlfI6Bg5WP3tPR+8xPcv3X5ETt5uR58jUaDzRBbOJRgFPRv45ScKH/67mPtSXd3nlfiWBm27v3Od4xWeEIXNhrHD5+48qYDZ6/vdMzltHPfWFm8AG01/kFg7a/rH3Ge0Ejjk9lYR3oEzrKF87pyUBMQOqEbcfejKIAjdBZpP0djdqNcthGTykggMiaSz4MHl5eUKgxmg0oqSkRHK7eKoU66OyDUI8TdqcmF5zhEwJlHFDiMdR4CYAxaWHQa60/WjNJquQfUMmJixGjZR8x7Suom+806RYHLgx+1HGjd1ZV2aCl9siWr2dAzj2da2PVwRY5YA+VFQu1eWhpEIO+DKhFjq5LZtFBh6X1KdCbh3fNw3eaE4MAJYhY8HjabrUMEqlEnPnzhUuDy2XoowbQryLGoITMvVQqRQhnkeBmwAkk/NIzHJk3dQepz43kzX7XMfo56qjrdB3D3j8Pof2uHFlYpM3hMWoMXe5o5Hroc9Poa/H6NIxLBZpBghjDM09BlgmMQ2tJ8wRnAj1VOAGgEFmweeJp4TL0QNqLG1JHGUP0b6ijBuV2bPBFOpzM7aFCxcK52tra9HS0iJcpg+RhHgXp6JSKUKmHCqV8glfT5GiqVLeRc9wgBKXS9VR4GbSUmdHISTCVk5htTIc39c4xh6TJ864gdkMq16PPXv24O9//zueffZZHDhwwONrGMuii9MQpLEFBkwGC/Z/UjXitgaDAc3NzSgpKcHu3bvx/vvvY8uWLbBarbBaGdb/Yz8WP/ElznjyK1S16Se8pp5wcYNiucuNg11RE9KLg5GOD/kLO2KR2jv2FDdJc2IPZtwA0sBNuMyKIBoLPkxCQoIw1h4Ajhw5IpynjBtCvEtSnkjBUkKmBMq4Ie506NAhPPXUU1i7di2Sk229RcfTX9RkMuGFF17A6aefDq1Wi5CQEGRnZ2PDhg2or/dOxYQnBWxz4ukuOddR2tNSo4NBb/LaGOtAxMt45J+TiP3bbIGJ4r31WHhRKnjec024ZFqt5LKlqwsdHR2orbWVJHV2+n5EuEqjwOKL07Dn/VKAs6JkbwPmLk9GZKJG2ObIkSMoLS1FZ2cnenp6YBjyDWpbWxtiY2NR39WPdr0tY6eksQczY0MmtCadKONGaeSh6udhCPbcm4i9sQ1I1YciZsD2YeOihlS8kXEc/fKR+8n0y71TKgUAOiuPPiuHYN4WwYqTm1FDY8GHWbhwIbZv3w4AOHbsGM477zzI5XJwanHGDQVuCPE0njJuCJl6KOOGuNHjjz+Ojz/+2KV9Ojo6cOGFF+LQoUNISEjA+eefDwA4efIkXn/9dWzYsAFJSUljHMW/UcZNgIpK1AhjrMGA+nLff8if6vKXJIIbDNT0dgygpqjdo/fHyeXgw8KEy5bOToSLsnC6/GREeGQWYIg9iQFVG6xWK7798CQACKVdGo0GLS0taGlpQUREBBYsWIDLLrsMS5cuBQAhAp6f4AhUlTRMvC+TWcnQF+wImoR2ezY+beEZtidVwzyYyRJiVuD8xtFHhEuaE3twqpQNhyaTI1AUR31unJozZw7kctvPpa+vD2VlZQCGjAOnjBtCPE4SLKXADSFTgyTjxr9K+wMVA2AB71cnd/3kzzrrLDz00EPYunUrGhsbJdM+nT4XjOGqq67CoUOH8Mgjj6CmpgYffPABPvjgAxQUFKCiogK5ubluWp3vUOAmQHE8J8m6qTtOgZvJ0oQHIWNetHC5aI/nU+5k4aLATVeXXwZuGpsaoedaAAZw4FBd2Iba0g4hpXHmzJmIj49HVFQU1q5diyuuuAKLFy9GTk4OgoKCUFdXBwDITxQFbhon11C7J9wRnNB2ySZ1rPFoUxmwJ7ZBuJytC8fsrsgRt/dWc2I7cblUrNwMj9aPTVFqtRr5+fnCZXuTYl7jCNzQVClCPE9cKgWTCcwLfyMJIZNDpVLEne677z489thjuPzyyyWl7CP5z3/+g507d+Lqq6/Gpk2bhC/i7DIyMhAdHT3C3lMHBW4CWHKuqEFxKfW5cYdZoibFp4ra0dPm2Q9ykpHgXV0IE2XgdHd3e/S+x4sf/M86ItbR22Xff0/CamVgjIHnecycORPt7e1obHT0BgoJCUFYWBgaGmwBD3dl3ACAThK48U5F6OHIVpzS6ITLK5qSETHg/BsCbzYnBmxjwe1fgAXxDBE0FtwpcZPiiooKdHV1ST5EUsYNIZ4nLpUCKOuGTH0bN24UenTYTwqFAunp6di4caPfvJ+bFEmpFL3HIN712muvAQB++ctf+nglnkWBmwA2I8/xjX93Sz962unb4slKzolAWOzgBzkGFO9tGH2HSZIEboaUSun1ehiNrk1x8gR7MCltgSNQ2F7Xi7LvG4WsG/u6e3t7hW00Gg0iIyPR3m4rOcsTBW7aegfQopv4m3XxZCmVQQblgOd6EQk44PPEU+jnbfetZDJcVp8GmZMR4d5sTgwAZnBotzgyj2gsuHOpqamIjHT83Txy5IikOTEzGsEs9IaUEE8Sl0oBNM2NTH3Hjh0DAFx88cVYv3491q9fjwsuuACNjY148cUXsXLlSpi98CWOR1HGjfcxwMo4vzr5IqHbZDJh7969kMvlOP3001FQUICHHnoIt912Gx577DHh9RcIKHATwEIjVY4gA4DaEsq6mSyO5zBrqSPrpmRvA8xGz32Qk4dLR4KHhoZKuqr7w7c0cXFxAIA+UzeyTosDB9v6vv2oAoY+W1DC3khZJfomVaFQIDIyEkajET09PYgJDUJsqCNDpbh+4lk3RhWDQSXqc+OlrJtehQk7EmuEy7GGYKxoTh62nUGUwqnyeI8bm2ZRnxsK3DjHcZwk6+bIkSNgQ+qqKeuGEM/ilErpt/cUuCFTnP2D46uvvootW7Zgy5Yt2L59O7777jsoFAocPnwYn3zyiY9XOTlUKkV8pbKyEgaDAVFRUXj++eexYMECPPHEE3j11VfxyCOPYMGCBbj77rt9vUy3oMBNgEuZFSWcP+XhZrrTRd7ZCZArbS8dQ68JZT80eey+hpZKyWQyhIY6SpJ6eiZXUuQOYWFhiIyMxPHjxzFvVTzkisHnpseEg59Ww2w2C29aYmJiAADWwf/Uw8PDwfM8OjpsQcXZSY5SsML6yQWlJGPBvRS4AYCT2m4ciWgVLs/rjEZud4Rkm34vZ9wAQKOoz02E3AI1jQV3at68eUL5X09PDyqapK9vK/W5IcSjOI4bMllqwIerIWRyampq0DmYMZ2cLP0iZ8GCBVixYgUA2xcFUxpNlSKDKioqMGvWLKcnT7B/Odze3o77778fP//5z1FRUYG2tjb8/e9/h1qtxgsvvIDNmzd75P69iQI3AS51tiNwU1faCYuJ/phOlkqjQO5ZCcLlY1/VChOU3E3anNgWyPDHPjdz5sxBf38/tv9vK7KWacHAYJEZcHBvIf773oeora3FzJkzJaVeAJCfn4+bb74ZsbGxANwduHFklYR5MXADAN/E1aNJpRcuX9AwA5GifjcDXu5xA9jGgvdaHH/y4xXU8NOZ0NBQyeSBw0ePAjJHmRmjkeCEeJy4XIoZKFhKpq6jR48CAGbPnu30do1G48XVeA5HU6V8gPP5FKmhJ8ALrQmGsH8ZbDabcfHFF2Pz5s3IyMhAVFQUNmzYgGeeeQYA8Ic//MHra3M3CtwEuKSscCEDwjRgQUNFl28XFCDmrZwhnO9s6kONh8rQhmbcAIBW6+gF4w8ZNwCwePFi5OXl4dSpU/jhxBfoijuAnvASdIcVo7S8GOHh4VixYgVCQ0NhtVqFjIaQkBDMmDEDwYN9ROaIAjdFbgzcqPtkUHijz80gC8+wLbkaBlG/m8vr0iG32h63LzJuAE6SdZNI5VIjWrx4sXD+xIkT6I9wZExRqRQhnifJuOmn5sRk6rJnHI8UuCkvLwcApKene21NHkEZN2RQZmYmiouLnZ48ISQkRDh/8803D7v9pptuAgDU19fj5MmTHlmDt1DgJsDJlTIkiaZLUbmUe4THBSNtrmOs3LGvaj1yP84CN+KMG38I3DDGEBoailWrVmHZsmXgOA4WfgBW3giZORjBvTOwdP7FSEqy9Qbi+ZH/7IgDN43dBrTqJp4iP6CyYiDI8ebBm+VSANCjNOLzpFPC5egBNc5vnAGwIT1uzBbwXnqT0yjqcxMjN0NOY8GdSktLQ4QoWHMqPU04T41SCfE8Ti0ulaLXHJm67Bk3c+bMGXbbjh07UFxcDJVKhYsuusjLK3Mz8Xs7ZvVYJjohQ6Wmpgrn09LSht0eHBwsZPa3tLR4a1keQYGbaSBV1OemhgI3bjP/PEfWTW1JB9rre0fZemLGyrjxh1Ipe7PksLAwrFixAnfeeSc2btyIvOhzEdY5C8G9aSj8vA1Gw9gZHnHaIMSIGhRPKuuGk2bdhPTIRtnYMypCe3Agqlm4PKs7EnO6oiTjwAEgyEvlUu0WGQYGp1zxHBBHWTdO8TyPefPmCZerEhOFEBf1uCHE83iVuFSKMm4CgdlkwUCfye9PZpN7B04MzbhhjKGmpgZ//etfcc011wAAHnzwQcTHxwv7fPLJJ5gzZw5UKhUSExPdso5nnnkGmZmZbjmWM9zQL+Uo68bjGAAr4/3q5ItwXVhYmJCxZu93I2a1WtE1+BlKnJ0zFXn3K2jiE+I+N51Nfehu7UdYjHqUPch4JGaHI3pGCNpqbQGbY1/XYuUNeW69D5kou8bSPbzHjT9k3Axl/6N4wY8X4p3HfoDVzKDvGsChz07hrCtHf9PAcRzmJIXh61JbRLywvhsrcmMnvJZerRkxzUrbunS++XO3N7YBCX0aJPfbnpeVTcn4zwzpz01lNqNfqfT4Whg4NJnlSFXayrMSqM/NiObNm4ddu3YBAHrUauiXnI04XgZZ6NT+T5+QqYBKpQLP4c9P4cCn1b5exphOuzQNp1+e4ZZj6XQ6VFZWAgCWLVs27Ha1Wo0nn3wS999/v3Bdd3c3rrnmGtx666145ZVXJO/5JmPdunVYvXq1W47llLPAjcz7X5iR6Wn16tV48cUXsWvXLlx44YWS277//nsYjUao1Wrk5OT4aIXuQRk304A2Wo2I+GDhck0xZd24A8dxkqyb8h+a0ddjdOt9iDNurHo9mNHodxk3IwmPDcaCC1KEy0e/rEFnk36UPWzc2aC4N9TxzZlGJwN88AWQlQM+Ta5Gn8wWJJEzHhc1zoRR5vhgEuSlkeCAtFwqXm6GxeK5cfZTWUREhCT9tmXtWqS89irU8+f7blGETBPUnJgEgoKCAjDGEB0djfXr12P9+vXYsGEDfvWrX2HLli2ora2VBG0A4IsvvgDHcfjjH/+IJUuWjNgbx1UZGRme/dDKSfsIUp8b4k0bN26EUqnEyy+/jO+//164vq2tDRs3bgRg638TFBQ0whGmBgrcTBPirBvqc+M+MxfHITjMlilhMVtR9E2dW48vGzKFydLdLfn2xWg0wuDHaeSLLk5DSKTtj6TVwrDnvRNj1j27s0GxPsQCK2e7P5mVQ3Cfb/7k9SpM2J50CmwwiTTCpEJJ3g1CSqnaaw2KgRazHJbBO1bytpRt4py4XKqwsBBmL5W0ETLdUcYNCQT2/jYrV67Eli1bsGXLFvz973/Hs88+i/Xr1yMqKkqy/eLFi3HNNddAr9cjKCgIYWFhKC4uBsdxOHHihGTb008/Hb/73e+Eyx988AFOP/10hIaGIjIyEueeey7KysoA2N4rKhQKbNu2Tdi+u7sbd955JxISEhAeHo4rr7wSDQ0Nwu0GgwEymQzvvvsufvnLXyImJgbR0dF47rnnnD5WjuOGTJaiwI03WMD51cldPv30U5x55pnCyWi0fTEuvu7TTz8Vtk9LS8Nf/vIX9Pb24txzz8WyZcuwevVq5Obm4sCBA1i4cCGefvppt63PV6hUappInR2Fo1/aGujWlXXCbLRArqQUxsmSyXnMWZ6MHz62pcIW7a7HwotSIVe457nl1GpwSiXY4B8sS1cXgqOiwPO8MP6uu7sbKtGbXH+iUMpwzlVZ+PzVIgC2XkBVx9qQMT9mxH3mJg9vUCzue+MKJgP6NBaE9Nr+1IX0yNEX4t6sqPE6FaLD99FNOKvNNkq+I3o+6pKWYUb9N1B5MePGDA6tZjniFbb7LCsrm/rTLDwkPz8f27dvh9lshsFgQHl5OfLz8329LEICHjUnDjwLL0rFPFGWsr+SKdz3BY+9v838cWZqvvbaa7jzzjsRExOD3/72t1Cr1SgsLIRarZb0p7FarSguLhYyCbZv344bbrgBmzZtwmmnnYauri589tlnwqjx48ePw2w2C9k7Op0O55xzDlQqFTZv3oygoCA88MADWLduHb799ltwHIeSkhJYrVZs2rQJP/7xj/Huu+/inXfewb333ot169ZJMlIFPC8EbCjjhkxGa2srfvjhh2HXi69rbW2V3LZhwwZkZGTgqaeewg8//ID+/n5kZGTgl7/8Je655x7h9TCVUeBmmkiYGQ5FkAymAQssJivqy7skWThk4mYvTcKh7dUwm6zo15lQvr8Z+Uvc00yO4zjIwsJgHvzjZOnuRhDPQ6vVCo22enp6EBcX55b784SMBTFIzo1AXamtYdje904gJT9yxMBhnFaFmNAgYaJUkajPjZxz/Y1AX5hZCNyE6nh0uHAM5uYJ4t/GNiGxPwSp+lAAwMnMtQjrqUaQ2eS4Ly9MLW8UBW5KS0uxatUqock0cVCpVMjLy0NhYSEA27enFLghxPMkzYkp4yYgyBUyt32pNVXYM24WLFgwru0XLFiApqYmrFu3DmeeeSYA4N///jfy8/MlEzkrKyvR19cnBGL+9a9/4dprr8W9994rbLNmzRrhfFFREUJCQoSJO7/73e9gMBjw/fffCx9mw8LCsHTpUpSXlyMnJwdFRbYv3B566CFcd911wvr+/ve/o6KiYuTAjZ2VpkqRibvpppuEMd6uWL58OZYvX+729fgLKpWaJmRyHjPyIoXLVC7lPqoQBXLOShAuH/uq1q1jEKfCSPDRcByHpddkg+dtgQFdhwGHvjg16j5z3NjnRh8qnizl21g1G+x30yu3lUYxXo6iWT9FiMm7QZNGs6PPTVdX15Qfj+hJ4m9KT548id5e90+PI4RI8ZKMGwrckKnHYrEIwY/xZtz09vaiqqpKMjq8sLBw2CjxwsJCyOVy5ObmArA1Of7www/x6quvOp2qU1hYiFmzZoHjOBgMBmzZsgV33323JAPBHtSxl0sVFRVhxowZQtAGADo6OgAA0dHRTtcvLZWi/nmexsD5fIrU8KlS9CWgJ1HgZhqR9rlpc2twYbqbtzJZON/RoEft8Q63HXsqjAQfSW9vL+rr6xGZoMFcUYr0kS9q0NXSN+J+7mxQrNc63jyo9TLwPn4v0Sc345PkKoDZMn8MqijkDCyEN2coGhiPTovjm097HTwZLj09HaGhtgwpq9UqvBEnhHgOJ8q4sfaP/H8FIf6qvLwc/f39iIuLk4z6Hk1xcTEYY5JATUFBwbAGxYWFhcjKyoJycBrl008/jbVr1+Kee+5BfHw8fvSjH0n61RQVFQnHPHLkCHp7e3HeeedJjmnf3r7WoqIirFixQrJNUVER5HL5yE2ORYEb+oxBiPtR4GYaSZnlCNz0tBnQ1UxvhtwlIl6D1DmO5/fYV7VuO/ZUzLipr6/Hc889h//3//4f3n33XQC2EZsaUSPnPe+Wj/gf+1w3Niju11hgkdnuh2Mcgn00FlysTqOHqmOXcDmcJeL0tomPPZ+IBpPjeaDAzch4nsfcuXOBwd9Ve+o7IcRzxBk3VCpFpiJX+9sAtoBMdHS0EDzR6XSoqanBrFmzJNvt2bNHEsyJjIzE3/72N7S1teHtt9/Gl19+iYcfflhyXPv2bW1tADAsmPTNN98gJiZGCMoUFRXZ/u8bsr6srKyRJ/OIM25oYiUhbkeBm2kkJCII0TNChMtULuVe4tHgNcUdaG9wT0mFLNwRxLAMZtf4e8ZNaGioEFDS6XTQ6XRQquRYcnWWsE1NSQcqj7Q63X+OkwbFE8ZJy6U0Ov+osbfqDyKqrVC4fE5LIpL13mucJi6Xqq+v98sAoD8wlJcjp6wccc3NAICmpiY0D54HAENJCXS7dqHnix3o/uRTdL3/Pjreehttr72GludfoAaNhEwAp6JSKTK1XXvttWCM4fPPPx/3PkVFRZKAjL35amys44ud4uJifPPNN07HhCuVSlx11VVYtGiRMAWxp6cHNTU1QsZNcrItQ7yyslLYr6urC88//zxuueUW8DyPnp4e1NbWDgvcFBQUDLtOjKMeN17n6ylSnpoqRZyjwM00kzqLxoJ7SlJOBKKSHIGxAjdl3UzFjButViuUlwCOFNyZi2IxIy9CuH7PeydgNAyfqGRvUGw36bHgWlHgxsd9buwGFArkl74BlcH2OuTB4bK6dKiYd9bXY+Whtzr+ky0vL/fK/U413e9/AP3mzYgNcfw+i7NuevfsReMDD6L+7rvRcO+9aHzwITT//vdofe55tL/6Klg/TcQhxFXS5sT0GiLTw9B+NomJiVCr1XjnnXfQ0dGBr776CjfddBNMJpMQuLn11ltx11134YMPPsBXX32FX/3qV9i1axduueUWABDKe+3bz507F7Nnz8btt9+Ozz77DP/973+xfPlyJCQk4KGHHpLs46y3ztDrJCSlUvSlBSHuRoGbaUbc56bhRJfTD81kYjiOw/zzHVk3ZT80o183+dHT4+lx44+1xImJjsla9sANx3E499oc8HJbwEDfNYADn1Y73X+uWxsUO1J2/SVwY5DLoTD3YXbx38GYbX0hZgXOG0gB55UfJ4dGkyPrhsqlnBs4eRJ8aChmXH6ZcF1BQQH+P3vvHebGeZ573+8MOrC9F25f9s5lE5soiVSvtmVbtlVcE8eOHPscO+Xk2CeOE8d2EttxiR3Zn+Qiuao3UpQokqLY+y7JJbm9913sogMz3x9YTNm+6MA+v+saCS92ZvACRJm5537uxzduA7fs2gnR4YB+yRJkfOLjyPqLzyH3f/0vmLduBQAIdNJJEPOGwomJhYiypAnwdzb87//+b/zmN79BaWkpfvjDH0riSmC9pUuX4ujRo3jiiSfwwQ9+EOfPn8fBgwexfft2AH4RJicnR3Lt8DyPF198EWlpaXj44YfxxS9+Edu3b8e7774Lo9Go2kZZTuV0OnHjxo05Czcgt2lUiHUY8cSFiCzxcQZDRI288lToTRq47F4IPhHtV4dQsTYn1tNKGqpr8vD+Cw1wWN3weQXUHu7AxrvLQ9qnSrgZGgagdtx4vV44HA6YTKaQHifcFBYWSmKAMiQvPc+E9XtLcfr1ZgD+PKClW/JVbiXAH1D89lV/t6PQA4plgdLg4MF7GHza2IpdTq1fNEkdbYHHdhQ6y04AQLGQgvWePJzR9cy0eVjo8mpRpfeLi42NjXC5XNPXri9QvIOD0JWWYtmSJXjz0CEIggCbzYaGhgYsXrwYhqVLwcwmGJYvQ97XvgbG+0vxRLcLtmPH6KSTIIJAFU7sJPGTWBhM1eHx0UcfxaOPPqq6T3mx7itf+Qq+8pWvTLvPz372s/jsZz+ruq+yshL79u2b1zYGg0Eqv5oOxhSOGxJuCCLskDS2wOB4DiXLFW3BL/XHcDbJB6/lsPrmIml86d12eD2hBbTxaZMzboxGIzQaWXeNx3KpiY4b5YHGhjtKkZrtv6IqCiIOPVcPcUI99KowBhS7DQI8WvkgwmyNfc6NUyv/+2lGz6I+VW7hucGbh0W+lKk2Cyv9Ph6G8SwJn8+HhoaGiD9moiG6/PlKRr0eixcvlu6/cOGCdGDKGU3wtLTCp/wc8v5/X8FOIfAEMV8onJggEhBy3BBERCHhZgGiLJdqrh2YdMJMhMaKnUXgtf6PlmPUg6vHukPa31SlUowxVblUvAs3NptNFaKs0fHY8WH5JLjrxgjq3utUbT8xoLh3NISDd6Z23VjioFzKqZHLlIweD/YVtmJI53+ODAy3ukqRJugiOgcRDNXVcmD0lStXIvp4iYgmNxfu1lYIY2P+7iDjAuTVy5dhdzjg6e6G6PWAM6uDpTmD37kkknBDEPNGFU5M5YYEkRAwThFOS8JNxBEB+EQurhY6o4wsJNwsQEpXZktfrvYRN3qa4++kP5ExWnRYdlOBND77Zgt8vuB/wFTCjSLPxmKRS4vGxsLTwSqcmM1mpCvm3tHRofp72apsVK6Xy/SOPX8DY0Ny96i8VAPyU+WD9/OtwyHNZ0wZUDwSB8KNwnGj93rh5gW8tKgJHvgdWnrwuN1VDl2Ea4aXLVsm3a6vr4fH44no4yUaxlUrIVitsL33Hqqrq2Ee/9z5RBEXLlzAyEsvw9vVDcOqVeAVYirT+9+7VCpFEPOHMyrCiekzRBCJAUelUgQRSUi4WYAYLFoUVstuhsbzU7dkJoJn3d4ScOPi2OigE9dOBJ9XoiyVEt1u6SBWKdzYbLag9x9JAm0nAaC9vX3S33d8eDH0Jr+A4Xb6cPh39aqSqrWL0qXb59uGQ5qLLW2C4ybGlwUcWtlxYxgXS/oNThzUyd3IMkQDbnWVRjSsuLq6GtrxubjdbiqXmoBl927oSkrQ/a1/weiLL2JDWRlMYzakjFjR9evfYOCXvwAYg/mmrWA8D3FCBkDAJUcQxNzhqB04QSQeVCpFEBGFhJsFSvka2enQeL4vLrsSJTKpWUYs2SKn8Z95sxlCkCVpnEK4AeScG7OiNCMeHTfA7MKNOU2Pmz5QJY2bLvSj4awsJK4tSZduhyrcjKV6IY6rNRovB4M9tl9/LoXjxuCRT/abNCM4rZHL60qEVGz2FCBSaLVaVXZLXV1dxB4r0RBFEab165H2wP3g9Hp0/Z9/ROG/fhvb33sPuw8exLKDByHY7cj7h7+HMdAJZDyc2LhmNbI+8xnoKipi+AwIIjFhExw3dIxCEPEPI+EmyjAIcbYAbNZZE8FDws0CRdlJaqTXgcGu+HRsJDLrby8FG//+Gul1oOHM5G4Bc4HT6cAUHaMCwk2iOW66urqkFspKlt1UgKIlGdL48O/q4bT5HShKx83F9hGEcuwuaACHRX58S4zLpZyKcGnDBJfGGW0PGvlhabzGm4vF3gxEihUrVki3qVxKho1/gLP/8i9R8M1/gnH1amgyMmASRbh1OnQVFqDj/vuR8ZGPgOl0qm30ixcj+wt/Bb0iQ4ggiLmhdNwAckg4QRBxDJVKEUREIeFmgZKSaUBOidy1ponKpcJOep4JVTV50vj0G81BB0GrOksNJ47jJj8/H/y4A8Hr9aKnZ3LJGGMMuz++RBXofPTPNwD4O0sFsu7GXF64xsyTtp8PypybmAs3U5RKSTDgoK4N/UwO5dzpLkauLzIt36lcanZS77oLZb//Hcr+9EfovvXPeHf3zTiycyeO6fVwTHFSyTjOL7oyuvpEEPNF2Q4coIBigkgIyHFDEBGFhJsFjNJ103ie2oJHgg13lkq3BzttaLoY3OusFm6GAcR/ODEAaDQa5OfLJWNTlUsBQFqOCZvuLZfGV9/vQtuVQZj1GizOkwVGx3DaVJvPmbGJOTcxxDFNqVQALxOwT98EB/yiDg8Oe11lMAvaSeuGCpVLzR1NRgaW7N4NPjsbgL+N+oULF2I8K4JILgJd2QJQQDFBxD9MowGXkgI+NU0V1k9EBuoqtfAg4WYBoxRu+lpHMTpIB0bhJqvQgop18ut85o3moGr1VcLNyDCAxCiVAmbPuQmw9tZFKhfYu7+9Co/bpyqXcgynT95wHiiFG6NNA94TOzeES+m48U5dmjTGebBf3wLf+E+hGVrc7i4DL4Z/3lQuNXd4nse6deuk8ZkzZyiDgyDCCNNoAMV3pOCg4xOCiHc4vR760lLoShZBW1gY6+kQRNJBws0CJqPAhPQ8ufSCuktFhpo7y6TbvS2jaLs8OO99TGwJDqhLpRwOx5T5MfHAXIUbjuew+xNLpVb11n4nTr7SpBZuRkJz3LiMAjxa2b5rjqHrRplxoxFEaKb59+vmbXhPJ79uOYIJu9yLwt4Vi8ql5sf69eul2/39/WhpaYnhbAgi+VDm3IhOKpUiCIIgFjYk3CxgGGMoX5MtjSnnJjLklKSgdGWWND79+vxdN0rHjTBFODEQv64bpXAzODgIu90+7bo5i1Kwbk+JNL5woBUVvHzV1TlqgeAL4WuLAbY4yblxatWPPSnnRsFVzSBqNXKZXbUvA2u9uWGdj1arxZIlS6QxlUvNTGZmJioUHaPOnDkTw9kQRPJBLcEJgiBmQAQEkcXVQrVSkYWEmwWOslyq8/owHGPuGM4meam5q0y63dUwgs7rw/PaXl0q5RdutFotdOOdbID4zblJT09XuYNmct0AwMa7y5CW6w+mFEWg8Y02pGj9AccQObitKdBwQtCLPV0WSFKs/IzrRhKnRp1VE8i5EadZjmo70M6NSutv8uSjxJs67fpzXZQsX75cuk3lUrNTU1Mj3b58+fKMoiRBEPND2RKcwokJgiCIhQ4JNwucvLJUmNL8J/+iCDQHGZ5LzEx+RRqKlqRL49OvN89rez59clcpIDFybhhjKtdNR0fHjOtrdDx2f3ypNB5oH8PtWrmkzx5iQLFNkXNjHtHE7OqAj+fgUXRgmNgSfCIiA97St2CE+TsYMTDc6i5BhqCfcbv5QOVS82PJkiWSKEkhxQQRXlSlUtQOnCAIgljgkHCzwGEcQ8Ua6i4VDZRZN+1Xh9DdODL9yhOYynEDJEZLcGDuOTcBihZnYPl2OdiurNuLDJ8/+8YeYkCxPc0DkfnVGt7HwWDjQ9pfKKhbgs8s3ACAi/nwpr4JbvjzcHTgcYerHHoxPM+ByqXmB4UUE0TkYMpSKXLcEAkIY0y1cByH9PR07NixA0899dSk34tvfOMbk7bR6/UoLS3Fxz/+8WkvDjQ3N0+5XW5uLjZs2IDPfe5zeOutt+j3KckQAfjAxdVC77DIQsINoSqXarsyCI8rPkNuE52iJRnIr5DbI555o3nO23LTCDeJ4LgBgKKiIul2e3s7BGH2MqSbHqqU3GBMAG63awExdOFG4AGHRX6Pm4fjI+dmpowbJUOcC2/rWiGO/zymiXrsdZWCC9OvJZVLTU3Pv30HN/bsxbXtOzD4zDPS/RNDiltbW2MxPYJIOtThxJRxQyQujz32GB577DF87GMfw/Lly3H06FF85jOfwSOPPDLl+mvWrJG2ueuuuyAIAn77299i48aN2L9//7SPYzabpe0efvhhbN68GYODg/j5z3+OvXv3YuPGjbh27VqknmZQCE4nfGNjEGdxHRMEQcINAaBwSTr0Jv8JpM8joLVuIMYzSk4YY9igcN00XxpAX+vo9BsoSHTHjVK4cblcGBiY/T2mN2mx6yOy+2ORj8caNw+PwwiPUzfDlrNjS5PFCPOIdoY1I4tDJdzM/aClRWPFCW23NC4SUrDVUzTDFnOHyqWmxjc8DE9bG3z9/arPIIUUE0RkYEal44aEmwXLW28BH/0o4J5jBqPb7V//rbciO6958PTTT+Ppp5/Gr3/9a7z//vvYt28fNBoNfve73+HVV1+dtP4DDzwgbfPCCy/gxo0b+MhHPgKPx4PPf/7z0z5Odna26rFeeeUVNDU14fz587jllltw5swZ7Ny5E21tbRF5nt7BQXiHh+e1jW9kBJ7WVvis1ojMiSCSCRJuCPA8h9JVctcjagseOUpXZiF7keySOfNm85y249PSpds+xY+i0nETz8JNwLIbYC7lUgBQsS4HletkR9guhxYWIXTXzaScmxjhUgQUG7zzc7ac1/TiOj8kjVd5s7HCkzXDFnODyqWmhlMGpdrVZRsbNmyQbtfV1VFIMUGEAc4gf+aoHfgC5a23gPvuA373O+Dhh2cXb9xu/3q/+51/uzgSb5Ts2bMHn/jEJwAAL7744qzr6/V6/Od//icAoKGhYd4XVNasWYP9+/dj79696OnpwZNPPjnvOc8FT1cXvL29EMdd1aIozrowvR6iIEAYs0nbEXMl9l2kJnWVAov1i5LUkHBDAIAq56b50gB8XvryjASMMVWHqYZzfRjsmr3EiU9Pl26LTqfUGlXpuInnUilg/jk3AXZ8ZLHkCNOD4Ta7Dvah9JDmonTcGOwa8O7Y/NA4g3TcAAAY8K6uDb2cLBJs8xShxJcS8ryoXGoynGn6DjcUUkwQ4UfVDpwcNwuTX/4SCJTJvfTSzOJNQLR56SX/2On0bx+nBPLR5up+yc/PR1aW/+JMb2/vvB+P53n86Ec/AmMML774YkTKehmvztubmLsz1aJJTwfTaCDYbf4uKQRBTAsJNwQAoGRFFnit/+3gdnjReW04thNKYirW5CCjYFxwEYGzb7bMug2flqoa+0b8ltJEcdwAwQs35jQ9bvpAlTSu9vLIb88PaS5uowCPThYnY+W6cWrmn3GjxMdE7NM1YYz5D2Q5MOxxlSJLMM6y5cxQudRk1K2J1Y4ajUZDIcUEEWZUpVLkuFmYPPMMcP/98ng68WaiaAP4t1PkkcUbo6P+Unm9fm6dIUVRlC7QKR3M86G6uhobNmyAKIo4dOhQUPuYEcYAQYDodkPweCA4nRDsdvhsNvhGR+EbGYF3aAjegQF4+vrg6emBp6sbEAHR6yXHDUHMAgk3BABAq+exaFmmNKZyqcjBOIaaO0ul8bVTPRjpm7m0gjMYVB02fCPDABInnBhQ59z09fXBO48gumU3FSClRH6u23szoXGEkHPD4iPnRtVVKshgPhvnxRuKTlNa8LjLVQ6LEPxzonKpyXBGuSW9OEWHGwopJojwwukV4cTkuFmY6HTAH/4ws3gznWjzhz/4t49DRFGUsm1Wr149p23effddOJ1OLF68WJWrNl/Wrl0LALhy5UrQ+5gWjoPo9cJ14wZc9fX+/zc2wt3UBHdLC9xtbfB0dPhLqnp64O3rg3egH6Jv/PjHR81R5osALq4WIrLQK0xIKLtLNZzrheAj5TtSVG3IRVqO/wq+KIg4/VrzrNuoAorHc26Uwo3dbp+XGBJtsrKywHH+rxxBENDfP/fW84wx7Hl0GTzjnZTMIoel729EKH0HVTk3w7ESbkIolVIwwDnxlr4FgvT6aHG3qyKkNuErVqyQbl+9ehXuuQZDJimqUin7ZOFmYkjxiRMnojIvgkhW1I4bEm4WLDOJNzZbQok2Pp8P169fxyc/+UkcO3YMer0eTzzxxIzbjIyM4NVXX8Xjjz8Ok8mEn//852As+PLu7OxsAMDQ0NAsa84fxvzHeEyrBafXgzMawZnN4FNSwKelgc/IgCYrC5qcHGjy8qAtKIC2qAi6RYugW7QITBu7ZhEEkQiQcENIlK/JBsf7fwwcox50ULlUxOB4TtVhqv5EN4a6Z3bM8KlyuZQwnr6fkqLOMwlYb+MRjUaDnBxZHOzp6ZnX9gXFKTieLpeDFXblobCxJOj5jKUrHDdWDVgMLvSoHDch5si08aM4opNL0DJEA+50lUMjBneAV1VVJVm4PR4Prl69GtL8Eh1VOPEUjhsA2LRpk3T7ypUrGJ5ndw2CIGTU4cQk3CxophNvLJaEEG2kPBeNBosXL8bTTz+NlJQUPPfcc6isrJy0/v/7f/9P2iY9PR333nsvRkdHcfz4cezatSukuQTKeEMRf6aFYwDHQVdRAX11NfSVldCXl0NXWuoXZ4qK/GJNXh60OTl+EScjwy/qpKVNysghCEINCTeEhMGsRckKuSvN9VPzO7Em5seSzXlIz/OXX4gicGoW1426JbhfuNFoNKqA4hFFm+J4JC8vT7rd3d09w5pTc72kAy0aWWFZenoNjGOmGbaYHkeqFwLnP4DhBAaTNfo5N6qMmzC4pa5oBnFaI7+u+YIZt7lKwYJwJmm1WpXr5uLFiyHPL5FhcxBuFi9ejPTxIHFRFHHq1KloTI0gkhJmkLM/yHFDTCneKIlT0QYAHnvsMTz22GN44okn8OSTT+Kpp55CS0sLHnzwwSnXX7NmDR577DE8+uijuOOOO2AwGDA0NIRHHnkk5DzDgNs5MzNzljWDgOMAQQDGHcSiIMyps1RgIeaHCMAnsrha6F8xspBwQ6io3igHnjWe74PPQ+VSkYLjOWy8u0waXz/dg4HO6X+QOZVwIws0aYr7reNOnHglP18OFZ6v4wYAzFlDeN3khnNcidB4tFh5tAYI4m0qcoBN4bqxxKBcKlylUkpOa3twWTMgjcuENOx0FwdVVqasvW9oaIhrR1ekUWXcTNPum+M4bN68WRqfOXNmwZeYEUSwkOOGmIROB/z2t1P/7be/jUvRBgCefvppPP300/jlL3+J73//+/jUpz6FjIyMadd/4IEH8PTTT+OZZ57BG2+8gRs3bqC6uhq1tbX427/925Dmcu7cOQDq7pHhgvG8P6A4cMAxh65SyoUgiJkh4YZQUbYqG5rx7lIuuxetVwZjPKPkpqomT9Vh6tSrzdOuq3LcWGXhJlVRQpVojpv5XmExZw5hjAPeMsqCS0ZfNsovLw5qPspyKctQDIQbheNG7w1Ty20GHNG2o4mX3wvLfFnY6Jl/J66SkhJJGBRFEbW1teGZYwIyUztwJevWrYNu/OTB6XRSa3CCCBKOMm6IibjdwMc+NvXfPvax6VuFJzhFRUV4+umnAQA/+9nP0NjYGNR+rl+/jnPnzoHjOOzcuTOMM/SjycqCrrgYbPw3kMQYgggvJNwQKnQGDcrWZEtjKpeKLBzHsOmecmnccLYX/e1Tuxr4JHPc2O32eVt+dUYntAYHrup8uKyVHSqVF5YjZSB93vMZS1cEFI9og3LuhIJLkXFjDJPjBgBEBhzQtaCLk1/fDd48rPBkzbDVZDiOU7luFnK51FwybgDAYDCoWoOfOHECArU4JYh5w/TUDpxQMFX3KCXTtQpPEm666Sbcf//98Hq9+Pa3vz3v7X0+H77whS9AFEV84AMfQHFxcdjnyJlM/qwaTfRLzxcqgsjiaiEiCwk3xCSqa2RXRNOFPnhc1J4vklSuy0FWkdwd6uQrTVOux6cpwolHZIEmkRw3ZrNZ1QkrmHIpU8YwAOCA0YMxrd+lwokcVh2tAeedX7CdLc0DYbzsivcxmEaje7ChLpUKk+NmHB8T8Ya+GYNMPuHZ7ilChTdthq0moxRuurq60NvbG7Y5JhJzybgJoAwp7u/vR0NDQ8TmRRDJiq5kEdIefBDpH/0I0u66K9bTIWLJdC2/x8ZmbhWeZHzjG98AYwzPPPMMOjo65rzdxYsXsXfvXuzfvx8FBQX4/ve/H7lJEgQRMUi4ISZRsiITOoP/BNjrFtB8ae5tm4n5wziGTffKrpumC/3obZnsnEkGxw0QekCxOdPfwtLFAW9lWiGO11JbrKlYfG7lvPYl8oA9VXa6RDvnRlUqFUbHTQA38+E1fRNGmf8gloHhVncJCn3mWbaUycnJQUFBgTReqK4bzqQIwfZ6Ic5wYpCVlYXFi+XyvePHj0dyagSRlBiWL0fhv/4LCr7+dWR9+tOxng4RK6YTbf7wB8Bsnr5VeBKKN2vXrsUDDzwAt9uN733ve5P+3t/fj8cffxyPP/44PvGJT+C+++5DZWUl1qxZg3feeQcbN27E4cOHUVhYGIPZEwQRKiTcEJPQaHlUrJPbNlO5VOQpX5ONnBK5tfeJlye7bjiFs8ZnndpxkwjCTcgBxRlD0u0GtwHNS29I45L6SmR15k612bSMZShzbqLtuFG0Aw9DV6mpsHEevKZvhBP+/fPgcLurHFmCYZYtZZSum0uXLi3I0h9lqRQwu+tmy5Yt0u2Ghgb09fVFZF4EQRBJy0yiTSCIeLpW4Ukq3gRcNz//+c+lDlEBbDYbnnnmGTzzzDP4/e9/j2PHjiE9PR2f/exnsX//fpw4cQJVVVUxmjkRfhgEkYurBaByqUhCwg0xJcpyqZa6Abjs4S3jINQwpnbdtNYNoKtBXfbEp6VLt6dz3NjtdnjCXHITbkJ13BhTR8Hx460mRQ4XSjowmj4s/X3l+zXQOufeWUIp3JiHtUF1XwoWVTvwCDhuAgxzLryhb4J3PMRHDx53OSuQIszNYbRq1SopZHBkZAQtLS0Rm2u8Ml/hpry8HLm5soh44sSJiMyLIAgiaXnssZlFmwDTiTePPRadeU7DfNtcf+Mb34AoivjGN74x7TqrV6+GIAiw2WzIzvZnUpaVlU1qre12u9HX14czZ87gZz/7Gfbs2UNhwQSR4FB6FDElRUszYLBo4RzzQPCKaDzfj2U3Fcy+IRE0pSuzkFeeip4mv2vmxMuNeOBv5JBTZcaNUrixWCxgjEkHB1arFVlZ8wuhjSZKx01/fz+8Xi80cwyy03ACwAHmjGGM9vsPWOyjabi84yRqXrsVvMBD7zRgxcm1qN11fE7CvyvDDREiGBg0Xg4WO4MzxZ/rJEZY2nbqFcKN14NIXqzo0djxFlpwu6sMHBjM0OJuVwVu/tgP4BJnF43WF3HIMftfl2/98FnU9czdsTORY89+JehtYwXTagGtFhgXRgX7zMINYwxbtmzByy+/DAA4f/48brnlFpiUJVcEQRDE9Hzyk8CLLwJO5/SiTYCAeBNw6BgM/u0JgiCSBHLcEFPC8xyq1stXi6+fpnKpSMMYw+b7KqRxR/0QOurlsiBlxo1gtUIcL1fheV4V+BvvAcVZWVngeX+GkiiKQZWQWDLl12VsMAO2DCsa18utqnNbi5HfUDqnfQkaEQ5Fzo15aO5unVBxahSlUh4vMM/26POlRWPFYV27NE4XDdhtqgA/h5+CLqs81zyLBxyLojUpTlB3lrLPuv6qVaskocbr9eLs2bMRmxtBEETSsWcP8PLLwEc+MrNoEyAg3nzkI/7t9uyJzjwJIgaIAHxgcbUsvCPD6ELCDTEt1Rtl4ab96hDs1uSrFY43ipdmoLA6XRqfeKVRctLwiiwbiCKEUblteCIFFPM8ryohCS6geFC6PTaYAVEE2pZdx2C+LDAuPrUWhtG5uRtsynKpoegFFCu7SvGiCG0UsmOuagdxUtsljbN5M3Yay2Y1+vSOaeAdn56WB3LMkSvtileUwo04S6kUAGi1WtTU1EjjkydPwuejLn0EQRBzZs8e4LnnZhdtAuh0/vVJtIk58y0VIwhiZki4IaaloDId5nQ9AEAURDSeW5htgKPJRNdN140RtF32ixRcSgqgqE+eLqA43h03gDrnJpiAYkvGMAJhND6PDs4xC8CAK9tOw6PzC4wajxbL39sEzEELsWXIoqRpSBe1nBulcAMA+ijlE53V9qJWI4caFmnTsMVQMuM2PpGhR9EuvTA1vrOUIgE3j5bgAWpqasBx/p9aq9WKK1euRGRuBLHQ8Q4Owjs4OPuKBEFEDNHrhfPKVTguX4azrg5YgM0MCCJSkHBDTAvjGKpqZGfENeouFRUKq9OxaFmGND7xst91w3jeL96M4xteuC3Bea0XxhTZcWQb9L9eLrMD9ZvlcpT0vmyU1i2ddX92heNG6+ags/PznlMwKEulgMgGFKtgwFFdBxr4YemuSl0W1upnbhHaOSrPN9vsg5ZfWAdkzKQQbmbJuAmQmpqKFStWSGNqDU4Qs9P7n99H349/DN/w8Jy3GXjqF2j/4l/DSeIoQcQOjoPo80qCjUjCTUQRRBZXCxFZSLghZkTZXarrxgjGhpwxnM3CYZPCddPbMormSwMA1Dk3Pqss3CSa42ZiS/BgrLTmCTk3AXrL29FdLnc9Kj+/HCkD6TPuy6cV4bAoc26iUy7l4zl4OPlrOGrCDQCRAe/oW9HjlQWwlfo8LNHlTLvNoJ2H0+v/YeYYkG9ZWOVSnFEuvZtLxk0AZWvw9vZ2tLe3z7A2QRCDzzyD/h/9GG2f+wu429rmtI1h2TI4zp6F9bXX6GSRIGLFxM5V9FkkiLBBwg0xI7mlKUjNka8yXz9N5VLRIL88DWWr5M5QJ15uhCiI6oDiaVqCJ5rjxuFwYFSR1zNXJgYUK7m2+TycJv+JNSdyWP7eJnDemV00dkW5VFQDirWKgGJvdIUQHxPxrr0JQz7ZPbLRUIxSTfo0WzB0WRduudR8M24CFBUVYdGiRdKYWoMTxMxwRiPA83BcvIjWJz4Jx6VLs26Tdu890JWVYezQ4Xl9PgmCCB+MMTDFBSkSbggifJBwQ8wIYwzVinKpG9RdKmpsuld23Qy0j6HhXJ8qoDiRM25MJpNqzsGUS1kUAcUumwUelyy2eHUeXN5+CuJ4WI15JBVVp1fPuL+xiQHFMci5MUQp40aJBz68Y7+BMcEl3XeTsRT5vGXK9ZXdpdKNAoyahXNQpsq4mWOpVACl66auri4hBFaCiBmMwbx1K9Luuw/ewUG0PvFJjB06NO3qAdemcd06uBobIdjn7ogjQoMpHBYCnaQTAKAQbiIVTqwM+mcTXT4LBFEEBJGLq4WyqCMLCTfErFRvlN0RvS2jGO6hA6JokFOSgop1ctnKyVcawdLSpfF0GTculwsul3wSHq+EGlCsMzmg1cule7YJrpvh/D60rrgmjYuvVSKnpWja/SlzbnROHlpHdL4enRqlcBOb0iOH6MU79gY4Bf/j84zDLlMFsrjJXblG3TzGXPJrk5uycMqlONP8w4kDLF26VBIrBUHAqVOnwjo3gkgmmEEPwWFHwb/+C7I/9zmAMbT9xV9i+E9/ksqgVCeE47c12dmAIMz780kED2MMuvGOTzabLcazIeKCKDhuAhc/9Hr9ghVuiIUHCTfErGQVWpBZaJbG107O3x1BBMeme8oR6NM81G1Hm7Za+pvScWM2m8HzcinQ0JBcRhSvKHNuurq6ZlhzahibmHOTOWmdxrW1sGbJzpxl79fAaDVPWg8AvHoBLpMsQliiVC6lctxEuVRKiVVw4V1HA7yi/yBLy3jcYq5EOmectG7PmDznfMvCKZdiqq5S8xOweZ7Hpk2bAPgdZ2bz1O9DgiAATqcHvD74BgeR/bnPIvcrX4YmPx9d//h/0f+Tn8I7NCSdrImKK+/u5mb/DbrsG1VSxhsn9PT0YGRkBF6vF4Ig0LJAFxEMgij6lzC+F3w+H+x2O3p6etDb649uyMjImOmtSRBJhWb2VQgCWLI5H8deaAAA1J/oxsZ7yknhjgJZRRYs2ZSP+hN+seyKrRybOR14wa0KJ+Y4DhkZGejv97d4HhwcVAkj8UhBQYF0OxjhBgBSsgYx3OXfz2j/ZOFG5EXU7TiBja/dBo1HC41Hi5WHtuDMXQchTNERaSzTDb3d/7VoGYiWcKPIuPF4AH1UHnZK+n12HHY0YZexHDzjoGca3GaqxH77dVgVpVTdoxpUZvkzgdKNAgwaAU5v8l8H4AzBZdwE2LBhA3Q6HdauXStdoSYIYjLMYIDolnPHMj7yEWhyc9H3gx+i/8c/huvGDWR+4uMwrloFNv5ZGn3nHdhPnYJ+2VIwgyFWU1+QZGVlwWazwel0orOzM9bTIWKM4HJJThvW3g7GR6ZTZ3p6uspxvhARQOdiC4nkP9ImwsLiTXmS88Pa70R3Q/znqCQLm++vAK/1f1SdPi1aF90KABBG1BkZWVlymPHAwED0JhgkSuFmaGgIjiBOhFOy5edpH0mDzzNZi3ak2nDlptPyNkMZqDq1Zsr9jWUpcm4GdVG5autSlErpY1QqpaTTa8V7jmYI48/dwGlxm6kKFiYLDWNuDmNu+ecjb4GUS6lLpebfYc9oNGLTpk0k2hDELHB6PUSPB+K4C1F0u5Fyyy3I/8bXYd66BaP79qH983+Fnu99D4O/+jV6v/99dP/TN+EbHkbGww9DqyjFJSIPz/MoKSlBVlYWfb8R8HZ2wd3QAHdDg8odHg54nkdqaiqKioqQn58PjqNTWWLhQI4bYk5YMgwoXpKB9qv+0pSrJ7pRUJUe20ktEFIyDVhzyyKc3edvcd1asgeFXUdhsk4v3AwODiLeSU9Ph9FolASbrq4uVFRUzLKVGkPKKHitGz6PDgDD2GAG0vL6Jq3XV9qBtqXXseiqv9Ss+FolRnL70VOhbjNry3RDhAgGBq2bQ7pPwLAmMleKAsRLqZSSNu8I3ne0YJuxFIwxmDgdbjNXYb/tOuyiBwBDz6gGlnHXTb7Fg5YoduKKFepSKcrQIIhIwfR6CIODEMcD25lOB9HrhWndOhT88z+j/3/+B6MHDmDo179RbMSQ8bGPIfWuu2I064UNz/PIzc1Fbm4uRFGMWCgtEf+0/+jHGDt8GACQ+9WvIvNjj4Rlv4wxcvsTCxoSbog5s2RLviTc3Djdix0PV0OjjexJLeFn/R2luHy0E84xD3y8Hk1ldyHVekG1TmamXCqUCI4bxhgKCgrQ2NgIIDjhhrHxcqluf1nYaH/WlMINANzYcAlpfVlIHfC/TkuOb8Bo1jDsaXIrcp9WhCPVC9N456RCty/ywo0mtl2lpqPZOwSNk8MWYwkAwMLpcZupCvvt1+EUvQuyXIozymHN8824CQf9/f24cOECampqFrw9nEhuuNQUcEODkutRFEUwjQaiIEBbWIiCr38dKbfeBtv770Ow28CZzTAsXoyUPXvAmSaHqhPRhU6wFza8XgcWOJ6x28kVEzEYfGK8fc7ibT7JBQk3xJypWJuDQ7p6eN0C3A4vmi8OoGpD7uwbEiGjN2qw8e4yHPn9dQBAZ8E2lLXUqdZJtFIpACrhJti6eEvWgCzcDEzOuQkg8gJqdx3Hxldvg9atg8arwcpDW3D6rncgaORwy7EstyTcFHi8uIzIOklcCseNPk4cNwFueAbAMw4bDcUAgFTegNtMVXjLfh1jbhFjLg4Wvb+OPT/Fi+Ykd90o24GL82wHHgotLS2oq6tDQ0MDBgYG4HA4cM8990Tt8Qki2hR++9uAKIKzWADI7X7Z+AmgKIqwbN8Gy/ZtMZsjQRBTwwzBB/kTBDE9JIESc0Zn0KjaUwcCc4nosGJHEVLTxt0fjMO19J2qvysdN4GQwHinsLBQuh10QHG2XBZmH0mDzzu9Q8ZpsePKNrkNs2U4DYtPrFWtM5YpB2Lmu31gEbZ7q8OJ40u4AYB6dx/OOWVRLZ034hZTFbTQoFvZXSolftxCkYIzyoGnkS6VcrvduHTpEv7whz/g2WefxcmTJ2Gz2ZCamoqzZ8/CrQhuJYhkg7dYwKekTOvaIDcHQcQvqoscQeTBEQQxNSTcEPNi6WY5ULa1dgCOUTp5iBa8hsOm2+TAxf705Wi/3C+NU1JSoFWIAImQc6MMKB4cHAxKbDKmWsFrx0UDkcPY4MytIfsXdaFleb00LmwoR8GNUmlsT/dA4PxijRZAjtc3cRdhRV0qFX/CDQDUuXtwySULtVm8CbeYKtA3Kjts0gwCjNrJnbqSCVXGjTNywo3dbsf+/fvxyiuv4PLly7BYLNizZw+efPJJ7N69G4Ig4MSJExF7fIIgCIIIlmhe5FjIiAAEkYurhZKtIgsJN8S8KFqaAXOa/2RNEETcONMb4xktLCo3FyJtpEEaH/3zdYiC/2uS47iEy7nJyMiAQdG2NRjXDWOAJVMWqcb6s2ZY20/j+loM58ii1+IT62AeSgUAiLxfvAlQ6I6wcBOH4cRTccHVhSsu+fOeo7Fgs6YaY06F68aS3K4bZcZNuEqlPFPkGplMJixfvhwpKSnIzs7Gww8/jG3btsFoNKK0tBSFhYUk3BAEQRBxSbQuchDEQoOEG2JecBxDVY3s+rh+uieGs1l48BYLqppeksb9HQ7Vv4FSuEkEx00goDhA0OVSWbJINTowu3AjciLqdp6AW+8CAPA+f94N7/GXWY1lyU6ygogLN8pSqfgWPs64OnDNLYc/52lSkDW8Ekzwv27J3hZc3Q48tINRl8uFM2fO4MqVK/D5Jr/HKioqsG3bNvT39+PatWvS/ZmZmVi6dCnGxsZQV1c3aTuCIAiCiCWcQVkqRcINQYQLEm6IeVO9URZuum6MYHSQ6lejBeM4ZIr9yOk9K913/MVGeD3+E79EDSgOMFtAMQdxyiU1W36u9uE0iF5u2nUDi8dsx9XtsmvBbE3F0uPrwYkibJku6f4crw8aUQCYGJHFqejMZvB4/YH8UVzEeS4nXO244ZFf71SkIm3IL96kGQQYdcKs+0hUuDC2A+/p6cGBAwdQX18PnuenFG/Wr1+PlJQUXLt2DcPDw9L91dXVSE9Px8GDB0OaA0EQBEGEG/VFDjpHiCSCyOJqISJLUgs3//Ef/4GHHnoI1dXVSEtLg16vR2lpKR599FFcunRp3vsbGhrCk08+idLSUmlfX/rSl1QH1AuB3NIUpObIX8o3TlO5VDTh0tJQ2fQymOB3N4wOOnHpYAeAxBRuwhFQbEobAa/xu1XEOeTcBBgs6kHLqivSOK+pFAXXK+BM9cKr8ee1cADyPZFz3bg08dtVajqOOVtx3S2Xmmk9aUgbWgUm8EldLqW0f4tOJ0Qh+Ewfi8UCnucxOupvR8/z6lBtYXzf5eXlGBoaUuU/FRQUoKqqCj6fD1arNeg5EARBEES4YWG8yEEQhExSCzf/8i//gjfeeAOZmZm49dZbcffdd8NgMODXv/41NmzYgFdffXXO++rv78emTZvwwx/+EBqNBg888ABSUlLwgx/8AJs3b06IspRwwRjD4o1ULhUr+NRUmBx9KOo8It13+o1mOMc8CVcqBagdNwMDA0EFFE/MuZlLuVSA5jV1GM6Txcfqk2thGUyHPTM65VKqjJs4L5VSctzVhmsq8SYVaYOrUWiaYaMER+m4AfziTbBkZmYiNzcXVqtVEiwDYo0oiuA4Dl6vF06nE2NjY9CMC3yBdXbs2IFHHnkEJlMSv+AEAUAUBAgOB3xjY7GeCkEQc4CjduAEERGSWrh56aWXMDQ0hBMnTuD555/H888/j/r6evz4xz+Gx+PBpz/9aXjneIX7S1/6Em7cuIGHHnoI9fX1+P3vf4/a2lp88YtfxLVr1/DlL385ws8mvqhW5Nz0tY5iuIe+mKMFn+oP0S1reQNa3n8S53Z4cfr1ZpXjxuFwwG6P/3+XzMxM6PV6adzdHVyb+ZRsZc5N5gxrqhE5EZd3nIDb4D8J5wQeKw5vhT1NdlNEMqA43tuBz8QJVxuuKjJvtN4UFNtXIF2bnHbZicJNqFcSV69ejeHhYVy54nd9McYgCILU6tjlcqGnpwcmk0kSbDjO/7OdlpaGnJwcSdAhiGRk9MABXF2+AvXr1qPl0UdjPR2CIOaAslSK2oFHFgEsrhYisiS1cLNt2zZVx5oAn//851FZWYmenh5cvnx51v10dXXhueeeg06nw09+8hPVgfJ3v/td5OTk4De/+Q16exdOyVBmoRlZRRZpfO0UuW6iBZfmF250HhuW5couk0uH2uG1cyoRJBHKpSYGFM+WczMdKVnya2EbTofPO/evN7fJics7TkAcb2RoHLWgsHEVAn0NM3wCjL7ItLp2aROvVErJKVc7rrjl7z6tNwW3GKqhZ8knKLAJvyehCjdr165FRkYGjh07hsbGRjDGwHEcfD4fWlpa8Pzzz2NkZAQrV65Ebm6ualtRFFX/J4hkhOl00m06ASSIxED5W0mlUgQRPpJauJkJ7fhVbp3ioGA63nzzTQiCgB07diAvL0/1N71ej3vvvRc+nw+vv/56ROYar1RvlE8krp/qoROIKMGnpkm3K/WtsGT4hRrBJ+LES40JXy4VbM6NOW0EHO8XPkSBh21objk3AYYLetG8Ru7Sk9VRBM5RJM8xQjk3To2yVCrxhBsAOO3qQAeTBTczzNhrrIIhycQbxnHqA9IwONp2794Nnufx3HPP4Q9/+AMOHTqEF154AS+88AIaGhqQmZmJ1atXT57LuCuHMUbfvUTSwvSKz5uLhBuCSAQ4o1zCS12lCCJ8LEjh5te//jXq6+tRXV2N6urqWde/cOECAH+Hj6kI3H/x4sXwTTIBUJZLDffY0d9G9efRIFAqBQAYG8aW+yuk4Y0zvUjVyIJaIjhugPAEFDNODDrnJkDLqisYLJDdYxnWcmjcKQAil3OjzLjR+3xgYmScPZHmuKMLdnOrNE7njdhjrIIxycQbbkJAcaisWLEC9957L3Q6Ha5cuYKDBw+itrYWoihi06ZNePzxx1FcXAwA8Pl88Hq9sNvtqK+vR3NzM3p7e+FJoGwkgpgPnEF2kJLjhiASA85IjptoICL+ukrRZaTIklxH1NPw3e9+F3V1dbDZbLhy5Qrq6upQWFiI5557blInj6lobfWfjAQOnicSuL+lpSV8k04AUrONyK9IRXejv6vJ9VM9yClJifGskh8+TRZuhBErFm/Kx/m32yThzNGUBvAAWOIIN0rHTX9/P1wul6rka66kZg/A2ucXroIRbsABV7afQM2re6B3GMGBQ+rwMgxln/ULN6LoT0IOI8qMGwDQ+7xwamZ3AsYbdg+HLk0r8s0izLZSAOPijakab9lvwCEmh7jAGY3wDQ0BAAR76AekPM9jxYoVyM/PR1dXF7q6ulBYWIjU1FRkZ2fDaDTCZrNhYGAAHR0daGpqwo0bNyAIAniehyAIWLJkCTZv3ozy8vKQ50MQ8QRThpy6XDGcCUEQc0V1gcPthujzgc3hfIsgiJlZEMLNvn378Pbbb0vj0tJS/OpXv8KGDRvmtP3YeCeD6bp3mM1mAJDaus7GihUrpry/oaEBlZWVc9pHvFC9MU8Wbk73YOuDlWAchVNFEk7huPFZrWAcw00fqMLL3z8PAHD0A7r0bLgN/Qkj3GRmZkKn08Ht9ndy6u7uRmlp6bz3k5IlP9+xoXQIPg4cPz8Hi8fowuWdx7F2/y4wkQMvGJAysgRieh1SfSKsmnALN+qvYb03MYUbAOi2aZCa3QIwEeaxMgBAGmfA7aZqHLDfwJjonnkHCQAzRaZbRlZWFrKysrBy5UrV/Z2dnbh06RKuXbum+jyXlpbCYrGgt7cXV69eRWdnJz784Q+jqKho4q4JImFRO24cEEVRKhMkCCI+YZOC/J3gLeYYzYYgkocFUSp14MABiKKIoaEhHD58GNXV1di1axe+9a1vxXpqCU/VhjzJgDA25ELH9eGYzmchoMy48Vn9otmipZkoXSk7TCzWCkDg0N/fD58vch2RwgXHcapyqY6OjqD2Y0pX59yMDc4v5ybASF4/mtbWSmO9KwvmsXIUucOfQePmeSilJYMvMXNuAKBrTIuuUQ2OWPtw3iVn3qRwetxuWox0bnJYfKIR6dp9Zejw8ePH8fvf/x7Hjh3D8PAwSktLcfvtt+NLX/oSnnjiCdx///34q7/6K9x///1wOBw4dOhQ2OdDELFEFQguihCpLJAg4p6JHRhFagkeIRgEkYurBdRZKqIsCMdNgPT0dOzYsQOvv/46tm7din/8x3/E3r17sXHjxhm3s1j83ZOma61ss9kAACkpcysTqqurm/L+6Zw48YwpVYdFy7PQWue/Enz1WBeKlwR3skzMDVWp1LhwAwDbPliFtiuDEHwieMEAs60ENq4ZAwMDkzrSxCNFRUVobm4GALS3twe1D44TkZI1iJFe//O19mcjNSc411Hrynr4GkpQbU0HAJhsi7Bq0IErpjBnOTEGl1YD43gwsS6BhRuHh8OFbv8BWx964BVF1Bj8DhATp8VeUzUO2htjOcWQ4VTdMsKfucEYg81mwxtvvIHaWr94WFlZiQ0bNmDx4sVSV0NBEKRw/dWrV+PGjRu4du0arFYrUpU5WASRwHATSmZFpxOYQ1MJgiBiB5vwuaUyR4IIDwvCcTMRrVaLD3/4wxBFEa+88sqs65eUlACY/mQycH8wpR3JwNKt+dLthnN9cDsT98QzEeBSFKVSivK8jHwz1u0pkcZGWzF4rynosN9ooyzxCNZxAwAp2f3SbWt/dvATYsBri5oxqJcF25LBKhTbpi6ZDAVVZylf8lxRvuLpxfuOFgjjLhI90+A2UxVa6hKjhG8q1KVS4XXcCILfe3Xu3DnU1tYiJycHH/rQh/CJT3wCy5cvh0ajgSAIEAQBHOf/+fb5fOB5HikpKRAEAVaFmEsQic6kkoswBIITBBFZItGBkSCIBSrcAEB2tv+Erq+vb9Z116xZAwA4e/bslH8P3D9Vy9aFQPmabOhN/hNPr8uHhrOzv6ZE8KgcN6OjEAW50GbDXWVIyfT/WDJwsFir0NmZGMKNMvx7ZGRkzplRE0nLkYUb21A6vJ7gjYUeXsCfyhrg4/zZLAwcHmiuQIpbO8uW80MZUKxPYMfNVDR4B3HY2QTfeLcsDePw+o8v4tqp7hjPLDg4g7KrVHiFG47jMDg4iKNHj4Lneezdu1dyYgZEHY7jJNEG8Icb22w2dHR0QKvVIj09PaxzIohYwnQ6VSB8ODq5EQQReZTuVPrcRggx/rpKUVupyLJghZtAFsBcwoDvuOMOcByHI0eOoLe3V/U3l8uFV155BTzP46677orIXOMdjZZHlaI1eP3xxBAKEhVeWZInihDG5NIdrY7Hjg/LLe517nS0145Ec3pBk5qaqirxCLZcyphqhUYXsOUyjPYH0V1KwYjeg2s59RDHk2iMPh0eaKmERghfHa9LI3dbSDbhBgDavCN429EAj+jPWxIEEW/98jIuvSv/G3u9XinfJZ5R1u6Ho6vURPr7++FwOLB9+3ZUV8ufZaVYIwiC9FrZ7XYcPnwYbW1tWLVqlRSWTxDJAGNMVXZBjhuCSAzU7lT63BJEOEha4ebo0aN48803pauUATweD/7rv/4Lv/71r2E0GvHhD39Y+tuPfvQjLF26FH/3d3+n2qagoAAf/ehH4Xa78fnPfx5er3xi9dWvfhV9fX34+Mc/nhA5IpFCWS7VcW0Y1v7wn9AQfrgJWUo+q9qZUr4mB7mVcjmPsykNDltidPMJR7kUY0BKtlyKE1K51DhXU+0YS70hjfMdJtzZVha2Kwsqx403eUqllPT4xrDffh1OYfz5icDh313Dqdea0NLSgldeeQXHjh2DM85PzJhRYf+OwFwDWWr68ZNV5e9NIGic4zgwxtDX14dXX30Vp06dwqJFi7Bt2zbquEMkHcqcG5GyMggiIYikO5UgFipJG058/fp1PPHEE8jOzsaGDRuQlZWF/v5+XLp0CV1dXTAYDHj66aexaNEiaZv+/n7U19dPmQny/e9/H8ePH8ef//xnLF26FDU1Nairq0NtbS2qq6vxH//xH9F8enFHXlkq0vNMGO7xn3RcPd6NTfeUx3hWyQnjeXAWi+S0EUatANQtgG9+ZCl+/81TYODBCTq896er2PNY/JfyFRcX48qVKwCCd9wAQGp2P4Y6/V2qwiHcdOh4OE3d4L1mmOz+13rpSAb6ex04lhd6yY+yJXgyOm4CDAoO7HNcx8eK12FsyAURIk6+0oSKfgsGPAO4cOECGGPYunVrrKc6LcquUuFsBx6gvLwcjDF0dnbC6/VKYcSAvywKAFpbW3H69GlcvHgRAFBYWIhbbrmFyqSIpIQZDMCI3zlKJRcEkRhEOsif8F87FOKsi1P8+6YTm6R13OzatQt///d/jyVLluDixYv44x//iKNHjyIzMxNf/OIXcenSJTz88MNz3l92djZOnjyJL37xi3C73XjhhRcwMjKCv/7rv8bJkyeRmZkZwWcT/zDGVK6b+uNdEAX6+EYKLlV23fhGJoeR5hSlQ1RkvVw73o++1uAyY6KJMuems7NzkmNurqQqAoqdoylwO/UzrD07Dp5Dv4aDLaUBbt2QdP/2nkJUj6SHtG8AcGkWhnADAFbBhYf+9wak55nAxg84Go+NoRDrkZmZiaNHj6K/v3+WvcQOZamUGIFSqbS0NCxfvhy1tbU4ePAguru70dHRga6uLpw6dQpPPfUUfvnLX+LixYvgeR7bt2/HI488gvJyEsqJ5ER1Augkxw1BJALKYPFwB/kTxEIlaR035eXl+Na3vjWvbb7xjW/gG9/4xrR/z8zMxA9/+EP88Ic/DHF2ycmSzfk4/lIjIALWfie6GoZRWE2twSMBn5oG73josG906i4yeSs16Dpsh8ZnAkTg0HP1+MD/3gDGxZc6r6SgoACMMYiiCLfbjb6+PuTl5c2+4QT0Zjt0RjvcDr87wtqXjexFwXeqAvyum2yvAGv6FaQMroPe6z8ouau1FM9WudBnDP7AJLkdNyIw4YpQSqYBD/2v9Xj1RxfQ2zIKESKaTg8jtaoUrfYLOHXqFO68887YTHcWuAiXSgHA7t274fF4cPToURw9ehQmkwkul0sqlUpNTcW6deuwfv16pKWlAQBEUaQyKSIpUXanEV105Z4gEgF1ODEJN5FCEOl3fyGRtI4bIvpYMgxYtEx2Hl09lphdYxIBZUCxME3738KiAlUuS0+TFVeOxXdwtE6nUwk1wZZLMQakKhxHo2Eol2rX+8UVkfNiNL0WLs4vsOhEHg82V8DkDV4Hd2mTqx24USMgz+KBSStALdrILjxjig73/806FC1Jl+6zNuqgRyquXL4StbnOF/VVxMi0OM3OzsYHPvABPPjgg1i6dCmKiopQWVmJ9evX42Mf+xj++q//Grt370ZaWpoUVEyiDZGsMIMynJgcNwSRCHAUTkwQYSdpHTdEbFi6JR9tlwcBADfO9GLHhxdDq+dn2YqYL5yi+9LEcOIABQUF8OiH4TT0weDMAQAce74BFWtyYLCEt511OCkuLkZ3t1/0a29vx4YNG6S//fGmn855Py+ZOvBk63kAgM5ajT9s/dy8T27LLnxPut2v5eBkgEEERI0DJwobsL19MTgwpHn0uL+lAr+vuA6Bm3+JoFNRKqWLtuMmAif85ZluLEr1wCMw9Ns16BrVoN+ugQgOSvFGZ9Dgni+swf6n6tB0oR+8oIfXweAUxtDc0I6yyuLpHyRGqAIXI3gwqtfrsWbNGqxZswYA4HQ6YVBewRwXa5TdpggiGeH0dOWeIBINpvitFOhzSxBhgY74iLBSvjYHOoNfqPG4fGg81zvLFkQw8ArhRpimVCo/3585ZEtpgMD8YoDT5sGxFxsiP8EQUObcBNtZCgC2VsptwDtHnGgeCM0dITKGDr0iKFYzgEOF8vyKbRbs6VgUVDKbynHjTfxSqWGn/zuAYyIKLB6sK3Bg6yIbFqW6wU/QiTRaHns/vRxLt+ZDYF6InAfMq8PbT1+Jy+506quI0ZmfIAiSaBPIfSKHDbFQIMcNQSQeqlIpctxEDEFkcbUQkYWEGyKsaHU8qmrkUperx6lcKhLws4QTA4DZbEZqaioE3g27pUW6//J7nehuHIn4HINF2RK8t7c36PbQuSkGLMmTX6ejN0IPvG3Xye6xYrcPp7N6cClDbj2+ejAb6/tz5r1fVTvwJCiV6hrVQgQw6NDgSr8B/XYNTFoBy3Oc2FE6hn379qG5uRlerxeCIECj1eCWR5cha60LXs0YGABnH48/f/cMBjrGYv10VDBVUGp0hBulq4YcNsRCQ+Vyo4wbgkgImDIPjsKJCSIs0BEgEXaWbpG7S7XXD2F0kA60wg2XoiiVmsZxA/jLpQDAYeqEPk2+/9Bz9RDitOtXVlYW9Hr5CmtnZ2fQ+1K6bk41D4Y0LwDo1GskQ41JEJHpE/BWcSs6TLK4sLuzGGWjKVPvYBqSrauUCIY+mwYZBi8GHTzOdplwutOE1hG/QHXs2DE8/fTTeOqpp/D888/jrbfews9+9jNc6zoDjuNhHvV3SLKNuPDCv5+NK6FR2Q48El2lCIJQo3bc0PEEQSQCHJVKEUTYIeGGCDv5lWlIyxn/whaBenLdhB1VqdQ0GTeALNyAidCVycJFf9sYag+F1mUpUnAcF7ZyqY1lclj2yaZBiGJoYpWLY+jTyl+bxS4ffJyIF8saYdW6AQAcGO5tKUeGa+4tyJOxq1TriA4aDsi3+B1Ew04NrvQbcaLdjD179qC8vBzd3d2ora3F0aNH0d3dDb1ej527duCWBzYBTAQDg8vuxUvfP4fWuoFZHjE6qEql6CSSICKOOuOGSqUIIhFQ/lZSqVRkEBH70qiJi4jwlEudOXMG3/72t/HQQw+huLgYjLF5l4jfdttt0nbBNjuJNyicmAg7jDEs3ZqPEy83AQCuHuvChjtLKZMhjHDKUqlpukoBCuEGQL+jFWu2LJfK10681IDK9Tkwp81dYIgWRUVFaGjwZ/GE8mW7sVxuR9814kT7kAOLMk0zbDE77ToNcj1+kabI7cVF6GDXevFCWQM+2rAYOoGHwafBQ42V+G11PZwa36z7TEbhZsChgUdgyDT6oOMFuH0cGEQ4vBy2bduGjRs3oqenB8PDw+jq6kJxcTFKS0thNpsBAJZUM976/+ogeEV43QJe+8lF3PbEclTXzL89fDhRlUqR/ZsgIo7qM0elUgSREKjLiulzS8yPb37zm3jppZeC3v7pp5/G22+/DcZYyBdt4wly3BARYcmWAqkL8EifA90N8VPqkAzwqXLd03ThxIBauLFarVhzRyH0Jr9I4Hb68P7zN6bbNKYoHTft7e1Bf+nmphhQliULNeEol2pXdEnL8QjQj5ec9ZoceGORnCWU6TbgweZK8MLsgmWylUoF6BzVIk3vQ5reL14p/xV1Oh0WLVqEVatWYe/evVi+fLkk2gBA1YZc3Px4BWD0X2EXfCL2/6IOF95pi+ZTmARnUpRKORwQx8OCCYKIDJyiVIocNwSRGKg7MNJFDmJ+bN26Ff/4j/+Il19+GV1dXaoIhdno6+vDV77yFezduxclJSURnGX0IeGGiAgpmQYUL5HdDhRSHF7mEk4MACkpKaqT4RHbALbcXyGNr53oQUf9UGQmGQLKgGKbzYaRkeCFv03lcrlUOISbQQ0HO+cXYzgAhS5ZaLmWPowj+XImT7HNgjvbSmftNKVy3HgTP5w4QNuIFhwDcs2B12h2EcvhcKC1tRXHjx/HuWtHoV3SCb15/PURgff+cB1Hfn8tZhlNyk4ZACC6Ynci6Xa7Y/bYBBEtYhEIThBEaHAUThwVYl0aFamuUl/72tfwT//0T7j33nulLrlz5Utf+hLsdjt+8pOfhG0+8QIJN0TEUIYU3zjdA49r9pIRYm6ow4mnz7hhjKm+8Do7O7F8RxFyS2Xh59Bz9fB54ss1YDabkZEhC38hlUtNyLkJGcbQMd5dapRnk75Ej+d242Km3MFq2XAmdnUVYSaSsVQKAGweHmNuDoII8Gx6ocXj8aC7uxvnzp3Dvn378OKLL2Lfvn1oaGhAZ3cbtn68AJYM+WrLxYPteP0nF+F2RP+14oxG1TgWB6T9/f145ZVX8O///u+wzlAqSRDJgKqtMDluCCIhYAbKgyOiz5tvvolnn30W//AP/4DKyspYTyfskHBDRIyKdbnQGvwnuG6nD9dP98R4RskDnyYLN6LDAXGGK++FhYXS7ZaWFnAcw86PLpHMD0PddpzZ1zLN1rFDWS7V2toa9H6UjpuGPhv6RkM/8L9k1uH5LBP+nGVCg1Gr/iMD3ipuRbNFPqHe1JeHmt7cafenLJUyJJFwAwAnOsy40m+Eb4YrMfX19Xjrrbfw+uuvo7a2FgaDAbt27cLu3buh1WpxrbkWH/zbGuSUyIJjS+0A/vSdMxjps0fjaUiwicJNlDtLCYKAX/3qVzhz5gxcLhfee++9qD4+QUQbpqeMG4JINJSOG9Ee3d9pYmFis9nwl3/5l1i6dCm++tWvxno6EYGEGyJiaPU8lmyS3R61hzqSKiAqlnAWdbtp39jYNGsCFRVyaVRzczO8Xi/yylKxaqfsAjnzRjMGOqffRyxQ1qWGItyUZJpQkCYfQBxvDL07kVXDwarhgGkCtwUGvFTWiF6DfLCyu6sYywczp1zfqZXFH12SCTdeRcaPhhOhrBsLfB9kZ2dDFEV4PB7cfPPN+NCHPoTt27ejpqYGZWVluHz5Msxpejz4lfUoX5MtbT/UZcMfv30a7VEs92McB6ZXZm5EV7jhOH+4c4AzZ86EVEpIEPEOZdwQROKhDhWnz22kEMDiaokl//f//l80Nzfjv//7v6HT6WI6l0hBwg0RUVbuksWBvtZR9DZPX9ZDzB3ObAI4+eMrzFAusWjRImjHhQGv1yuJIFseqJTKTwSfiIO/vhqz3JCpKC0tlW739PTAGaTVljGGrRVZ0jgcws1ccPMC/lRxA8M6+YDljrZSlFtTJ63r0siBxzrBBybGV+laqGg4EUuynFiV64Cel99jgU5z+fn5uPXWWwEAdrsdGRkZ0Gg0MBgMKCsrg8fjQV1dHbR6Hnd+bhVq7iqT9uGyefHKD86j9nD02ttzqs5S0XcArF+/HikpfvHW5/PhyJEjUZ8DQUQLpmoHTo4bgkgElGXF9LldWDQ0NGDFihVTLpHi7Nmz+MEPfoDHHnsMu3btitjjxBoSboiIklVkQUGV3AGp9nDwWSWEDGMMfIoioHh0ereMRqNRiSCNjY0AAJ1Rg12PLJHu72my4tLB+Pn3yc7OhmH8BFkUxZBybrYohJtjURJuAMCm9eKPFTdg0/gDh3kw3NdSjgKbuiW50nEDJFfODQBoORH5Fg/MOgEuHzfJeSeKIoqKipCfn4/r16+jt7dX+ltZWRlSU1Nx+vRpAADjGDbfV4E9n1oOXuv/CRMEEYeercfh312D4Iu86MWUnaViEJaq1WqxY8cOaXz27FkMDw9HfR4EEQ2YwnFDV+4JIjHgqB04ESV8Ph8+/elPIz09Hd/73vdiPZ2IQsINEXGUrpvrp3vhtCVP15xYwqXKzo2ZWoIDUAV0NTQ0SLfLVmWjemOeND7+UgOs/fGR/s9xXNjKpbZWysJNY58NvdboHUQM6134c/kNuDl/OLdW4PBQcxkyHfLJiDLjBkg+4cbh5eD0cmAAdLwAxtiUZZNVVVWwWq0YU5T+5eXlobi4GE1NTXAogoAXb8zHg19ZD1OabIe99G47XvmvCxH/jlE7bmLzeVm/fj1Sx78DBEEg1w2RtKjCiUm4IYiEgE1w3IhCcjmJ4wER8ddVSoT/nKOurm7KJRJ8//vfx7lz5/Cd73wH2dnZs2+QwJBwQ0ScyrW5MKb4HQU+j4Crx7piPKPkQOW4sc5cgqYUbrq6umCz2aTxjoerYbCMl1K5Bbz726txk0WkFG5aWoIPUC7OMKIoXT6IiKbrBgB6TA68UNYIN2+HNf0y3CnX8IHWAqS4/a+7S8NDeUij9yaXcAMAVhcHHS8gVe9/poH3mCiKkpBjtVrhcrkkp5UgCNBoNFizZg3Wrl07qYNSXlkqPvS3G1Vd0tqvDuFP3z6NoW4bIoXSAh6LUinA76TbuXOnND537hyGhqKX9UMQ0YLplI4bunJPEImAUnAFSHQlIscrr7wCxhieeeYZ3Hzzzaqlu7sbAPChD30IN998M958880YzzY0SLghIg6v5bBsm9zZqPZQB8Q4ylJJVDhVqdTMjpucnBwpEwMAmpqapNvGFB12PFwtjduuDKH+eHcYZxo8SuGmo6MD3iAFDcaYqlzqeGMY2oLPk9aUUewv6gTn08GjG4ZGO4gPNlbB4OUBxuBK0pbgATpHtdBwQL5F7YYJ5Nz4fD50dnaC5/lJwmFFRQXuvPNO5OXlYSKWDH9ocXWN3LVrpM+BP/3bGbTURUagYyrhJnbdMtauXYu0NH8pqiAIOHz4cMzmQhCRgsKJCSLxULYDB6hciogsoiji8OHDOHTokGpxjQuGx48fx6FDhyQhJ1Eh4YaICit2FErtp0f6HGi7Gv0T52SDT5WFGGEWxw1jTNVdSlkuBQDVG/NQulIWNt7743XYrdO3GI8WhYWF0IyXEXm9XnR1Be/W2lIhd3Q6EWXHDUQRTBRxJcOKCykMnM8Ah6kb6T4fHmqqhEZgqnKpZBRuRlwajLh4FKV4cOHCBXDj4doOhwNtbW344x//iP7+fixduhRFRUUQBEFaR6vVQq/o5DQRjY7Hnk+twOb75Pe42+HFaz+6gAtvt4XdQaYq3YjhwahGo1GF8J0/fx6Dg/TdSiQXLE4+bwRBzB2l4AoAYozKipMaMf5KpRCD6/LvvvsuRFGccglkfLa1+Y8FH3/88ehPMIyQcENEhdQsI8pWyXWHtYei1wEmWeFS5Iyb2Rw3wOScG+XJLGMMux5ZAq3e393IZffi8O+uhXG2waHRaFBUJGckhZJzo3TcNPbb0BOGnBuNKMI0XRjuuFgDUQQYgzjuLDmWY8UIrwEgwGnoQ5HdgvuaK+DQylktySjcAEDjkA52D8MLL7yAZ599Fi+//DIOHDiAV199FfX19cjPz8fmzZsBQBJt5gpjDDV3leHOz62CZvx9LIp+EfLgb67C5w1ffT1nin2pVIA1a9YgIyMDgP+K06FDh2I6H4IIN5yewokJItFgGg2YovGCQG45gggZEm6IqLFyp3wC3nyxH6ODdOUsFJQZN7M5bgCoHDdWqxUDA2rXSUqmAVsfVIg7Z3vReL4vDDMNjXDl3CzKNKE4Qz7hDkdb8LVjbtwy7ETauCjABcQaQBZrGIPJJ6DK4cEtww58rHcMFjYGEYDT5LdsVo6mob3sg9KFCr0vOQO8e20a1PYakZ6ejmvXruHs2bM4f/487HY7Vq9ejfvvv1/17x0MFety8IH/vR6WTPlk78rRLrz0/XNwjIbHRaa0gMeyVAoAeJ5XZd1cvHgR/f39MZwRQYQXpeMGPh9ET3J+PxJEsqF2y5Hjhpg7r732GrZs2SItbrf/+E1532uvvRbjWUYfzeyrEER4KFmeidRsA6z9TogicPm9TlVpAzE/OEWplG9sduHGYrEgLy8PPT09APyum4np6yt3FuH66R503RgBABx+rh5Fi9OhN2kn7S9aKE/k29raVCU082VLRRb+dMbfVvxYwwDuX1s08wZs9j9neQXkeXwY0XIQxl01EEXkegQscnlR7PIhfYLbo1/LoV2nQeVACQL/AqOZG9BQMYCqxpegE7wQZ3nsRGXIqcHnPvc53LhxA16vFz6fD5mZmSgoKIDRaJx9B3MguzgFH/rbjXjzZ5fQ1eB/L3fdGMEf//U07vr8amQXW0LavzKcWIyx4wYAVq9ejSNHjmBwcFBy3XzgAx+I9bQIIiywCWWSgssFXhu73ySCIOYGZzBAGPUfn1LGTWQQkvRgsa+vDydOnJh0v/K+vr7YX1yONuS4IaIG4xhW7JBPlC+/1wnfdGUmxKzM13EDTN8WPADjGHZ/fCk4jf+HwDbixvvPT14vmixatEgKsHU4HCG5CbaqAopDd9w0Gfzad7bHB60gosruwe4hBx7pteHOQQdW2jxI9wpwMaDRoMG76QY8m2vGa1kmXEjR4aWSHrSZ5X+71pK9aC3enZRdpfz4/x2NRiNWrVqFdevWoaamBhUVFWETbQKYUnW4/0vrsPSmAum+0UEn/vzdMyE7yThj7NuBK+F5XpV1U1tbuyAPaIjkZFJ3GjoBJIiEQB3kH/vfSiJxePzxx6fNrQksc8mraW5uhiiKKC4ujvykowAJN0RUWbatALzG/7azW91oOk+W/mBRZ9zMTbhRlks1NzfD5/NNWicj34yNd5dL48vvdaKjPnZthg0Gg6qbUEg5N5WycNM8YEfXSGgHEv06Hh4GVDm8eKTXhm1WF0pcPmhFYEDD4ZxFh5ezjPhdngVH0g1oMWjg4ZiUf+NjAl4ob0SvQS63uVH1QWRpkuMHZjaULcEjAa/lcMsnlmLbB6sQMEN5XT688bNLOPNmc9CPqyqVihP796pVq5CV5X9/U9YNkUxMctxQVgZBJATxEuRPEMkCCTdEVDFadKjaILftrT3UHsPZJDbqrlKzhxMDQGlpKXjeH9zqdrvR3j71679ubwmyFOUkB39zFR73ZJEnWijLpUIRborSjSjJNEnjcLhuOnU8GAA3AxoMGhxO0+O5XDNezTbhokWHIa3/9WbT5N+4ND78qfIG4B2W9plj2YJF3pTJD5ZkBJxUgf9H6jHW3laCuz6/GjqD/98CInD8xUa89cvL8Abxvo63UinAH+Z88803S+Pa2lqpLJIgEhnGcWA6ObxddMXHZ44giJlhKncqfW7DjYjYd5GauIizZQwQIUHCDRF1Vu6Sy6U6rg1jsMsWw9kkLpyiVGqujhutVqsSQaYqlwIAnvc7FZiihfupV5qCn2yIhCugGFC3BT/WELpw0zpeLnXFpMV76QY0GbVwK1w1CLhKFJ2lJmLTeuEbfhFat//fkTEOtztKkeszTbk+MX/KVmXjA1+tQWqOLLpcP9WDF/7jHGwj87uCH2+lUgFWrFiBnJwcaUyuGyJZUIacUlYGQSQGnMKdSoIrQYQOCTdE1MkrT0X2ItnNUXuYWoMHA58ql0rN1XEDqHNuGhsbp10vtzQVa2+TBZPzB1rR2zL3xwknSuFmZGQEIyMjQe9ra6Uy52YwpHkBQIfeL9zku32yUKNsAT5RrJmmPMfFjWLNxR+D9/oPbrTgcZejHOk+/ZTrE/Mns9CMD32tBkVL0qX7eput+OO/np7Xe1tZtx9PnTImum4uX76M7u7u2E2IIMKEsiW4SC3BCSIhUJZKkeOGIEKHhBsi6jDGVK3B6491we1M1jDWyMFZFKVSdjvEOQbaKoWbjo4OOGZwDGy8t1xyKIgi8M6vr8YkUDo1NRUZGRnSOJRyqc3lsnDTOmhHx3BoJ94ujmGMZ8j2CEjx+QWbSWIN/KVS/LigAwBGnyCXTgFwarVIHWvDqrqfQxT95TtGUYN7HBUwC9RBJVwYLFrc+9drVd9BtmEXXvjeWVw/PbfSImWplGCPH+EGAJYtW4bcXLkc9d13343dZAgiTDDKyiCIhCNeL3IkE6LI4mohIgsJN0RMWLwpX8qbcDt9uH6KshjmizLjBgCEsbE5bZeXlweTyV+CI4oimpqmL4HS6njs/vhSaTzQPobzbwUvmoRCuHJuCtONKM1S5NyEoVzqVIoe51J08Iz/ZkmCjCjC5BOQ7/Jiid2DjVYXbh904CM9Y7h90IEdIy4st7mhEUS4NH7nTuZQPbiefRDh30eKqMM9jnLoRD7keRJ+eJ7DrkeWYOdHFoNx/n80r0fA/qfqcOLlRojCzKHF8Vy2MdF1c/XqVXR1dcVuQgQRBjiD7LihcGKCSAyUTjly3BBE6JBwQ8QErZ7Hkq1ym95L73ZErLNMssJZLCpnh2+O5VIcx6m6S02XcxOgeEkGlm8vlMYnX23CQMfcRKJwEs6cG2Vb8GNhCChu0/O4bNLCwfu/UkXGwIkiqhxebLW6sGvEhc2jbixxeJHv9kEvAjoRKHd6sXHUja1WF1yKK1OGkct4T98pjTMFI+6xl0MrJvdXttVqxbvvvov3338/Ko+36uZi3PvXa6A3aaT7Tr/ejNf/+xJcjukdbJxRFv4Eh33a9WLF0qVLkZ+fL43feeedGM6GIEKH6RWOGzcJNwSRCKjCiclxQxAhk9xnAURcoyxVGOgYQ/uV2LWcTkQYx4Ezm6XxXAOKAaCqqkq6XV9fD0GYufzppocqYU7zd/UQvCL2/6IuqG48oVBaWird7u3thc0WfKi1Mufm6I3+kEVDVfCwKKLK7sFDfXZss7pQ7PK/Tp06HhfNWrydbsAfc0x4I9OIg+kGNBg0qHB6waemS/vT+7yo1fXjjE52ouUJZtztKIcmScWbq1ev4j//8z/x7rvv4vDhw3C73VF53EVLM/HBv61BRr4sxjRf7Mcf//UUBjqnFiiV4cTx0lVKyUTXzfXr12fMsyKIeIepHDfx95kjCGIyqnDiOPytTAYEsLhaiMiSnGcAREKQWWBGyQr5BPrcW6G5KBYinLIl+OjcXTCLFy+WWjCPjY1N2xY8gN6kxS2PLpPGg502vP/CzE6dcJOVlYUURSet5ubmoPe1rSpbut014kRDXxgcROPiT7nTi/VjbpgFEUMaDqdSdHgz04i3Mo04l6JHu0EDO89hVMOh1aDB8VQ9unU8dAZZhNP5/G6Pk7pu1Gr7pfsLfBbc5SiDJgnriEtLS6EZLxdzOp24cOFC1B47PdeED3ytBmWr5O+jkV4H/vRvZ6bMvYnnUqkAS5YswaJFi6Tx/v37ZxVoCSJe4XSKcGIqlSKIhEAluFJXKYIIGRJuiJiybq9c/tJ2ZQh9bXN3jRAAb1G2BJ97VxyTyaQqPers7JxhbT8lK7Kw5hb5RPDSwXY0X+qfYYvwwhhDeXm5NJ4pm2c2si16LC+Qu3IdvhaG58EYUr0CNo26YRREnEjR4eVsEy6bdRjRjH/VKrtOwZ+F4+UY+rUcGGMYyPS3KtePCzdgwBF9By5r5XKuIl8KbneUg08y8cZoNGL9+vXS+Pjx41EVGvRGDe76y9XYdG85AheNvC4f9j9Vh4O/vQqPwmGmLJUS46gduBLGGG6//XZp3N3djUuXLsVwRgQRPMqQUyq5IIjEgBw3BBFeSLghYkrR4nTklMjiQ6yCbxMVLiU4xw0AVeeZ/v65CRdbHqxAVpHcyv2dX12B3RqdkhYAYRNuAGDHYtl1c+R6X0j7ClDg9sEgiDhv0eG6yd8JiimEGqnj1LjbKVBepREBUTGWhBsAYMAhfTvqNXLr8hJfCvY6ysAlmXizefNm6fbAwACuX78e1cdnHMPGu8tx9+dXQ2eUc28uH+nEn759WiqdUpVKeTxz7ugWbYqLi7FixQpp/Pbbb8Pj8cRwRgQRHJyqqxQ5bggiEVA7buhzG25EAILI4mqhtNLIQsINEVMYYyrXzfXTvRgdJFV+rvAWWUQRxubnVsrOloWLuQo3Gi2PvZ9aAV7r/+pwjHrw9jNXohYsrRRuBgYGMDIyEvS+dlbnSLePNw7C5Q09syfL499Hm56HjzFAFP1ijCJEmomi1HWKE0WUOr2ocnjgFAWkDw8DmCDcAAADDhracF0j50CV+VKxx1kCLol+JTMzM7F0qdzF7Pjx4zGZR9mqbDz89zXILZWF0cFOG/74r6dRe7gDUHTKAOK3XAoAbr31VnCc//NqtVpx4sSJGM+IIOYPhZwSROKhdtzQ55YgQoWEGyLmVK7LQUqW/6BMFERceLstxjNKHLhUudxnPuHEgFq4GRiYe2elzEIztn1ADjdurRvAxYMzZ+SEi/T0dGRkZEjjUFw3G0ozYAgIUB4fzrYMhzo9jPEcBAAWn1pNUbpuAkHGTBRR7fBio9UFjQi0MS80Pr/wM0m4ASAy4B1DKxo18jwrvOm4xVkClkTizdatW6XbTU1N6O7ujsk80nJMeOh/b8Da2+TyQJ9HwKFn63Hg923waBLjgDQzMxObNm2SxkeOHAkp2JsgYgGVXBBE4kGOG4IILyTcEDGH4znVydHl9zrhspOdfy7wKQrHzTxLpbKy5CDW0dFRuObxo7pyVxHKVsvCz7HnG6LWIjxc5VIGLY9N5fJrEI5yqXY9Dwag2uEBJ4rqkijGoBFEFLq82Gx14eE+O7ZY/a/5kTQ9ujSyK0c/TemNwIC3DK1o5uU8o2pvBnY7FyFZ/KklJSUoKCiQxseOHYvZXHgNh20frMY9X1gDY4pWur/xwgBO1fwdRlLLAMS34wYAdu7cCcN4qYnL5cKhQ4diPCOCmB+cMf4DwQmCUEOOm8gjiiyuFiKykHBDxAXLbiqE3uzPlPC4fP5yBGJWuCDDiQEgNTVV6uIDzM91wxjDLZ9YCmOqv0W4zytErUX4ROEmlDKtndXKnJvQA4oHtTyuGzUodvlw74ADN404scLmxoZRF24fdOBDfTbsGXJiqd0DgyCiU8fjZKoeTQYNXFr530Lv88q5OBMQmIj9xma08rLDaok3E7tcxUkh3jDGVK6b2tpajM7TTRZuSldm4cP/ZxOKlshuL6chC2fXfRnNJXvgs9tjOLvZMZlM2LlzpzQ+ffr0nMsjCSIeYHplxg2dABJEIkCOG4IILyTcEHGBVs9j1a5iaXzxnXb4PNS6dja4EBw3HMcFlXMTwJiiw22PTWgR/nzkW4QrhRur1YrBwcEZ1p6ZHYqcm9rOEQyMhX5gcSpFj3MWHYw+AdUOL2pG3Vhp8yDf7YNWBHq1HM5adHgh24S3Mo1oNWggMganQrjhIEIzQ0clHxOxz9iEDoV4s9yThZtdxUlRNrVixQqp9bvP58OpU6diPCPAnKbHfU+uxeb7K8C4gJOKR2PFA3jzj72wjcT3QemmTZuQnp4OABAEAQcOHIjthAhiHqgcN1QqRRAJATluCCK8kHBDxA2rbi4GP9422W51o/5kbLItEgle2VVqnuHEgLpcKpgr8JNahL8b+RbhFotF1RErlHKpxXkW5Kb4rwiJInC0Ye6uo+nwcgwXLTq8lmXC65lGnEjR4USKDm9mGvG7XDPeyDLhkkUHq7JFOACXwv0EAAbfzOWCXibidWMzung5r2SZJwu7nYsSXrzheV6Vy3L69Om46IbEcQw1d5bhwa+sh8EjB2N3tnvw+38+ida60N8/kUKj0eC2226TxlevXkVLS0sMZ0QQc4cZKJyYIBINjhw3kUWMv65SyeD8jmc0s69CENHBlKrDkq35uHykE4C/NfiyrQXS1W1iMsp24L55Om6A4AOKlWx5sALt9UNSxs07v7qCj/zjZpjGy6giQXl5OXp7ewH4hZuampqg9sMYw47qHPz5rD9c+b3rfbhvTaFiheDnOKrlMAqgT8/PNgkAUJVKAYBO8M76+F4m4DVTI+62l6PA53dfLfFmgndyeNvYAmEO849FSfLu2/9t1nU0GhFb1gM8D9jtdjz6ye+guze4n6yD+74W1HbTUVCZhm09v8FF/U3oy1kHwN9h7ZX/uoB1e0qw+f4KSYSOJ1asWIFjx46ho8Nfirp//358+tOfBmP0HUvENxROTBCJh1JwJccNQYRO/B1ZEguadbeVSCerQ912tNTG7xXseEDluAkiBySUUqkAsWgRPjHnRpihrGg2dkzIuYnIvBVdpabDx3PwcPJX8lSdpabCwwS8ampCu6Jsqsqbjr2OMnAJHBTn9TJ098miV3GBF/F0KUevZ1hZ9xSWXHsOnKIn+7m3WvH8985ipC/+DlIZY9i7d6807ujoQF1dXQxnRBBzg8KJCSLx4JROOZcroseFBLEQIOGGiCvS80woV3QrOvdWawxnE/+ow4lDK5UaGBgIWgCJdovw0tJSySVgt9vR1xd8R6htVfL7rWvEiYa+CHTHGu8qNRuTAorniJcJeN3UhFZFt6lybxrutJeBT2DxpqNLfj3MJhEZafGTe8WMBjAARZ3v4Y4tNmTkm6S/9TZb8YdvncT10z2xm+A0lJaWYunSpdL4wIED8E7TxYwg4gWmdNxQqRRBJARKxw18PiAOSp6Ti9h3kZrcVSpxjzkTARJuiLhj3d5S6Xbn9WH0NM2vW9JCQt0OPDThxuv1wmoN/rWOZotwo9Goahnd2NgY9L5yUvRYXpAqjQ9fi123HWXOzXQtwafDx0S8YWpGk0bOXinxpeJuezk0YmJ+1TucHPoH5bkXF8aPwKAs3UjX2vChv9uI5dvk96Tb6cP+p+pw8NdX4IlCt7X5cNttt4Ebd3cNDw/HRfgzQcyE2nFDWRkEkQgoHTcA5dwQRKgk5tE8kdQUVKYhvyJNGp97iwI0p0OZcSO63RDc7nltr9frpe49QPDlUoDcItwUpRbhE8ulQmHHYmW5VPDunVBxBum4CRBoFX5DMyzdV+RLwT32CmgTVLxRum4y0wWYjPHhulGdSNod0Op57P7EMuz99AroDHKJ1+WjXfjjv5yKmIgZDNnZ2apcqEOHDsFB+QNEHEPhxASReLCJwg39zhBESCTmkTyR9KzbWyLdbjzXh5E+ewxnE78oM26A2OXcBDCm6HDr49FpEa4UblpaWuDzBS8Q7VS0BT/eOAiXNzYOCaXjRheEcAMAAgMOGFtQr5XbpBf4zLjXVgGdOEtQchwybOUwZpOtt0X58eG6UZZuKE8kq2vy8PA/bEJumeziGuq244/fPo2mi8F9vnxeAbYRF+zW+QmzM7Fr1y7o9f6OH06nE++//37Y9k0Q4YYzUjgxQSQaTK9XjUVy3IQVEfHXVYpSjCILCTdEXFK+Ohvpef7MCFEEzh9oi/GM4hNmMvnb7ozjC6LUKRydpZSULM/Cmlsj3yK8pKREKvdwuVzo6uoKel8bSjOgH+8C5PD4cLZlOBxTnDcurfxvaQhSuAH8naLeMbThslb+98wTzLjPVgmDkGjiDUO7wnWTm+MDz8X+0EB1IjkhLDUtx4iH/vd6lQCt1fPILVELrXNBFEVcfq8Tz3/3DN7470s4/Fw9+trmL9BOxGw246abbpLGx48fx9hY/LiCCEKJKuSUwokJIiFgjKndcuS4IYiQIOGGiEsYx7D2Nvnk/+r7XXCMhe9qc7LAGANnUeTcBHHipcy5CdVxE2DrA5XIKpbn9c6vrsA2Et4rLTqdDsXFxdI4lHIpg5bH5gr5dYhVuVQ4HDcSDDhkaMclrfxvmiMYcb+9EkYhuLbasaJvgIdn/OXQ8H7xJtaoSqWmcADwPIebHqrCvV9cA2OqDrc+tgzmdP2k9WZD8PlFqvQ8M+yjbtQe6cQf/uUUjvzhGkQhNAFry5YtMJn8ArnH48GRI0dC2h9BRAqmEErh9UKkkFOCSAiUois5bggiNEi4IeKWJVvyYUzRAgC8HiGiXYoSGd4SWkBxOEulpDlpOez9pLpF+IH/7zKEEE80J6IslwoloBgAdiragh+OkHDDiSL4GdphOrVa6bbBF4YTEwa8Z+jAeV2vdFemYMSDtiqkCrrQ9x8lBIGhp1d2ChXmxb41uKpUyjF9KWfJiix84ptbUbYqe9p1ZoLXcFh1czHu/eIafOKbW7H3UytQtiobFw+2442fXcLoYPDuA71ejx07dkjj06dPY2hoKOj9EUSkmBRySlfuCSIhIMdNZBHF+FqIyELCDRG3aLQ8Vu9WlNwcbIfbGR/5FvGEMqDYNzp/x41SuBkdHYUzTDb0zEIztn9QbhHefnUIZ95oDsu+A1RUVEi3W1tb4Z5nOLOSnYvlnJvaDit6reGz4xe6vNgx5MRHemyotk8vyLg0sjihCyGzRwUDjum7cFont6ZOE/V40FaFbJ9xhg3ji84ez8AInwABAABJREFU2SVkMYtIS4ltSLHScSPO0uVGqw++PC3gqgn8v2pDLnZ9dAnKVmahpW4AHddCE1pqamqQmurP4/H5fHj77bdD2h9BRAKV4wZULkUQiQKnyLkhxw1BhAYJN0Rcs3JXEbTjHVpcdi9qD3XEeEbxBx9iqVRaWhp0Otl90dcXPrfJip1FqFwnCyKnXm1Ce334rugXFxdLAas+ny+kcqnqXAuK0uWTg4P1vTOsPT8KXD5UOr3QiUCpc3pBxqXqKhXGUgAGnDJ045i+U7rLJGpxv60S+Zxlhg3jB4eTw9Cw/JNVVBBbEZdFKXODcUz6vyiKEAURlgw91ty6CIJPxLn9rfD5ghextFotbrnlFmlcW1uLjg76niXiC6bVAkwOKZ+YK0UQRHwSrd9KglgIkHBDxDUGsxardhVJ4wtvt8HriX2+RTyhdNwIY/MvlWKMISdHFlfCKdwwxrD70WVIzfb/cIsisP8XdWHLu+F5HpWVldL4xo0bQe+LMYZbl+VK47evhE+4aTXIgkye2wf9NCVjTkXGjd4bfmHivL4PbxtaIYyXGenA41ZDBcr49LA/ViTo6JZfn+xMAXpd7Fw3nEHZ5SY69m/GmCTkGCw6GExacDyDx+mDGIJHefXq1cjLy5PG+/fvD2l/BBFuGGMq181UuVIEQcQfzKBw3MziTiXmjwAWVwsRWUi4IeKeNbeWgB/v+GO3unH1WHeMZxRfKMOJgymVAhAx4QYA9EYN7vjsKnAa/xe6w+rGW7+ogxCCS0BJVZVcjnX9+vWQTjhvWSoLN+/d6Pf31g4DfVoO9vETbg5A8TQlf8pwYn2o4cTTcE03hDeMTfDAL4DyjMMOfSmWaoLLYIkmA0McHM5xBwoDCvJiJ+KqwomjeBUx8P7ubhiG0+6B4BOhM/BgLPj3Ksdx2LNnjzRuaWnBtWvXQp4rQYQTdcgpCTcEkQioLnLQ55YgQoKEGyLuMaXqsOymAml8bn9L2E76kwE+JbRSKSCywg0A5JSkYPsHq6Vxx7VhHH8xtDDhAErhZnh4OKSW5lsqsmAcb8ltd/sApynk+QEAGEObQc45KZ1OuNGGsavUDLRqR/GyqREO5h2fHsMmfTHWaQtm2TLWMHR2y69jQZ4XjMXGGaIKJ3ZG1nGj7B7lcfrQfLEfR//sd5etva0EHM+FHPxdVVWlcq+99dZb8IUrZ4kgwoDyyj05bggiMaDPLUGEDxJuiIRg3d4SqUTA2u9Ew7nYtGuORziLIpw4iFIpQC3c9PaGr0RIycpdRajeKJdjnHurFTfOhP5YqampqjKPUMqlDFoe2xXdpeAIX/5Lq14WZQpdvim7Szm1kXfcBOjV2PGi6QbGBDnQeZUuD1t1i+La7Nrdp0FAT9Bpgdys2IgLqnDiMB+MiqKoFqcZ4LR50HSxH2/9f5dx4JnL8HoEVK7NkURtjgv9X03puunv78e5c+dC3idBhAvVlfsIi6UEQYQHTk9OuUgiiiyuFiKykHBDJASp2UZUbZDLWM682UIZDONwqnbgwTlucnPl19ZqtYats5QSxhh2f3wpMgvN0n3v/OoKBrtsIe97YrlUKCjLpWC3hK3rdJeeh3v8N00DoMg1WXCIRqmUkmHehTec1zEkyCdB1dos3KwvBx+n8o3Xy9Dbr2gNXhCb1uCRDFxkjMHnFTHYacO5t1rxyn9dwHP/dAKv//Qimi/1Q6PhUHNnGW7++FIAmDaceL4unPz8fKxdu1YaHzx4EC7qAkLECZzqM0fvS4JIBFSOG/rcEkRIkHBDJAwb7iiVbg+0j6H18mAMZxM/hKNUKjU1FVqtVhr39/eHPK+p0Op53Pm5VdCNlw15XD68+bNLIbd5Vwo3zc3NIbUF371EIdx4dYBHN/3K80BgDO0K103JFM85WqVSShyiB/scN9Djk987izRp2GOohA7Bt7GOJMqQ4lSLiBRL9IUbzhjecGKfT8BA5xhqD3fgtZ9cxHP/dAK//9ZJvP/8DXTUD0Fv0qJqfS5ufWwZHvjKemy+rwIGs/8zy/McXA4vWusG0FE/hO6mEf8cOQZBEOclcu/evRuacQHRZrPh/fffD/m5EUQ4UIql5LghiMSAHDcEET40s69CEPFBVpEFpauy0HLJn2Fy9s0WlK7IivGsYk84SqU4jkNOTg46O/3tovv6+lBcXByW+U0kPc+E255Yjtd/egkAMNRtxzvPXMHtn10ZdMBqSUkJdDod3G43fD4fWlpaUF1dPfuGU5CfZsDKolTUdlj9d9gtgC48ImGrgUfFuGCzyOkFE0WIiuccbcdNADd8OOBswA59KUo06QCAXN6CO4xVOOBshF0MY2vyMGCzcxi2ckhP9TtNivK9uHojPALbXOHC6LgRRRFn32zB5fc6MTbsAgOQUWBG0eJ05FWkoXRFFtLzTJJQo8Tl8OLky41oPN+HsWEXeJ4DxzMUVqdj+4eqkZ43v5ymtLQ0bN26FUeOHAEAvP/++6ipqUGKonsdQcQC1WeOsjIIIiFg5JSLGCIAIc7Kk6gWIrKQ44ZIKNbfLrtuOq8Po6thJIaziQ84i1x6JIwFX3YUjZybAOVrcrDhTvnfsuFcH87tbw16fzzPo6KiQhqHXi4lZ+bAYQE4MSxLu5FHoEBKLwJ5Xp/q7y6d7HDR+bwQGSK+BPBBxCFXM655ZLdVOmfEnYZqpDHZ6hwOwjFvpesmJ8sHrU6c9TmGE2VrYtHphCgEH5gueEXYhl0YG3aB4xiW3lSA+7+0Dvc9uQ6b761AfkUa9CaNFFIcKIHqaxvFoWfrcfHddjDGsPa2Emx5oAKF1enovD6MP/7rqaBypLZt2waTyS/4eDweHDx4MOjnRhDhQvWZoyv3BJEQcKp24PS5JYhQIOGGSCgKq9JRUJUmjc/ua4nhbOIDXnElXBgNznEDqHNuItFZaiKb7q1AyfJMaXz8xQa0Xw3e2aJ02IQSUAwAtypzbpwmwBeer0ovx9CpV3SXcqhdNbFy3AQQARx3t+OCu1u6z8zpcIexGjlcmDpshYn+QQ5O13iLdQ4oyI3u66W8+g8AYghZMLyWw80fW4qbH1kCjme4cboXJ15qQOf1YdV6jGMQRREcx+Cye1B3uAON5/tQtjILH/zbGmz7QBXW3laCO/9iFXZ8eDFEETh/oBWOsfmVDhoMBuzatUsanzt3LuJiLkHMBqen7jQEkWgwRamUQIIrQYQECTdEwqF03TRf7MdAR3C5LsmCMpzYF2TGDRD5luAT4TiGPZ9cgZQs/4+6KAL7nqrD6GBwP+zKnJvBwcGQ2oKvKkpDtiVwksD85VJhotUoCzclTp//iY8Tza5SM3HB040TrjYpG0XPNNhjqEIRnxqzOU1EBENnjyKkOMqtwZXtwIHwBBSv2FGER//lJhQvzcDl97vw7m+v4sLbbXCMuqUywsD/W+oG0FI7AJ9XQPu1YTRflJ1SvIbDspsKsP72EvQ0W9F+dQgA5pV1U1NTg8zMTGm7AwcOhPz8CCIUmFFZckEZNwSRCKgdN1QqFVZE/yFkPC1UKxVZSLghEo7SlVnIKpLLg0IpsUkGlBk3ot0O0Rdce2SlcDMyMhKVbjIGixZ3fm4VeI3/q8g55sGbP6+FzzP/spO0tDTVcwjFdcNxDLcslfcFe/jyPdoMGul3zewTkaV4ri6NLETEUrgBgHrvAA65muET/fPTMA679eWo1GTOsmX06OrVIFChpNcBOZnRaw2uPBgFwhNQDABGiw53/eVq3PnZVXDavXjvT9dx6Nl6tNT6hchAq/DuRivsVjeqa/KQkWfCwd9exQv/fhYjfXZpX2k5fpeUY9SfUTSfDCme53HbbbdJ42vXrqGpqSkcT5EggkLdDpxOAAkiESDHDUGEDxJuiISDMaZy3Vw71QNr/8K9+qbsKgUE31kqLS0tKp2lJpJTkoJdjyyWxr3NVhz+w7Wg9hXOcqlItQV38gy9Ovmrt8Qpiw2uiY6bGLe8b/WN4ICzEW7RP0eOMWzTl2ClNneWLaODx8vQOyCLXUX50RNumEYDpvi8hLsleMW6HDz+7W1YtbMIDef70Hi+D6IogjEGjufQeW0IxhQdNt1TjtueWI41uxehv20Uv/m/x3HylUYAAKfxCzVafXDdwZYtW4ZFixZJ4/3790MIIcuHIEJB3VZ44f7mE0QiwchxQxBhg4QbIiGp2pCL1OzxEhtBxPkDbTGeUezgzGbV2DcanHAT6CwVIJqZFstuKsSKHYXS+PKRTlw+2jnv/SjLpZqamuDxBN8NaXt1DiS1RuD9WTdhosWgaAuuyLlRZtzwogiNGPuT5B5hDPucN2AX5Ndyva4QG3VFMZyVTLsipDgtRYDFHL3XTBmWKoTJcaOE4xh2fnQJPvjVGqy/vQSMMYiCCKfNA49bgFbPIz3PhMwCM7Y+VIndn1iG4iUZOPV6M579xnEces4vgKblGGZ8nEDosfRcxseMMezdu1e6v6urC7W1tWF+lgQxN1SOG8q4IYiEQJkHR+HE4UcUWVwtRGQh4YZISDiew7o9JdL48tFO2K3zC+BMFphGA2aSRQXBljg5N0p2PLwYeeVyhsrh566ht8U6r32UlJRIriGv14uWluDDqy16DWBUdOmKUM5NhldE6ni5lNJxA/g7S8UDQ4IDbzqvwyrIV8uWaXOwU18KHrH9oR6zcRgZledQnB+91yxaB6R55alS2RPjGAxmLSzpethGXBjq9r9HeQ2Hqg252P3xpdh0TznAGByjbpQsz0RhdcakfU6Vd1N7uAO2EX9nqwCLFi3C8uXLpfHbb78dkiBKEMHCKTNuolDKSxBE6KjagdPnliBCgoQbImFZurUAxhT/SbrPI+DiwYXruuEVAcWhdJaKpXDDaznc8dmV8r+pV8CbP6uFc2zuJ4kajSasbcFhUohgtvAJN2MaDoMaZbmUX2xwThBu9N74EG4AYEx0403HdfT75AyVMk0G9hqqYGCaGbaMPMrW4LlZPmg10SkxU4WlRtkBsHp3MQSfiBMvN8Fpkz8jqdlGbLy7HFsfrETluhzsemSJ9DfHmFv6PAXcOz6fAMYxdN4YxqHn6rHvf2rhcatLzm699VZwnP/9OjIygpMnT0bhGRKEGmVWRrgypQiCiCyqCxz0uSWIkCDhhkhYNDoea26V8xdqD3XA7YifE91okqidpSZiyTBg76dXIpChOjroxP5f1EqlG3NBWS4Vas4NzAoRzGMAPNrp150nk7pLAfByHHyKANlYBxRPxAkv9jtvoNMrO6FyeDPuMixGOpu5HCeS9A3ycI0b7qLZGlwdlhrdA9KCqnRUrMlGw7levPubq+i8PqT6e/nqbNz62HKkZvnnKAgiTr/WjHefrUfTxX5/Xg7HwPP+w4B3f3MVGi2HVbuKodXxKkdOVlYWampqpPGRI0dgt9tBENFE5bihkguCSAiYXpFNRY6bMBP70qjJpVJULhVJSLghEpqVu4qhM/hPgF12Ly4dao/xjGIDl6J03AQv3OTmyqGzw8PDUeksNZHiJRnY8mClNG67MoSjf5y7c0Yp3AwMDGBwcDD4yWg9gFbxGtjC112q1SALN7luASafADAGFx8fLcGnwwsBb7saUe+Rw6stnA53GqtRyqfHZE6iyNDVK79uRVFqDa68khiJjJuZMKXqcPPHl2Lp1gI0nO/D289cwYGnL6O1bgCjg074vIIUSiyKIjiOwZyhR8O5Xhz89RUcf6kRg13+MqvTrzdjqMeOJZvzUb0xb8rH27VrF/TjB+BOpxMHDx6MzhMliHGYQiilcGKCSAwo44YgwgcJN0RCozdqsHJXsTQ+t78VLvvCy1/gFS3BQ8m4mdhZKpoBxUrW7SlB5XrZ/XPxYDsuvDO3UriMjAxkZ2dL42vXgutQJaF03YRRuBnUchjl5SsTZQ6/60Yp3MRLxs1ERAAn3O046WqHMO7M0DIeuwxlWK8tiMn1ls4eRWtwPZCXHfkOU6pw4hgckOoMGtz66DLc+8U1SM02ovlSP1790QVcPNgOr6LNfKAN+Pq9pfjwP2xESqYBZ/e14PBz9Ti3vxUnXmlEZoEZa2/z54YJgjipdbjZbMaOHTuk8alTp9DR0RGFZ0kQfjjqTkMQCYeqHbh7YWZRRhJBZHG1EJGFhBsi4Vm3p0TlulmIHaaUpVLBtgMH/J2l8vLkK+49PT0hzStYGGO49bHlyCmRhZL3/ngdTRfmVr61ZImc6xFW4cZpArzBtVaeBGNoNMoiTbndL9K449xxo+Sqtx/vuBrhEuV5rtTl4RZ9BXQI0+s0R9wehu4+RflZoRdh6+E+DZzCAh7LLjcly7Nw/5fW4e7Pr8E9X1yDxRvzoDeqc4dEUYQgiMguTsGH/m4jtn+wGl0NIzj2YgMAf2lVet54API0j7NlyxZkZWZJ41f+vA8DXWPoaw0+V4sg5ooq44au3BNEQqAWXJ1TBuMTBDE3SLghEh6DRYu1ig5T599uW3AdpjiL3BI8lIwbAHEh3ACAVs/j7r9aDUvm+I++COz/Rd2cOk0tXrxYut3c3AxnKAf5egfAB1xcDLCHz3XTZJJPrnM8AlK8QkIJNwDQ6RvF645rGBLk0oUiTSruMkY/96atU4PAMaHJKCInM7KtwVWOG1fsTyQLKtNQsjxLJXgGYIyB4xgEnwBRFLHm1kXYfF+FdBDddLEfdUc64Bh1g413lVK2CRdFERqNBnffczc07hSkDa6E93IJ/vDPJ/Hif5zF6z+9iNHB2L8GRPJCGTcEkXgoM24gCAB1JSSIoCHhhkgK1tyyCAbzeBtolw9n9wXfBjoRUXWVGrPNsObsxItwAwDmND3u+as1kqPK6xbw2o8vwjowc77BokWLYDQGQlkFNDQ0BD8JBsCiEIvGUqdddb4MazkMaWR/Q7ndmxClUhMZFd14w3EdLd5h6b5UTo87jdUo4dOiNg+Hi0PfgMJ1U+RBJF036m4ZCXIiyRgYY7CNuHDqtSZY0vXYfG857CNuvPtsPY784To66v1Bx0oBhzEGn0+As8uAbPtqaN0Z8GpscBr6kLXIjLarQ3j+e2fQcW1opkcniKAhxw1BJB4q4QZULhVORACiGGdLrF+UJIeEGyIp0Bk1WH97qTSuPdSBsaGFc2DHmcNTKgVMFm5ibWvNKrLgjs+uAjd+Emm3uvHajy/CNUMHMY7jUF1dLY3r6+tDm4SyXMphBnzh++psVLhuKhxeOBPMcRPACwGHXM045+6S3jNaxuNmQznWavOjlnvT0im/filmEZlpkXPdsAR0AAQ+R0d+dw1ej4CVu4pQc1c5Hvv2TVi6JR/XT/dg31O1qD3cAe94W/CAgHPlaBdOvtIEJmjhMfdjOOs8RlKuQChtwU0PVsI27Mb1U7EVe4nkRVlyQd1pCCIxUF7gAEh0JYhQIOGGSBpW3VwEc5oOAODzCjj1enNsJxRFVBk3IYQTA2rhxuVyYXh4OKT9hYNFyzOx62Nybs1gpw1v/uwSfL7pT8qV5VLXr1+HIIRwAm+wA1xARAlzuZQiiyTdK2I0TXb0JJJwE+CSpwfvuJrgFuVw4NW6fNysL4/K49vsHAaG5J+2kqLIvYacygEQ/11uhPHPS9OFPjSc78OipRlYubMIAKDR8rj1seW4/8m1MJi1GO61j19B84twPU1WnHqtCfYRF1bvLkbN3aUAEwGRobb2EswlbmQXW1B/sgfW/vh/LYjEQ1maSFkZBJEYTHLcULA4QQQNCTdE0qDR8ai5q0waXz3ahZE+e+wmFEXCmXFjMBiQnp4ujWNdLhVg+bZCbLhDdlW1Xx3CoWfrpz14r6qqAsf5v+IcDgfa2kIIrWZQu27GwifcjGk49Grlr+LhfLkleyIKNwDQ4bPidcc1DAvylbV+IXqfxVaF6yY9VUBra2tEHkftuIn/g1GO5yD4BOx/qg56kwZr95RAb9JCFET/IoooXpqJR76xBWtvXQStnpe6S514uQF2qxvVm/KwYkcRtt28CYWFhZJ489prr8GSoYdWR4cVRGTgJpwAiuS6IYi4h3EcmKJbqeimz204EUUWVwsRWegIi0gqlm0rRGq2/2RKEEScfLUpxjOKDuHMuAHiK+dGyeb7KlBdIwsbV452TZtnZDAYUFoqCz0h5dwA6pwbhwUQwvcDpSyXGsvNlmqEEyXjZiqsogtvOK6h1TuCFu8wLnlCex9pGA8tN7dOVSOjPIat8s/bkSNHQnrs6eAMSgdA/LtMRFHESJ8DGh2PyvW5KFnu7xDFOOZfGIMwHkhsyTBIomjtoXa0XR1CarYRq24uRmq2ERzH4Z577gEDA5iIwb5htF/vh2PMA59Xdrf5fALsVjdsIy7J8UMQwcCo5IIgEhLlZ5c+twQRPCTcEEkFr+Gw8R65JOPayR4MdITmQEkEVKVSo6G35o1X4YZxDLc8tgwFlXLg7fEXG6fN1aisrJRuNzWFKOIZbQA3Xv4jcmEtl2o2ahA4pRUMOvRnZwMA9N7EFW4AwAMB77qa8J4rtLBwLcdja24l1mWWotySAw2b/adL6bq5fv06uru7Q5rDVKi63CRAODFjDBn5Znzq33dg20NVACAJNQECGTii6A8kHhty4cr7XQCAVbuKkF0sf9cUFhZi46aNAACdKxNuu4D8yhRk5MsOwLbLg3j9pxfxyg/P451fXUXj+b6IPkcieZmYlZEouVIEsdBRlkslgjuVIOIVEm6IpGPxpnxk5Jv8AxE4+Uryu244iywi+ELMuAHUwk0kTnhDQaPlcedfrkJajux2OPDMZXTeGJ60bnm5LOJ1dHTANU9rvcgUCweIinIp0Zai/nsIi0PD0KWXv45bS/3t7XWCz1+mleCLj4nq++ZJtj4FGsahxJyJDVmluK1wBYpNGTNuMzjMYdQmP9h77703/weeBdVVxDhoBz4fdOPZSgGhZiKBEqmOa0MY6rEjrywVJcuzoNHKridRFHHLLbfAYkiH1p0BgGFYaJNajgf2Y07Tg+M53DjTizd+dgkvff8ctQ4n5g3TagFe8f4j4YYgEgJlmSOVSoURMQ5LpSh6LKKQcEMkHRzHsPm+CmnceL4PPc3WGbZIfJQZN+EolcrPz5duDw4Owh1n7RuNFh3u+cIaqQW84BXx+k8vYrhHnaNSUFAA/fgBgyCEIevErHgf2SJXLtW2aBEExhI24ybcdDmGcW6wFe/33UCP0wqLRo8tOZUoMWfNsBVDa4f8mtbV1WFgYCCs81I6ABLBcTMfAk4ca78DHpcPhVXpUhlqAMYY9Ho91i/dDr0rEz6NDV0jjbhaf1USfkpXZmHPp5bj4b/fiPueXIOVO4rQcW0YL//g/JRiK0HMhPIEkDpLEURioLzIQU45ggiepBVu7HY7XnzxRXzqU5/CkiVLYDAYYDabsWbNGvzTP/0TxuYZ4FpWVgbG2LTL1atXI/RMiGCoWJeDnBLZhXLi5cYYzibyKDNuRIcDYoglNhkZGdAqwuR6e3tD2l8kSM8z4c6/XAVO4z9BdNm8ePVHF+AYk0UmjuNQVlYmjUMulzLZIDJ/URMTeXzmxdPQzvG11nq9+OHPf4vtl69N+fdWowaBPkwugwE9eXkk3CgYdtvRaR9Gv9Pvehr1OtFqm1mI6RvkYXfIpT/vv/9+WOeUzAejASdOa53/Nc6vTINGx08KAx/qssPergUnauHSD8CrGcMbb7wBl8slrRtw6RRWZ2D7h6pRc2cphnvt1DqcmDcql5sj/nOlCIIAmF4n3RapVIoggkYz+yrz41e/+lXY9vXoo48Gve2zzz6Lz3zmMwCAZcuW4b777oPVasX777+Pr3/963juuedw6NAh5ObmzrInNY899tiU96elpU15PxEbGGPYfH8FXv2vCwD8OQsd14ZQtHjm8opERZlxAwCCzQY+hPckx3HIzc1FR0cHAH/OTXFxcUhzjASFVem47bHl2P+LOgDASJ8Db/z0Eu770lrpZLG8vBz19fUAwiDccKK/u9SY/7UdZIX48c9+i7/63Mfg0Uz/dar1evHjn/0Wt5+vw+3n6/CpLzyO95YvVq3j5hjaDTxKnX75prW0BLrW+BPMYgEDgwgRWXoLVqT721ef7Gsc/9tMzlyGtk4NllR6AADnz5/Hrl27kJqaOu0W84FTtidOspPIQMaN3qSF3qiRyk9F0f8fxjHYrW5cPd6F1roB5Fel4OpIP8CAUesoDh48iDvuuEO1T0EQwWs5rLu9FLVHOlF7uAOrdhUjs9A8xQwIYjKcwSAJ3JSVQRCJAadXCK5UKhVWqDJpYRF24ebxxx+XLNKhEopwo9Vq8dnPfhZf+tKXsGzZMun+rq4u3H333Th37hy+9KUv4dlnn53Xfp9++umg50REl5LlmSioSkPXjREAwImXGvHg/1oftvdnPMGZ1Sc+wthYSMIN4M+5CQg38ZZzo6R6Yx5G+h048ZL/RL6rYQTvPHMFez65Aoxjqpybrq4uOBwOGBUn3PNGIdwcqN6Mf3vzhzOKN0rRBgAMHi8efu/UJOEG8JdLBYSb9uJilLfE7+seTcTxQ5OarDIAQO1wB4bc9vG/zUx3P4+atQaMjo7C5/Ph+PHj2Lt3b1jmpSqVSrKyjcD3pClNB5fDi96WUWTkm1WZOJfebUfd4Q5kFJix7tZyZA7ZcOjQIYABJ06cwNq1a1Vllxzn71rFAKTnGOHzCHA5yFVGzB21yy25xFKCSFaYQRlOnFzuVIKIJmEXbgBgzZo1uP/++4Pe/sUXX8TFixdDmsNjjz02pTumoKAAP/7xj3HTTTfh+eefh9vthk6nm2IPRKLDGMOW+yvxwr+fBeA/oW+tG0TpyplyMRITxvNgJhNEu/9k1jdmg3aWbWYjXjtLTcWGO0ph7XfgylF/95vrp3uRmm3ElgcqkZubC7PZDJvNn/3T3NysEnPnjXkMgACAg9VgwbGS1bj9/LkpxZuJog0A7Fu7Al/55Ien3HWbkYcgCOA4Dl6tFq6M8DhDkoG1mSVI0RrQ7xrD1ZGuOW8nigw33XQT9u3bBwA4deoUtm/fDpPJFPKcFkLZxoodRWi60I9TrzZBo+VQuT4XI312XD7ahbP7WmBO1aHmrjKUrsrCImE7Ll64iKHhIYiiiFdffRWf/OQnwXEcRMHv0uE4huF+J7oa/YK6Rpe0FdtEBFCeAFLJBUEkBpyOPrcEEQ4iItysXbsWX//614Pevrm5OWThZibWrFkDAHC5XBgYGEBBQUHEHouILYXV6ShZnonWy4MAgOMvNaBkeSbYNJ1UEhnebIZ3XLgRwtBZSnmlvKenRyqdiEcYY9j1yBKMDjjRfnUIAHDmzRak5hixfFshysvLUVtbC8BfLhWScMMJEM02MJs/Q+mNJTdhZ/M53H6+TiXeTCfazFRW5WMMDpsH5hT/QY41Lyf4eSYBgTKofGMaqlL8Za2n+ptUf5sL69evx+HDh+FwOODxeHDy5EncfPPNIc+PS+KMmwB5ZamoubMMR/90Hft/WQfzn27AYfPA6/bBYNbilseWoWS5XwzneQ5333M3fvOb3wAA2tvbcfbsWdTU1Ejfub0tVhz90w0AwJJN+chZlBLX3y1EfMEZFOWJCdbJjSAWKqqLHFQqFVZEkX47FxJhv9SVmpoa8pVMo9EYtgyCqWhs9JdUaLVaZGZmzmvb7373u/iLv/gLPPnkk/j5z3+Ovr6+SEyRCCOb75c7TPW3jaHhXHL+mylzboR5hm9PhTL/yeVyYWRkJOR9RhKe53DH51ap8jIO/bYebVcGVeVSIefcAKruUq8u2w4f83+VBsQbo8s9b9EmwIhdLh0ZycmCZgFXMIsAtBwvlUidGWiBzeuS/jZX9Ho9Nm/eLI1PnDgx79bwU8GUGTdO56Tg3mRhza2L8OF/3ITqmjyk5RqRU2zB1gcrcd+Ta1GyPEv1vCvKK7Bs2XJpfODAAYyNjaGjfgjv/ek6Xv/pJXTeGIY5TY8tD1QCAIk2xJzhlCUXSdbJjSCSFdXnlhw3BBE0YXfcDA8Ph7yPn/zkJ/jJT34S+mSm4Qc/+AEA4I477pBaBc+Vr371q6rx3/zN3+C//uu/8MlPfjJs8yPCS25pKirW5aBxXLA5+UojKtblqLIakoFwCzdGoxFpaWmSYNPT04P09PSQ9xtJ9EYN7v6r1fjzv52B3eqGIIh482eXcOtnq6R1+vr6MDY2BsuEQOd5YR6FCBEMDKP6FPzk5rvwxYOvAvCLN1e/8H9Uq89VtAGAYTdQ5nLBrddD5HkUCR60+BZuOee6zFIYeC06HcNoGgtedK3ZUIOjR4/C4/HA4XDg7Nmz2Lp1a0hzUzpuAEB0uVRXFpOJrEILbnt8OdxOL3QG9ftYFEQw3v99yvEc7rzzDjTWt4KNWaAZScVvv34MXjsvrb98eyGWbimAJUNPbhtiXjBlyCk5bggiIWDKUin63BJE0Cy44vLXX38dv/jFL6DVavHNb35zztvdd999eP7559HS0gK73Y7a2lp8+ctfhsvlwqc//Wm89NJLc97XihUrplwaGhqCeUrEHNh0b7m/tgLAULcdV452xnZCEYBPkYUI32jowg2gzrmJ54BiJalZRtz9V6ul7Ay304fDv25GmilbWifgugsaXgCMNmn4H7d+EPvWrphy1fmINgDg0miwqLVNGpdy7hnWTk7Y+Ie11JyFEnMmvKKA0/3NQe9vqNuGV/6zDksLN0r3HT16FG53aK8tM6hDroUkzblRotX7BRhRFCEKfqeNCMBudaP+RDcO/uYq9v24Hmnd62GxVsPgyIXL4UVWqQHbPlCFh76yHrs/thQFlf6AbxJtiPnAGRXlieS4IYiEQB0qTo6bsCLG2UJElAUl3Fy9ehUf//jHIYoivvvd70pZN3Phhz/8IR588EGUlJTAaDRixYoV+Pd//3f89Kc/hSiK+NrXvhbBmROhklVowZLNcmbL8Zca4bR5Yjij8KPsLCXYbDOsOXeUOTddXXMPhI01uaWp2PupFQicE9qGXDB2LwE37lwJi0hqkculBHs6/vpTH51ytSc//dE5izYA4OY0KG1pkcZ5vA8mJgQ/zwQhz5CKNRmLkKYzQoQIA6/F+qxSAP5cG7fgRbCn+CdebsRglw3dJzVItS4BRGBsbAwnT54Mac5K+zfgL5dKdgJCC2NMyq25caoHr/7oAg48fRmXj3bCMeZBZqEFXM4wrOmXMZx5Ad2Gk1i+Mx8FVekxnD2R6CgdNwJduSeIhIDTy65hMcQLJgSxkFkwwk1HRwfuuOMODA0N4ctf/jKefPLJsOz3U5/6FHJzc1FfX4/m5uY5bVNXVzflUllZGZY5EVOz5f5KaMavFjvHPDj1ahiyTuIIzqwolQqTcFNYWCjd7uxMLJdS+Zoc7PzoEmnss/NIG1oFJmjQ0NAQeh6JxSq1qWY+Df7ixdNTrvaDp56D1jv3lscujQbZ/f1IscrCUDmf3Ac6DECeMQ3VqXnYkl2JYlMmarLKwDMOzWP96LD7A6eD+RerSslFw7k+pGYZsHhTHvT2XGT2bYLWnYb33nsPjhBcMkyjAbRy/7ZkDSieDZ9PRF/bKACgdGUWbn10GT7yfzbhwc/fBI9xCALvxPDwMA4ceDtpc4CI6KDqKuVK7u9FgkgWVCWOC/R3kiDCQViEm5dffhkf/vCH8dBDD2H//v0AgBdeeAFLly6FTqfD4sWL8ctf/jIcDxUUg4OD2Lt3L1paWvDEE0/ge9/7Xtj2zXGcJLgkkiNhIWLJ0KPmzlJpfOlQBwY6w1NSFA+oHDdhyLgBoOq4ZrVapZbaicLKnUXY+qAsiGq8ZqQNroLN6gi9xTkvACb5de7Ql065WiCweK7ijYvXgAGoUJRzlfFuJLMHVQRwcagNV0e6kKI1YEtOBfKNaXD4PDg90AwA4ILw26TpjFiRUQQAuPMvVmPPEytQc28pGAPSBleD7yvA0aNHQ5o7p1e2OV2YB6TLtxXiwa+sR0aeCS21AzjzZjMazvYiLzcP27dvl1qAnTx5Am1tbbPujyCmg6MTQIJIOJjid1KgrlJhRRRZXC1EZAlZuPn973+PBx54AJ2dnRAEAQ899BCeeuopfOQjH8HOnTvx/e9/Hxs3bsRnPvMZvPHGG+GY87wYGxvDnXfeicuXL+Ohhx7C//zP/4S9pn5oyH812Kw4cSbik7W3liA1x59LIQoi3vvD9aS5AqwMJ/aFoR044O8Sp3xfJ5rrBgDW316KmrvKpLHWm4K0oZWov3o95H3zpkHp9r7FN8HJa7Fv7Qos/dE/qzJv5iPeuDm/K6ysqRlM8JdImZiIfG7urp1EpXa4A+90X8HYeOconyggW+9/XwtBCFdrM0qgZTw23VOO7GL/fjbfXYWKnSa49f0w2opx6dUhjAxbZ9nT9DBj8rcEnwuFVel45BtbsOH2UrRdHcLB317F8RcbsWpxDbKzs6WMsZdeegkeT3KVqRLRQ+m4oVIpgkgMVKVS5JQjiKAJWbj5zne+gy984Qs4cuQIXnzxRfziF7/A5z//eXz5y1/Gz3/+c3z+85/Hb3/7W3zyk5/Ed77znXDMec64XC7cf//9OHnyJG6//XY899xz4Hl+9g3nQV1dHerr62EymbB06dKw7psIP7yWw/YPVUvj9qtDaDrfH8MZhY9IZNwwxlSum0R1lW26txxrblkkjbWeNFx5YxRejy/off7/7J1neFzVubbvvadKo957lyxXucgV22DTXMCA6RB6CiekkOSkkI8kBNJJL5xUEpLQwabaBgy2ce+WZNnqvfcuTd3fj5FGM25qM2pe93X5svbMLktlZvZ61vM+r8Zi4bev/A0vk33y0Kkz8Jurb+GxL9xLr07LY1+4d1Tijak/D0dvNBJVPSiUTfdyqQFajN3sqM6huLMRH7WOKyNmMC8wFnmEgvusgChC9b4YbRaS5oe6PHfNzcuxRdTS41NOj1c1e/d9OurxCgeAK8tuTubu7y8lMNybkzsr2PdKERmxV0H/SlxzczN79uyZ2EEKpizOndwUEXIqEEwJnB03ilG8bgWC0TJm4SY/P5+bb77Zsb1hwwYsFgvr1q1z2e/mm2/mzJkzY73csLFardx999188sknrFq1ii1btqDVXrql7h//+EfS09N54oknXB7ftm0bn3zyyXn7Z2dnc/vtt6MoCp/97GeHPL9gcpAwN5i4WUGO7X1vFGIxjX4CP1mQfZxLpdxX0jSVc24GkCSJK25PIW6+n+Mxa7uebX/OxmodefCvxmLhT395kU3HT3Fd4SHH43+9YpMjiNisVo9KvLFIMtZ+kcK5XCpKtqBj+ocUD3CypZz9DYUoQIjeB4N68MZPLV36o0vV/3xFdws6Wc0Hf8/l6Pul9HTYxS+tVsuqtcvp8anArGvjxIkTtLS0XOqUF0UWjpvzCIo0cOu3MrnyrjRqS9opO9rB4kVLHc/v379/RO8lFWeasdmmhzNSMDZEOLFAMPVwybgRwo3bUABFmWT/JvqHMs0Zs3Cj0Wjoc7pZ9fb2BsDX19dlP71eP675GH/84x/ZunUrACEhIXzxi1/kwQcfPO9fU9Og26KpqYn8/PzzXAVHjhzh6quvJiEhgZtuuom7776bpUuXsmjRIs6ePctVV13Fz372s3H73gRjQ5IkVt6RitzfEaWzuY+TH1VM8KjGjsoDjhtgWjhuwP57X/fIfMyGwdd8ZW4rO58/M+JJ4a+ef5XrT+UCcNOZ3Y7Hbb1+YBt8W72YePOr51+91EAxquziT0RdHSarfWyyBPGqy6vEpLa3nbcrTpLVUkmX2X6zF6D1ZkFwPEm+oRc9zqrYONNWw9GmUnbX5SFJcGxbGaf3VAH2v4WFCxYSEBAAgM1mY9euXaMaowhdvDhzrozhoZ+vZM1n0rl23VoCAwMBeyvxd955B6t1aMG8uqCVd3+fxStPH6bwWL2jBbng8sS5k5tw3AgEUwPnUimbEG4EglEzZuEmJSWFU6dOObZVKhW1tbXntdrOy8sjNjaW8WIgdwbsQckvvPDCBf91DSPE9frrr+fhhx/Gz8+P/fv388Ybb1BUVMTKlSv529/+xs6dO/Hy8vLktyNwM4ERBuaujXFsn9hRTmfL1J50eSKcGFwdN+3t7VMuoNgZjUZN5GIw6gbFm6LjDez6z9kRTQhfW7mYPo1dXOn1N0F//oykyNDlKlqfK970adS8tnLxJc9v6hduZEWhpWdwcps4zUOKL4RVsdFs7EJBQSurSfYNI9YQRJwhGB+17pLHKig0Gbu45esLCU/04/j2cipymwHQaDWsWbPGsW9OTs6ohEnn0g2bmEieh7eflpj0ILRaLZs2bXI8XldXx6FDhy5xpF3gOfKuvftfa10PH/49l1d/fISSk43TJptMMDKEUCoQTD1EqZRA4B7GLNx8+ctfPi+UNzw8/LwsmTfffJP169eP9XLD5qmnnkJRlCH/JSQknHfMv/71L5dzLV++nH/84x9kZ2fT1NSE2WymubmZXbt28dnPftbtuTmC8WHxxkS8fO2tfC1mGwe2FE3wiMaGczixOx03fn5+DicdTG3XDUBKajIdAWcxaQdLY/IO1rF3BEHV+2al8ciXHuTtxRl89fN3ofg4hdt2+Z+3/4B48/biDB750oPsm5V2yfMPOG4AujoHb3L8ZBvB0tQv6xstFsWKRlYhI1HZ3ewIMR4KvY+GtMXh2BSFwuMNDpFu7ty5hIWFOfa7UEnsUEgumRujby1+OZCYmMiCBQsc27t373ZZZDkXq9mGIUCHc0Ox5uputv8lh9d+cpSy7CYh4FxmyC7hxGICKBBMBSStEG48w8R3kTq/q5ToLOVJ1EPvcmnuv//+Ye03mhtigcCT6LzULLs5mV3/yQOg6FgDc69sJSo1cIJHNjo85biRJImoqCiKiuzCVk1NDSkpKW47/3iTkpICkkJ74Bn8W+agNQcAkLO7Co1OZtnNyY7Oc+Wf/eaQ57sJOFzSzJ1/tbsH1H2+HL7rK4T4XMAN8ugT3DTE+WZ/5zcOxw2AbDJTb1URrrILNokqE82WMb91Tyyj7OxnAw41lRCm96XZ2O04j16lQSeraTdfXDiJSg1ErVXR0diLTVFQISHLMmvXruWVV14BoLCwkLKyMhISElAUZVgdCF0zbsQN6VBce+215Ofn09PTg9ls5v333+fee++94M9arVVx3SOzWbQ+nqPvlVJ8otHxXFNlF+8/l01Ygh9Lb0wkdlaQ2ztGCiYfrkKpcNwIBFMBF8HVdHk0WhAIPMGYHTcCwVRm5vJIwuIHS1s+fbVwyoZgyganduA9PW5diZ4uOTcA/v7+hIaGgmSjIzAXQ+jg2+CJDyo4vr18xOdcnBBEpL99QmG1KWzLGdvPyNlxo7VaKbUO1ofHqsyoL7NyqXNp6OvEqgwGNcd4BzLLPxKNdHH3Y1+3CYvJisVkxWq2H6vYFGbMmEFMzGDZ5M6dHztEG9swgqtdSzeE42YovL29XZoXFBUVkZube8ljgqN8WPf5udz55GISM0Jcnmso6+DdP2Sx9ZcnqMobXcC0YOrgXHIhHDcCwdRAlEoJBO7BY8JNZWUla9eu9dTpBQK3IMkSq+4cLFtprurizL6p2TnJ2XGD2YzixlUN55ybqS7cACQnJwOgyFY0qXUERw+KXoffKSHr48oRnU+WJW7MGPwZvX1qbH9DJqfyS63VQrVNg6m/nbJasos3AjuyJKGSZKK9A1kYHIdOHhS9BvwXVquNrI/twcTxc4LR6u37SLKEJEnMCF2CT3sqfi1zaMvVs3vrSfu5VfKQQq5w3IycuXPnOl6DANu3b6e3d2jRKyTGlw3/M4/bn8gkfm6wy3O1xe28/dtTvPXrE9QUtrl7yIJJgiwcNwLBlMNFuBGvW/ehAIo0yf5N9A9leuMx4aanp4c9e/Z46vQCgduISPJnxrIIx/aht4vp6556E2OVj2vWlKc6S7W1tdHT0+O2c08EzqVe5VUlbHhsDgHhgzk++14vJHdv9YjOuclJuDle3kply+h/Rs6OG53Vgg2JcqvG8Zg9pFgAYFMUKrpbqO5tI8Y7iPlBsYTo7ELcwP3DsffLKMlqJDDCQPpyJ/dYcTsfPZ9L9o4mvPoiUFsM6HvDOfNhK2/8/BgdTb2O7nMXQzhuRo4kSWzcuBG12v533t3dzUcffTTs48Pi/bjhsQxu/dYiYmcFuTxXXdDG1l+d4J3fnaSupN2t4xZMPK7twIVQKhBMBSStU1cpUSolEIwaUSolEADLb0lGo7O7HIzdFo68UzLBIxo5kre3S3aIO3Nu/P39p1VAcXx8vGPSaDKZaOlo4KbH5+MbPDgp2P1SPgVH6oZ9ztlRfiSFDopn72aP3nVjcimVsnesci6XCpat+F3GIcXn0ms1cbCxmJKuRmK9g1gRmsKK0GQyg+O5MnwGx7aXAbBsU5I97BZoru7i8DvFFBytZ8bSCJbfFUtryHFag0/Q411DQ0UH7z+XTWvdpQVQ4bgZHUFBQVx11VWO7RMnTlBePrIyxYgkfzZ9ZT63fGMh0WkBLs9Vnm3lzV8c590/ZNFQ3nHhEwimHK7twMXKvUAwFXB2ymGxoFgsEzcYgWAKI4QbgQAw+OvI3JDg2D79aTXN1e4TPsYDSZJcA4rd6LiRJMnFdVNTMzXLyQbQaDTEx8c7touKivAJ1HPT4wsw+PcLJArs/NdZSk41XuQsrkiSxE0Z0Y7td8ZQLmU6x3ED0K6oaLENllAJ1835nGypYH9jEd0WI2F6PxIMIYTofAiJ8eG6R2aTtCAUlVrGZrVxamcF9SUdqNUyCXNDWHhlGrPnpWPV9NDtW4wlsI6W2m4qzlw6N0U4bkbP8uXLCQ8Pd2y/++67WEZxQx+VGsDNX1/ITV9bQGSya1e3itxmXv/pMd7/Uxa1RW1jHbJggnEJJzYaRVcxgWAK4FwqBbi1lP9yR1Em1z+BZxHCjUDQT8baWPzDvAD7m8/eVwum3E2hpzpLwfTLuXEulyouLgbAP9SLm762wNEmXrEpfPD301TkNg/rnJvmD/6M8uo6KW4c3e/g3FKpAUqdyqXiVWZkUUx8HrW97eyuz2dfQyF76gvY21DAzV9fSGrmoEBQld9KeW4Laq0KrZeaD/5+msPvlrBmzRpkWQYJWuQiVBooP92M2XRxd5Nw3IwelUrFjTfe6Nhuampi//79oz5fzIxAbvnfhdz4lQzCE/1cnivLaWbLL0+w5dnjlGY3OVrCC6YW8rkTQFEuJRBMepzbgYMocxQMzfHjx/nZz37G5s2biYmJQZKki3aOtNls7N27l29961ssWrQIX19fdDodycnJPProo5SWlo7z6D2HEG4Egn5UGpmVt6c6tqsL2lzaz04FZB+nzlJudNwA08pxA7iEo9bW1tLVL3QFRhi48Svz0XnbxRObRWH7n3OoKWwd8pyJIQZmRg5OGHecHn6plTPGC5RKAVRYtVj655s6SSFKnnpZTOOBVbHRZOyi0dhJQ18nOq/+32V/l6iOpj56O00sWh/PVffOIH52MMe2lfHJX0uYk7YQAAkVZquJvi4TavXFPypdMjeE42bExMTEsHjxYsf2p59+SlNT06jPJ0kScbOCufVbi9j42DxC43xdnq8tbmfbc9m88qMj5B2sxWoZunOYYPLg7LgBUS4lEEwFZJ3WZVsIroKheOaZZ3jiiSfYunUr1dWXzpwsKSlh9erVPPvss9TU1LB27Vo2btyI0WjkL3/5CxkZGezbt2+cRu5ZhHAjEDiRMDeE+DmD3Ur2v1l4ydX2yYar48a9wo2z42Y6BBSHhobi5zcosgy4bgBCY3254UsZjtwji9nGe3/Mpq506LDT9XMGg663nx6dM+liwo0FiSrboOsmSXSXGhGyyv6RV1vcBkBwtA+JGaGsviuNReviaW/spW6PN9590Ug2FZJVhUVtfx1dzH3n7LhRhONmVFx99dX4+toFFqvVynvvvTdmt6MkSSTMDeH2JzLZ+Ng8olIDXJ5vqenm4xfO8t/vHeTUzgpMfSJzYSpwruNGrNwLBJMfSaMBp26ZQrhxI8ok++cmli9fzve+9z3eeecdamtr0Z3z3u+MJElce+21fPzxx9TU1PD222+zZcsWiouLefDBB+ns7OTee+/FbJ7698xCuBEIzmHl7anIKrsdr6vFyPFtZRM7oBHg3FnK3aVS/v7+eHl5ObanermUJEku5VJFRUUuz0ck+bPxi/NQaexvk2ajlXd+d4qaIXIynIWb09UdVDSPXOBybgeuOyfzo8QyuHIVrrJgECHFIyawv4OYxWx3W/iFeLH0xiSuujediGR/DG1JBDYvBGRq2kro7eu9qEX3XMfNgKtHMHz0ej3r1693bJeVlXH06FG3nHtAwLnlGwu59VuLSMwIcXm+q9XI/jeKeOGJAxzcWkR3m5hQTGo0GpAHb12F40YgmBo459yIsmLBUHz729/m6aef5sYbbyQiIuKS+yYnJ/Phhx+ydu1al3s1nU7Hc889h7+/PxUVFRw4cMDTw/Y4HhVuplo+iEAAEBDuzfxrYh3bJz+qoKXWve4VT+GpcGKwT4CiowfDd6uqqtx6/onAWbgpLCzEanUVQaJnBLL+0bkOIc/cZ+Xd35+iMu/igbWp4b6khA2WrL2XM/KyMpeuUjbXMTUrKjpsg2/dySKkeMSExfshAWXZgyU5kiyRsiiMq+5NZ9aqSJCtWDSddGmqzstdcc5HGXDcdHuHYzIqDlePYGTMnDmT9PR0x/aHH35Ic/PwsqWGS0SSPxv+Zx53/2Ap6SsiHa9rAFOvhRMfVPDv/3eAj/99luaaqRVOf7kgSZJLuZSYAAoEUwPZqSW4CCcWjBdeXl6kpaUB0yPmwWN3mBEREfzf//2fp04vEHiUzA2J+ATZVwdsVoU9L+VPCSFS9nYSbjxQyhQTE+P4eroINwNtwfv6+i7Yjjh+djDrH52Lqj/nxGKy8f4fsyk/ffFJ5Y3zBsvK3s0auTPpQl2lBpEodmoNniBCikdMZGoASfNDObO/hoNbi+jrHrTPBkUaWHn7DOIWe9PpVwiSwuHDh2lpbnNM5iVZcog3kk6PRaXn1LwvsT/4LrpaxURyNEiSxA033IC3d78bymJh69at54mp7iAo0sDV98/kvh+tYMG1cWj1gw43m1Uh70Atrzx9hPf+mEV1fuuUeO+/nHAul1JM4vUmEEwFJBfhRrxu3YWiSJPq32TDZrM57u2Hcu5MBTwm3Pj7+/OFL3zBU6cXCDyKRqdi9Z1pju2awjbyD48uaHY8kQ3ejq/d7biB84WbqT6h0Wq1JCUlObbz8vIuuF/C3BA2fmkeaq39LdNqsbHt/7Iv2ir8hozBIOeztR0UNYxs9f5iGTcDlJ0TUhwrsm5GhEarYvENiQRH+3Diwwr2vlpAxZlml+fX3b0Mnb/9h2yxWNj2/BF2/vMMOburMPVZkGT7DYqs11GasAGjLoDQzny8/DQXvKZgaHx8fFy6TFVVne92cuv1AnWsuDWF+396BSs2p2AIcK2hLz/dzFu/OckbPztG4bF6UQY3SXAuuRClUgLB1MDldSscN4Jx4uWXX6ahoYHQ0FBWrFgx0cMZM8LTLRBchMSMUJc8hP1vuK7MT0Y8WSoFuJRK9fb20tJy8ZKhqYJzeUZeXt5FxajY9CBu/PJ8NP2r8zarwo6/nqbwWP15+yaH+jDLqbvUe9kjs2e6ZNxcQLixIFHu5LpJEeVSIyY42ofbv5NJ+rIISrOa2PGX07z+06MUHqunp8OETqdj1apVjv0r2/LoaO5l72uF7H+ziMaKTgCq6yUqY9YQ2JpPbO1eVCpZtJoeAzNnziQjI8OxvXv3bo/naem81Cy4Lo77frScax6cSXC0weX5hvJOPvx7Li/+4BDZuyoxG0Wu1EQii6wMgWDKITl1lhKh4tOb4uJiZs+efcF/40llZSWPP/44AE8//fQlA46nCkK4EQguwao70xwui74uMwe3Fg9xxMTiaeHGy8uLkJBBMWs6lEsN1L4CdHR0XHKSGJUawKavDrYKV2wKH/0jl7yD5x/j7Lp5N6tmRO4kV8fNhSeJzuVSQbKVQEl0xRkpKrXM1Q/MYsP/zCVtaQQqtUx7Q48jkDozM9PR7cioaSFsdQdJGSGc2VfD7hfzyN5VycFPu9GZ2omp3oO+0/53MODGEYyO9evXOzq+2Ww2tmzZMi7dIFRqmRnLIrnzySXc+OUMYtIDXZ7vaOpj76uFvPDd/Rx+p4SeDiGYTgTOGTei5EIgmBrIWifHjVG8d7qNie4i5aGuUmOlu7ubzZs309TUxM0338yjjz460UNyC0K4EQgugW+QnsU3JDq2z+yrobZ46JbQE4VLxo0HhBuYfjk3Pj4+xMYOhlHn5+dfcv+IRH9uenwBeoO9JEZR4OMXzpK7t9plP+ecm+LGbvLqOoc9JtMQpVIA7YqKRtugMydFLW6ERktMehCr70zlhi9lkHF1HDov+89fo9GwevVq+04KZGWfZMnt0ay9L53mmm72v1FEZ7uF0MZThDbnoPT1YbVc3I0hnDjDQ6/Xc/PNNzu2Gxsb+eSTT8bt+pIkETc7mJseX8Ad311M6uJwFzHO2G3h2LYy/v3dA+z6bx6tdVMjvH664NqdRpRKCQRTAZFxc/mQnJxMbm7uBf+NB2azmdtvv51jx46xcuVKXnrppXG57njgceHGarXy7LPPsnz5chISEsjMzOT+++/nN7/5Dbt376atrc3TQxAIxkTG1bEERQ0KInteysM6SbMOPO24gekn3MD55VJDERrny81fX4CX3+CNyO4X88n6pNKxHRvkzfzYAMf2SMqlhiPcABQ7tQaPlc1omZx/l1MBWSWj9VKj0alcHl+wYAEBAQEggc1qY/fu3cxcEcXyW5Kx2RSQoNM3jubAmShISBa7M+RCDquByX9TVRdnD9Rw+tNqzuyvEdkpFyApKYmlS5c6tg8ePEhZWdm4jyM0zpfrHpnNZ55ZRsbaWNROfx9Wi40z+2p46YeH2fZ/2dQWtY37+C5HXMKJRamUQDAlEBk3gvHAZrPxwAMPsH37dubPn8+7776Ll5fXRA/LbXhcuHnyySf5zne+w+HDh6moqODEiRP897//5Rvf+AZXX301wcHBJCYmsnnzZp555hlPD0cgGDEqlcxV98xwbDdXd5P9yeQULJyFG2uP54Wburo6TNPgA3jGjMHfb319Pa2trUMeExztwy1fX+ASaLrvtUJOfDDYmeqGec7lUrXDLpcyXrKr1CBVNg19/Sn+KsneYUrgXtRqNVdddZV9Q4Ls7GyKcis5vqOcgDBvZi0Npd0vkTMzH6Asfj2d9R32XaVBh8bA772ltpsj75bw6o+P8Ml/8tjzcj67/pvHS08dpqawbZy/s8nPNddc41KauXXrVvomyGHhF+zFyjtSeeAnK1h2cxLeTqItCpRmNbHllyd48xfHKD7ZYBf1BB5BlEoJBFMPkXHjGSa6i9Rk6yr15S9/mZdffpm0tDQ++OAD+8LbNMLjws2LL76IRqPhrbfewmg00tDQwMcff8yvfvUr7rvvPubOnUtNTQ1vvfUWTz31lKeHIxCMisiUAGZdMTgJP/JeKZ0tk8+iPR6Om7CwMDSagTIhxePBoeNBSEiIywRxOK4bgMAIA7d8YyG+wYMTiYNbiznyXimKonDDvCgG5u8VLT3kVA+vzM45nPhiGTcAChKlLq3BTUyqIuNpwty5cwkODrZvKLDr5dP0dZmZszqaq+5NZ+nRH6E1dVCasJ7dr5VSXTAo/NlsCpIk0VLTzf43Cjm+vRyVWmbh9fFc98hsFl4fj9VqY/ufc6jMm/ph3+5Eo9Fwyy23IMv2W5X29nZ27NgxoWPSGzQsWpfA/T9ewZr70gmM8HZ5vq6kgx1/Oc1LPzhE1seVGHuEmOpuXCaAwnEjEEwJXEqlRMaNwAM8+eSTPPfcc8TFxfHRRx8RFhY20UNyO+qhdxkbbW1trFu3jk2bNgH2CdKaNWtYs2aNYx+z2Uxubi5ZWVmeHo5AMGqW35JCSVYTfV1mLEYre18tYMP/zJvoYbngKtz0eOYaskx0dLSjbKGqqor4+HiPXGs8SU9PZ9++fYA952b58uXDOs4/1ItbvrGQt39zkvbGXgCOvleK2WhlxeZkFscHcaTMPiF/N6uGeTEBlz6hBEa1U6mUzYqMDZt0YZ29zKZhJvbJi79sI0C20aaoLrjvhZgECyQe57plT4/5HMERCjPmg74nCmOnltqOOv7f9w9islr4dU8DS4/9hMLkW6jgaj765lZ+8/oDqNUysixhsynseTmfmqI2olMDmHNlDCmL7DcUqZnhhMT48OE/cinPaSY2PWjMY51OREdHs3r1anbv3g3AqVOnSE9PdylvnAhUGplZV0Qxc3kk5bnNnPywwsU11d7Yy77XCzn0VjGpS8KZszqasHi/i59QMGxknZPjxjj5FlAEAsH5uIYTC8FV4F5+85vf8OMf/5iIiAh27txJXFzcRA/JI3hcuMnIyBiyPECj0TB//nzmz5/v6eEIBKNG76NhxeYUPvn3WcBujS/NbiJxXsgQR44fLsJNj2eEG7CXSw0IN5WVlZfeeYrgLNyUl5fT09ODt7f3EEfZ8Q3Sc8v/2sWb1jr7z/3URxX0dpq4YW6EQ7h5P7uWJ9bPRB6i65Bzxg2AxmrFqL6wcNOlqGiyqQiR7c6cBJWJU5bpU887WWiuA3OrDyHGZCzqLsz+NZj6y9hMkgYvxURq8Va2d6hpUPmh0Q6KZ/teK6SmqI2gSAPLbk4mLN7eqcpqtqHSyKQsDOPAm0WUZjeRuT4BvY9mQr7HycqqVasoKCigpsaeE/XOO+8QExODj4/PBI/MnluUMDeEhLkh1Jd1cPLDCkpONjBw22Mx2zi7v5az+2sJS/BjzupoUjPDUGuHL64KXJH0TuHEYgIoEEwJRMaNB5hknZwAt43n/fffd4lQGYhlWLZsmeOx733ve2zcuJFTp07xjW98A4DExER+/OMfX/Ccn/3sZ1m5cqV7BjhBeFy4eeyxx/j85z9PQ0PDtLQsCS4v0pdHkHew1rGyuveVAmJmBJ4XaDpRyIZBoUHp6UGx2ZBk91dEnhtQrCiKS6bHVCQqKgofHx+6urpQFIWCgoIRickGfx03f30h7/z+FM1VXQDkH6ojoi0QLWACatr7OFHRSmbCpV0V5wo3OqsFo/rik/kyq5YQ2e72iZPNZKPHxtT+fUw+JOorJcIjjRi96vE2dOLjL9HVLmFBQkECFCy9bXSq1Y7XRFlOEzl77JlYK25NISLJ33FGlUZGsSnYFAWNXo1KLaHWimaP56JSqdi8eTN//vOfsVgs9PT08O6773LXXXdNqved8AQ/1n1+Dh1NvZz+tJqz+2vp6x4slWoo6+CTsg72v1FI+opI5qyKJiB8eOKwYBARTiwQTD2cSxxFNpVgKBobGzl8+PB5jzs/1tjYCNirewZMIgcPHuTgwYMXPOdVV1015YUbj98h3nXXXWzevJmbbrppWmRhCC5vJEniyrtnOBwTnS19HNtWOsGjGsTZcQOec904CzddXV20t0/eFunDRZZll5DiodqCXwhvPy23fGMhUakBjsfq8lp52GzAq79x0HvZQ78POmfcwKU7SwFU2jRY+lc5dJJCpHzp/QWjo6Kmi3L1UXq97b/DuBT7D92E2iHdaBS780mSJEx9Fva9XgjA4o2JxM8OdjmfYlOQZInG8k5a67qRVTI26+ByldlkxdhrwdQrfp8hISFce+21ju38/HxOnTo1cQO6BH4hXqzYnMIDP1vBNQ/NIiLJtUTK2GMha2clL/7gEO/87iQlpxpFZ7ERIIlSKYFgyuGccWMTGTeCIXjwwQdRFOWS/x588EHALsgMta/z/lOZcVnae+KJJ2hqamLu3Ll885vf5NNPP6XbQ8GpAoGnCYoyMP+6wdrJUx9V0lzdNYEjGuQ84cZDrzMfHx8CAwMd29OxLXhRURFm88iDRXVeam78SgbJC0Idj/l227i7S4efTeL9nFqsQ3ScsUkyZien1KUCigEsSFTbBh05CbK4KfIMEhVFgGT//QWEgl+QgllyCpNm8Hd1ek817Y29hPeXyDijKHbRxmq1t5QGSJwXgtZr0G2Vs7uK9/5wik/+c5ZTOysw9V3eAs7ixYtJSkpybG/fvp22traJG9AQqDUqZiyN4NZvZXLH/1vMrFVRLu3EASrPtrL9zzn858mDHH2/lO52sRI9FKJUSiCYerg45cTr1o1Ik+yfwJN4XLjZtm0b8+fPp6SkhJaWFn71q1+xZs0a/P39mTFjBnfddRc///nP+fDDD2loaPD0cAQCt5C5IcHRSWggeFSZBO1fZa0WNIMTeE8JN3B+udR0IDExEW3/qpDZbKakpGRU51FrVFz3uTnMuXJwsh5sk7m3UwdtJg6XNg95DtMwW4IPUObUXSpCtqBDrOB7gvZmaHdq/hSXqmByEm4GHDc9HSZqitqQVRKzVkbhdU5uzUCJT+WZFqryW/EL1jsCixWbYhdpFHuGSnlOM/vfLOKlpw5TcqrRw9/h5EWWZW666SZ0/RMAk8nEW2+9hc02+f/WQ2N9WXNvOg/+7ApW3ZlGYKSryN7VauTIu6X8+4kD7PjraaryW4fMB7xccQknFqVSAsGUQBLhxALBmPG4cPPd734Xo9HIDTfcwHPPPcfPfvYz7rrrLmbMmEFJSQmvvfYaTzzxBOvXrycqKsrTwxEI3IJGq2L1XWmO7dqidvIOTY5SQJVToK4QbkaGWq0mJSXFsT3ctuAXQpYlVt+VxtJNiY7HfBSJuzp1fLCrfMjjjU7CzVClUgANioqe/hZRsgRxKtGG2DNIVBQOrir5BUJTxGB+mwb770qWJZoqu/D21RIS44PkFEg9MCHvaOql4Eg9XS19pGaG4+1vF98kWUKrV7Pw+nhu+toC7vvxCpbemIhGp2L7X3I4+WHFeHyjkxJ/f382btzo2C4rK7tgHfxkReelZt6aGO7+/hJu+cYCUjLDXMLKbTaF4hMNvP2bk7z8w8NkfSJaip+Lc8ipTZRKCQRTApd24GbhChYIRoPHw4kLCgpYsGABb7/99nnP9fX1kZ2dzalTpzhx4oRoBy6YUiTMDSFpQSglJ+0r4AfeLCZhXghePtohjvQsssGAtT9zZryEm9raWiwWC2q1x99SPE56ejpnzpwB7O9fNpsNeZQBz5IkkbkhEW8/HbtezAMF9Eioj7VRsKCetEXhFz3WOedmOI4bkCizapmltq9kJcomCq1ahHXV/XS2SrQ2KgT2V8NVzUlmQXW+S8ZNa1033e1GolICXNpAD+TaWExWCo7UUXqqkYhkfxLnh6LVq8/bT5YkvP20ZG5IJDzJn4//eYasjyuISg0gPPHybC89d+5c8vLyHK/TnTt3kpycPKUaIEiSRFRqIFGpgXS3Gzm7v5bcvdV0tQ6uRLfW9bDvNXtL8bTF4cy5MobQON8JHPXkQNY7r9yLCaBAMBVwDicWGTduRBgzLys87riJiIhwCfx0Rq/Xs2TJEj7/+c/z5z//+aIp0ALBZGXVHamOjlJ93WYObCme4BGd0xLcg8JNeHg4qn5xwWq1UldX57FrjSepqakOoaa7u9stbqJZK6O46uFZWPo/YdVIfPS3XHJ2X/zcI3XcAJQ75dz4yzYCpMlfQjJVqXRy3fQG+lIdYy+LG8i48fKz36QOdIlSFAVbvxgDkHewltN7qtH7aJi9KprwBFcRZmA/SZYcZZix6UFkbkyku8NE/mH7620ylGiON5IksXHjRkc7cKvVytatW7FYpmYGkMFfR+aGBO778Qo2/M9c4ma7dp2zmGyc2V/Laz85yhs/P8bZA7WYTZfOvZrOuIQT9wnHjUAwFRAZNwLB2PG4cHPrrbdy5MgRUastmJb4BOpZcuNgKUzegVrKcpomcETjJ9yo1WqX8sbpUi7l5eVFfHy8Y3tgVX+szF4cQdlcA33S4Hvhp68U8OmrBRfsKDPSjBuALkVFk23QqZOoEqtanqKrQ6K5fnA7a14GVllGo9h/V34hXsSmB1Jf2kFFbjOSJDlKYvIP1bJ/SzHGHgvzr4kjYV4IwEU/J53LrGSV/eueDtN5z11OGAwGNm3a5Niura1l586dEziisSPLEokZodz45fl85pllLLg2Dp3B1cVYX9rBJ/8+ywvf2c/e1wpoqb38Gj24rtyLCaBAMBVwKZUSr1uBYFR4XLh58sknsdls/OhHP/L0pQSCCWHemhhCYn0c25/8J4/ezombMMvOGTceagc+QHT0YPhuTU2NR681nsyaNcvxdW5urtvCT69bHc9LPkY6nJwwObuqeP9P2RjPaflskp0dN8NfXS91CimOl02ohY/WY1QWSgxoLV1+vhSmpTpKpWRZInVxBOY+K3tfK+TQ28XkHarlw3/ksvOFs1hMVpZvTmbmFZHo+jtJDQQWX4q+rsG8E4v58nVdAKSlpbFo0SLH9qFDh8aUSzWZ8A/1ZsWtKTz4syu45sGZ55XFGXssZH9Sxcs/PMxbvz5B4bF6rJbLw2En653bgYsJoEAwFXAJJzaJRSW3oUyyfwKP4nHh5uabbyYjI4OnnnqKu+++m7Nnz3r6kgLBuCKrZK55aBYqtf3l1NthYtd/8ybMZebquPGscOPsuJluws3AJLqzs5OKCveEwa6dGYbVV81/fY3UqQYnWRVnWnjzF8fpaOp1POaccTPcUimASpsGU/+fnkaCWFkEm3qKni6JOqc/jdzZs1HpBsWXmSsiWf8/c7GabRzfUc7HL5yl8Fg90akBrPlMOvPWxLrk2lwKU5+F0uwmTnxgD7ZOnBeMWqO67N2s69atc8m2eeutt2htbZ3AEbkXtUbFjGWR3PZte0vx2aujHeW5A1QXtPHh33P517f3s/fVAhorOqf134XoTiMQTD2cHTc2EU4sEIwKjyeJ7tmzx/H1q6++ymuvvUZycjKLFy9m/vz5LFiwgAULFhAcHOzpoQgEHiM4yofltySz7/VCAEqzmjh7oJZZV4x/p7TxdNw4CzdNTU309fWhd1oNnaoYDAaSkpIoLrZnFuXk5JCQkDDm8+rUKm7KiOKFg+W87GPkXgyEtdsFnNbabl7/2TEiJAN16m6XUqmROG6sSJRbtaSq7TdGySojpTYNIqTYM1QWSURFmlG0aiwaDb2zI8BpfSJhbgjRMwIpz2m2l0pJED87GJWmP/tmIKNGsjtuFEVxiIaKTaGnw0RjZSdn9tVQV9KOsddC8oIwZiyLtB82DJfOdEaj0XDHHXfwl7/8BbPZTF9fH2+88QYPPfTQtAhLdyY01per7pnBis3JFByp5/SeapqruxzP93Wbyd5VRfauKoKjfUhfHkHakgi8/SY2MN/duJRKmYRwIxBMBSTtYAafCBUXCEaHx+9qSktLOXXqFFlZWZw6dYpTp05RVFREUVERL7/8suOmMzo6+qLdpwSCqcC8NTGU5TRRlWdf7d37WiHRaQH4h3oPcaR7kQ3j0w4cICgoCJ1Oh7F/1bO2tpbExMQhjpoazJ071yHcnDlzhg0bNjjCmMfC7ZmxvHCwHIsELyjd/PnKZIr32N1KfV1mbiKJ3d5Vo8q4GaDYpiUV+41RoGwjSLLSokyvSexkwWKW0J9poHe+XcTsjQ/Gp8bV7aDRqkhZ5NrxyGa1Iavk8zJq2ht76WjqpaG8k6q8Vlpqux2llwY/LXOvimHJDfbXmLPIczkTEhLCjTfeyJYtWwCorq5m586drFu3boJH5hm0ejVzVkcze1UU9aUd5H5aTeHxBqzmQRdfc3UX+98o4sCWYuLnBJO+PIKEuSEOZ+hUxiXktE8INwLBVMAl40aUSrkPRdwDXE54/E4+Pj6e+Ph4brrpJsdjHR0dDiFn4P/c3Fzee+89Tw9HIPAYkixx9QOzeOWZwxh7LFiMVnb+8wy3fGMhsmr8bpZdSqU87LiRZZmoqChKS0sBe7nUdBFu0tPTUalUWK1Went7KS4uJi0tbcznnR3lR3qEL3l1nSBBThBsemgWn/znLDaLggqZq3viMIWsRKkqRkIZUakUQKeiotGmIlS2O3WSVSZaLEK48RRSeTv+8d60BwYAkDhTGbKN/MB7QkN5BzWFbTRXdVFT3O5SLidLEgER3kSl+BOTHkTszED8QrzszhynDlUCmDdvHuXl5Rw/fhyw593Ex8czc+bMCR6Z55AkiYgkfyKS/Fl5ZxpFx+rJO1hHXUm7Yx/FplCW3URZdhN6g4bUxeGkL48gNM53yop+ksi4EQimHC6CqxBuBIJRMSF38n5+fqxatYpVq1Y5HrNardMmVFBw+eITqOPKe2bw4d9zAagr6eDEB+Vkbhg/MWM8S6WA84Sb6YJeryctLc2Ry3X69Gm3CDeSJHHbohh+9L79vG8er+br35mBX7Ce7X/JobfTnkkjBSzm9Gw1s87+e8TCDUCxVUuobBcBYmUzp7Bh9nys2WWJRVGx9MQJdl29FgDfAMjKymLBggWXPK78dDN7Xsqns7UPSZLwDdIRnRZIUKSB4GgDoXG++IV4ofNSO0SagewSIdqcz7p166iqqqK+3t7u6+233yYiIoLAwMAJHpnn0Xmpmb0qmtmrommr7yHvYC35h+voah0UNvq6zeTsriJndxVBUQbSl0eStiQcg7/uEmeefLhkZYgJoEAwJRCOG4Fg7Eyau3iVSsXs2bMnehgCwZhJzQwnbWm4Y/voe2U0lHeM2/VdhBsPl0rB9A0oBpgzZ47j67y8PExuutm4eUE06v6Jd11HH/uLmohMCeC2b2fSLA86LhpDF3BiwdfQMvLcoGqbhr5+C61KggSVCCn2FGZJRVhjI7FOIdY7d+6kr6/vkscFRxvw8tU4vl60PoGbv7aA1XelMXtVNGHxfugNGpdjpqpLYjzQaDTcfvvtaPsnCH19fbz++utYLCMXPqcyAeHeLLs5mft+vIJNX51P2pJw1BrX272Wmm4OvFnEC08c4L0/ZVF0TqnVZMZ55R6zGWUEGWACgWBiEO3APYOiTK5/As/iVuGmrKyMDz74gFdeeYVXXnmFDz74gLKyMndeQiCYEqy+awY+QfabS5tN4aPnz2A2jc/NpTQBjpsBWltb6RmHa44XaWlpjkmgyWSisLDQLecN8dGxJn0w8+T141UA+IV4scWviHL1oNDX6RuHOvJ2Qi1eI7qGDcmlNXiybEL0avQMZuzZRxmnspAs9td5d3c3n3766SWP8wnUc/sTi1lwbRxNVV0c21ZG1ieV9HQMCoSKIkqiRsJA3s0ANTU1fPTRRxM4oolDliViZwZx7cOzefAXK1nzmXQiU/xd9lFsCuU5zXzwt9P889v7+PTlfOrLOiZ1VypJ5+oQEpNAgWDy49pVSiwkCQSjwS3CzYsvvkh6ejrJycmsX7+ee+65h3vuuYf169eTnJxMeno6L730kjsuJRBMCXReaq55cJajkU9bfQ8H3iwal2urxjHjBiAgIAAvr0FRoba21uPXHC80Gg3p6emO7ZycHLed+7ZFMY6vP8ito73HfiNjlmxs8ymlq+fM4M5qH27uTCHJ5H/uaS5JqVXrWAHxlW2ESmJl2hOYJbtwY+jpITq/zPH4oUOHaGpqGvL4FZtTuOnxBSg2hX2vF3JgSxH1pXbxTjhsRs7cuXNZtGiRY/vw4cOOksfLFZ2Xmlkro9j8v4u494fLyNyQgE+gqwBi7LGQs6eaN352jJefPsKJD8vpbp98ooikc3Ug2oRwIxBMeiTtOU4529Rw+AkEk4kxCzd/+tOfePDBB7n66qv5+OOPqampobe3l97eXmpra/nkk0+45ppreOihh3juuefcMWaBYEoQnRbIgmviHNun91RTfrrZ49cdb8eNJEnTulxq7ty5jq8LCwuHLH8ZLmvTwwg29Lt5LDbezbb/3BQJbDI09p1kRsHLSIpdbNEg46WoUSSG/a9Lkqkb6CalQIpsOW8fJuLfNGNAuAGIyyumr7/azWaz8cEHHwzrHDEzArnvxyuYsSSC/MN17H4pj5zdVVjMQmwbDevWrSM8fLBk9a233qK1tXUCRzR5CAj3ZummJO7/8Qpuenw+M5ZGnFdK1VrbzcEtxbzwnf2898csCo/VT5q/RVnn2t5c5GUIBJMf53bgAIpw3bgHZZL9E3iUMQs3v/rVr/jZz37Gn/70J6666ioiIiLQ6XTodDrCw8O58sor+eMf/8iPf/xjnn32WXeMWSCYMizdlERwjI9j+5N/n6W3y7M3meOdcQMQHR3t+Lq6unpcrjleJCUlORxFVqvVbSv3GpXMTfMHf24D5VIDGFVqomv2kZH9JyRrL9m6Rk7rRy78FfeXS3l3x5HWE8UMky+S+HB1KwOlUgB6q5nyvEF1qrCwkIKCgmGdR5YlrnloFtd/dg6tdT18+mqBI6x6LNisl9/Kpkaj4Y477nCUOhqNRt58802sIg/FgSRLxKQHcc1Ds3joFytZc186UakBLvsoij1E+8O/5/Kvb+9nz0v51JdOcCmVWg1OHdtEqZRAMPmRtecIruJ1KxCMmDELN3V1dSxcuHDI/RYuXOjo9CAQXC6oNDLXPjQLldr+UuvpMLH7v/kevemVvce3VAqmd0DxucHpp0+fdtu5b88cLJfKqmyjsL7TsW1S2cWAoNZ8wgr+yj7v0f1caxU1JrM3WmMg3j0xXNUVz02dyYRbvIc+WDAszNJgg0aNYqW5HhISEhyP7dixY0QBuSmLwnjwp1dw7cOz8A3Sj+n9oqfDxH+ePMiJD8snjWNivAgODnbJu6mqqmLXrl0TOKLJi9ZLzawrorjlGwv5zDPLyNyYgG+Qa0mSscfC6U+reePnx3j5h4c58UE5nS3ucSCOBEmSXHJuxARQIJj8SOcKN8IpJxCMmDELN4sWLeI3v/kNxkt8cBqNRn7729+SmZk51ssJBFOO4Ggflt2c5NguOdVI3sE6j11PNriWSo3HyqizcNPR0UFXV5fHrzmeOHeXKikpodtNTqaZkX7MjvJzbL/h5LoxqQbFAO++ZpRRlhgpSBRIVrp8S+n2LcWq7ibKYuDWjhQW9IaOeuyCQUxOjhsNVkBi/fr1jnyalpYWDh06NKJz6n00pC2OAMaWc3P0vVK6Wo0c3FLMi98/RN6hWmy2y8dyNXfuXJe27Pv27aO4uHgCRzT58Q/1ZumNSdz3o+Xc/LUFpC+LQK09p5SqroeDW4v593cP8OYvjpH1cSXdbeMnoDh3lrL1CeFGIJjsCOHGA4ykdn48/wk8hnroXS7NH/7wB6677jri4+PZsGED6enpBAQEANDe3k5eXh7btm3DZrNdtp0dBIKMtbGUn26mKs+esbD3tQKi0wLwCxlZp6Dh4Oy4wWJBMZnO68Lhbvz8/PDx8XEINjU1NaSlpXn0muNJXFwcfn5+dHTYSwRyc3NZsmSJW859+6IYcmvsQcRbTlajKCBJg44bAK11DO2MFSixaZml6cCi7cCsaUfTMh8JaFWJCY87cM640fRnEoWHh5OZmcnRo0cB+PTTT8nIyMDX13fcxmXqs1B0vMGx3dVq5ON/neXUR5Us35xM3KygyyL8eP369VRWVjqCords2cL//M//4OPjM8SRlzeSLBE9I5DoGYGsuiuN4hON5B2spaawzWW/upIO6ko62PdGIVEpAaQsCiN5YRjeftoLn9gdY3N23JjE+5hAMNmR1GpQqaC/XFUINwLByBmz42b+/PmcOXOGxx57jMLCQn71q1/xpS99iS996Uv88pe/pKCggMcee4zc3FzmzZvnjjELBFMOSZa4+oGZ6LztWqm5z8rOf57xyMq3s+MGRLmUO5Bl2WPlUpvmR6NR2SfPjZ1GbNiFN6OT42ZMwo0ERkWmWlGDIuHbkYoEHNc3UKbtGPJwwdA4Z9xosTLQymvNmjWOfCSTycTOnTvHdVxavZp7f7iMjKtjkVWDAk1zdRfv/SGLd353isaKzkucYXqg1Wq57bbbUPWLod3d3WzduhWb6GoybLR6NTNXRHLLNxZy34+Ws/iGRALCzym3VKCmsI1PXyngX9/ex1u/OUnu3mqP5LqJUimBYOrh0hJcCDduQVIm1z+BZ3FLO/CQkBC+973vsXfvXurr6zGZTJhMJurr69m7dy9PPvkkISEh7riUQDBl8QnUc+XdMxzbtcXtnPyw3O3Xkb1cXTy27vERbpwDiqebcAOu3aUqKipoa2tzy3mDDFqumTnY/cai2EunnEuldGMRbrA7V4utOnw6klFZDFg0HeSMMjNHcD7OjhsYKJcCb29v1q5d63g8KyuLqirXEGpPo/fRsPL2VO794TJSF4e7PFeV18prPznKB38/TUvN+ASZTxQRERFcf/31ju3i4mIOHjw4gSOauviFeLHkhkTueWopd/y/xSy8Ph6/ENc8HEWB6vxWdr+Yzz+/tZ93f3+KswdqMPa4p5OMc2cp0Q5cIJgaOAs3ilEINwLBSHGLcCMQCIZH6uJwl8nTkXdK3b7iLalUSE7izXh1lnJ23FRXV09s1xEPEBkZSVBQkGM7NzfXbee+bdFgSLEVHxRFdhFutGPohDOwAuLXF4y+NxJQ6PDPJ0llEqsjbuI84UYZ/H0tWrTIpS31QOnweOMX4sV1j8zm9icyiZ4R6PJc0bEGXn7mMB/8/TTNNdMrn8qZxYsXk56e7tj++OOPx11Im05IkkRorC/Lb0nmM88s57bvZDL/mlh8Al1LcxWbQsWZFj75dx7Pf3Mf7/8pi/zDdZh6Ry9IS7pBoUg4bgSCqYFzZynFLIQbgWCkuEW4ycnJ4dFHH+X66693lEWdy6lTp0hKSrrA0QLB5cWVd6c5bmxtNoWPns/FbHJvtxeXluA94y/cdHd309ExvcpwJElycd3k5OS47dxXpoUS4jMw2ZGw4Hd+xs0ohDBJsbttfKwa1nTHAtDpX4BN3UeSZEISyo1bcC6VgkHHDdjL7NavX+/Yrqmp4dSpU+M1tPMIi/fjpsfnc8OXMwiOdsrDUuwCzivPHGHHX0/TVDX9BBxJkti0aRN+fnZXm81m44033qC3t3eCRzb1kSSJ8AQ/rrgtlft/vILN31zEvDUxePu75tzYrAplOc3s/OcZnv/mPrb/OYfCo/WY+kYm4ohSKYFg6uHiuBGlUu5BmWT/BB5lzMLN/v37Wbx4Mfv27SMwMJAdO3awYMECnnnmGZf9jEYj5eXuLwsRCKYaOm8NVz84C/ojJ1rretj7aoFbr+Ei3IxTqZTBYMDf39+xXVlZOS7XHU+cu0vV1dVRX1/vlvOqVTKbFw6WmlkUf/qcHDcyoLGNUNxTBsP913bHokGmQNtCj94eVquXFGJl95QtXO5YkbExmCGjVVx/VwkJCS4ZSR999JHbOpONBkmSiJ8dzB3/bwnXPTKbwAinrBIFik808OqPjvD+c9nUl04vAdbb25tbb73VEcrc1tbGli1bRN6NG5Fkichkf1bdmcYDP72Cm7++gDmro/Hy1bjsZ7XYKDnVyIf/yOWf39zHjr/mUHS8YVgLGS6lUqKrlEAwJXAtlRKvW4FgpIxZuPnud7/L5s2bycnJ4ZVXXqGwsJBnn32Wn/70p9x9992XbBMuEFyuxMwIZP41cY7ts/tryT/svhbhLsJN7/gINwDx8fGOr6djy93Q0FAXZ9HJkyfddu47MmMdXyvo6Fb5uTw/7HKpc1Y8MnvDibH40CGb+MRQRYVNY99Hghmy8fwDBCNHkjA7fZyqOf93dd1116HR2Ceuvb297NixY9yGdzFkWSJ1cTh3fX8p1312NoGRBpfny7KbeOPnx3jn96fO6yQ0lYmPj2fNmjWO7cLCQvbs2TOBI5q+yLJEdFogV94zgwd/dgWbvjqfWVdEojO4NjW1mG0Un2jkg7+d5vn/3csHfz9NyclGLBcRcSStc1cpsXIvEEwFXIQbs1g4EghGypiFm6ysLB5++GHH6pUsy3z1q19l165d7N69m7Vr1zpacAoEgkGW3ZREeOLg5Hz3S/m01rlnFd5ZuFHGqasUQEpKiuProqKiaZdzA7Bw4ULH11lZWZjddPOREubDFSnBju0elWug+5CdpQZ+1BLIigQSRJkNLOm156t86FOOTYICi87h9gqQbIR6jS34WGDnQi3BnfH39+eaa65xbOfk5FBQ4F6n3WiRZYnUzHDu/t4Srv/cHIJjXNtkV55pYeuvTrD1VyeoPNsyLV7XK1euZMaMwbD4PXv2kJeXN4Ejmv7IKpnYmUGsuW8mD/1iJTd8OYP0FZGObosDWEw2io41sP0vOTz/zX189HwupVmNWM2DrijRDlwgmHqIUikPoEiT65/Ao4xZuPH29qar6/xa+KVLl3Lw4EHa2tpYtmwZZ8+eHeulBIJphUotc90jsx03rRajlQ/+lnvRFcaR4NxZyjaO+Q3JycmOrzs7O2loaBi3a48Xc+bMcXFOuHOyd9+yBMfXZsmPJp2vY3sox02UxcDSnggCrDpskoJakbi6P9fmoFctDepeUKBdUlFt7Z8oSTDDR2KWKpS1mkSu0MSxSB1JkDT49yM+hoeHmcHJp+YCjhuwh+PGxAwGUb/33nuTypUqyRIpi8K48/8tZuMX5xGW4Or6qils453fneLNXxynLLtpSgs4sixzyy23EBw8KJZu2bKFxsbGCRzV5YNKJRM/O5ir77eLOBsfm8eMpRFo9K55UWajlYIj9Wz7vxye/+ZePvpnLsUnGrBqnT7jJtFrSCAQXBxJM1guKRw3AsHIGbNws3DhQt5+++0LPpeQkMCBAweIi4vjs5/97FgvJRBMO/xCvFh7/0zHdnN1F3tfKxzzeWXD+GfcgD3nxrmUqKioaNyuPV7o9XqXvJITJ0647dzXzAxDYuBmRmJb4nLHc5dy3EgKJJj9WNQXxnVd8cSYfbiyOwZfm5ZKdRcnvZwmowrk23SgyGj7QojvmUWmOooI2YcY2Y/ZqjA2aFPJUIUP7C4YBq6Omwv/rmRZZtOmTciy/aO3o6ODjz/+eFzGNxIkSSJhXgi3fXsRm746n6jUAJfn60s7eP+5bF798VGKjjeg2KbmX4ler+euu+5C278KbDKZeOWVV+jr65vgkV1eqNQyCXNDuOahWTz87ErWPzqX1MXhaHSuIo6pz0rB4Xp2/PU02zrXkjX3UaojV9DbLfKJBIKpgLPjxiYcNwLBiBmzcHP//fdTUFBAa2vrBZ/39/fngw8+4MEHHyQuLu6C+wgElzNJ80OZt3ZwFf7MvhryDtaO6ZyuXaXGT7iB88ulpiPO5VKlpaW0tLS45bxqlYxaands70hYhkWyv01fSrhRJDjgXUuOrpkQq55NnUnMMAVikmy851sCDJZPIUGTosLSE4lPZyKyoqZRV802UyFbjGfYay6nwdZNhjqCTHUUsvDcDAvnzlIa5eITybCwMFatWuXYPnLkCBUVFR4d22iRJInYmUHc8o2F3PKNBcTOCnJ5vrmqiw/+dpqXnz5M/uE6bNapN4EODQ3llltucWw3NzezdetWEVY8Qag1KpLmh3LdI7N5+NmVrPvCHFIWhaHWut6u2lDRHDyX/Bn38m7xTN78xTFOfFDutnJjgUDgfiStk+NGCDfuYaK7SImuUuPKmIWbO+64g/379xMYGHjRfTQaDX//+98pLS0d6+UEgmnJis0pLmUJu1/Kp6mqc9Tnk1zCice31a2zcFNRUYFpGn44x8bGEhIymEHjzpBiNe0MfPq16v04GGnvZKUbRlepvYZqtvmUYZTs+7bJRgw2+42STVIcH6qRZh90veHIVj022YzsV4VJ1Y0ZG6W2Ng5ZqmhReklUBeAjaS92OYETLo4bLp0btGrVKkJDQx3b77zzDhbL5M4aikoNZNNX5nPbtzNJmOeav9Ra18POf57hxacOc2Z/DVbL1BI9Zs6cyerVqx3b+fn57N27dwJHJABQa1UkLwjj+s/N4eFnV3H95+aQtiT8vEwckKgr6eDg1mJeeuowL/7gEAe2FFFb3D5l3WACwXRE0ohwYoFgLIxZuBEIBGNHpZZZ9/k56A32SbbVbGP7X05j7BndB5vs5ey4Gd8VyOjoaHT9wZFWq5WysrJxvf54IEmSi+vm1KlTWIfb9WnIc1tRMSjavZe4AhhGOHE/ZdoO/uufR4WmkzCrF5s7U5jd1++UkOxlVbFmHwIsBsyqXlQWLwJbFjDPR+84R4di5Ky1CS80RMg+F7mSwBlXx82l/xbUajWbNm1ybDc1NU0ZoSA80Y+NX5zHnU8uJmVRmEsIUkdjL7v+k8d/v3eQnN1VbsnrGi+uuuoqUlNTHdu7du0iPz9/AkckcEajU5GyKIxrH57NQ8+u5MrYYmKqdqPrO9/t2Fbfw8kPK9jy7HH++Z397PrPWcqym7CYp87fo0AwHXF13AjhRiAYKR4Vbk6ePMnTTz/NbbfdxuLFi0lPTyc9PZ3Fixdz22238fTTT7t1pVogmMr4Bum59pFZjolQR2MvH79wdlQBoBNZKqVSqUhKSnJsT9dyqYyMDEdWSWdnp1u/T7XU5vg6OzSFct/w4bcDB4yylfd8SznoVYuPTcMMUxB+VvtKlyJBnNmXbtnMKUMlXb4lINlI65vFIk244xzmIcQHgSuujpuhf3axsbEsWbLEsb13794pFeYdEuPL9Z+bw93fX8qMpRFI8qCC09Vq5NNXCvjPkwc5+VEFZuPk/1uSZZnNmzcTFDRYDrZlyxaam5sncFSCC6FSyUQEWUgrep0Vh77HVd77WbwxgZDY80Xm3g4TZ/bX8v5z2fzjf/ex/S855B+qpa9bTBoFgvFGFl2l3M9El0aJUqlxxSPCTVlZGWvXriUzM5Mf/vCHbNmyhePHj1NQUEBBQQHHjx9ny5YtPPXUU2RmZnL11VdPy1V5gWCkxM0KZskNiY7t0qwmTn448vwLl3bg41wqBZdHzo3BYCA9Pd2x7c6QYpk+JAYDUt9LXDFsx40zJ70aec2vgBP6Brpk+0TFz6ol0KqnR7JwXN1Lm66WTr9CTLoWZqsiWK9NRQICZXvXlr6LBO0KXBmqHfiFuPrqq/H39wfAZrPx9ttvT7lslaBIA9c8NIt7f7iUWSujkFWDAk5Ph4kDbxbx7+8e4Nj2Moy9k/tvycvLi7vuusvRNc5oNPLKK69Mqs5fAjuS1u7qlAB/SxNLbkzizv+3hPt+tJyVd6QSPSPQRUwEe+fGkpON7PzXWZ7/5j7e+vUJsj6upKNp/D8jBYLLEZd24KJUSiAYMecWCo+Zmpoali1bRkNDA/PmzeO2225j4cKFxMTEYDAYAOju7qaqqooTJ07w+uuvs2vXLpYvX87x48ddOtIIBJcjmesTqCvpoCLXvtJ76K1iwhP8iJ5x8Rypc3Fx3IxjV6kBnIWblpYWWlpaXFaypwsLFy7kzJkzABQUFNDZ2Ymvr+8QRw2BBJIEGlsbJiUCgI9jF7G6/pNR9eZu0vTR5CQCdanMGOUBYUGmrF1LenAbVnUv2q5IgnqiuUc3DxUSPZhptrn/70eZhnnHFlwdN+tnPjGs4/wjZNKvtAsF1dXVPHzz96kvHLlDZfvZn474GHfiH+rNms+kk7khgZMfVXBmXw1Ws12E6us2c/jtEk5+WMG8NTFkrI1F76MZ4owTQ1hYGLfccguvvfYaAI2Njbz11lvccccdSNI0/MOdorhMAJ2ENb8QLzLWxpKxNpa+bjPlp5spzWqkPLcFi5PzS7EpVBe0UV3Qxr7XCwmO9iExI4Sk+aGExPqI37VA4AFc2oELx41AMGLc7rj53ve+R0NDA7/+9a85deoUTz75JBs2bGDevHkkJyeTnJzMvHnz2LBhA08++SRZWVn88pe/pL6+nu9///vuHo5AMOWQZIlrH56Fb5A9c0RR4IO/n6a7bfirvrK3l+Pr8S6VAns3Oefw1enquklKSnI4JhRF4dSpU247t0rqRG+xCy69Gj11Xm4QtRV7SHG1potgq54IizcVXVrMNrCpjPT5lVOoLqVJsf/NnLY00M2lV8UGpjfqyzwybTSOG4D2OhtNZYP7x85VofW+xAGTHN8gPavvTOO+Hy1n/rVxqJ1aOpt6LRzbVsYL/+8An75aQFv9+L83DYdZs2axcuVKx/bZs2fZt2/fBI5IcC6Szrmt8IU/G/UGDTOWRrDu83N55Jcr2fjYPGatisLL7/zA9ebqLo5tK+O1nxzl3989wKcv51N5tgXrFOyUJhBMVlzCiYVwM3YmuixKlEuNO26/096xYwdLly7l8ccfH/YxX//611m6dCnbt29393AEgimJ3qBh3RfmIKvt0+LeTjMf/O30sG8i5QnsKjXA5VAuJcsyCxYscGyfOHHCbaUukqQwvynPsV3qm8Qo4o4uSL62FbNkY21XLOGSHxWd/TdTkoIhsJYsSy3HLDXkWZscx3hzvkNCwv4ZHSJ5c7duLtHyGN1GUxgTI8u4cab8lAWz0f7LVWkkEha53Qw77hj8dVxxawr3/3g5mRsS0OoHfz4Wo5WcXVW8+NQh3v9TFpV5LaPK8vIka9euJTk52bH98ccfU1hYOIEjEjgj9wfgAyjGoSeAao2KhLkhrLk3nYd+dgW3fmsRC6+PJzDifJW0q9VIzp5q3vndKZ7/333s+OtpzuyvoatVlMwJBGNBlEoJBGPD7cJNS0sLCQkJIz4uPj6elpbzuwMIBJcrYfF+rL4zzbFdW9zOwa3Fwzp2IsOJB3AWbkpLSyd9u+PR4izctLa2Ul5e7rZzZzSddXzdofXDhtcl9h4G/faYKm0Xx7zq8bNpWaKOwasrFsVqn1h7qRVkr1bOWBsdh/lLOhZropmvjnARcAam2ldo4pAAw2XcOny0jhsAixHKTw6+PgKjVARGTw8Hk5ePlqWbkrj/JytYuinJ0TkPAAXKcpp557eneOWZI5zZVzNpOlHJssytt95KQECA47E333xT3KdMEiRn4WaEK/eSLBGR5M/yW5K556ll3PvDZSzfnExksv955aimXgvFJxrY9Z88XnhiP688c5gDbxZRldfiKAUUCATDQ5RKCQRjw+13hnFxcezdu5eeEUwWe3p62Lt3L7Gxse4ejkAwpZm1Mor0ZRGO7aydlRQdH7rzzGQQbuLi4lCr7c4Bs9lMZWXlhIzD0/j7+7uIVO4MKfaxdLGoftB1Y7EFuO3c2V5NvONbgoLCbDmSwKbFeHfGozb7kOxnwtnv2qtY0Etq5qnCWaKJdmkRfoU6Fn9Jx1lrIwXWy7cDj3kMjhuA5nIb7XWDE8H4hWrkqW+8caDz1pC5IYH7f7KCK++ZcZ7ToaWmm13/zeOFJw5w6O3iEZWGegpvb2+XsOK+vj5eeeUVTGLCMeEMhBODa8bNaAgI92bhdfFs/uYiHvr5Stbcl07CvBBUmvNvkZuruzn5UQVv//YUf//fvbz/XDY5u6tobxQBxwLBUEiiq5T7UaTJ9U/gUdwu3Nx5553U1NRw/fXXk52dPeT+2dnZXH/99dTV1XHPPfe4ezgCwZRGkiRW3zOD4OjBifIn/z5La133pY/zmvhSKY1G4+K+m67lUmAPKR7gzJkzIxKuL4VJpeaG0gOObSs+2BT3zeartF28a8ony1JHk60HjdkPyabCV2cj1GvQAWLCygemIk5bG4iT/VmujiVRDiBFFUSyKoh6pZtcS+MlrjT9sYzBcTNA2QkLNqtdMNN5S8TMVg1xxNRDo1MxZ3U0d39/KTd+OYO42a6h5X3dZo5vL+ff3z3Ah//Ipb6sY4JGaiciIoJNmzY5thsaGnj77bcnXWnX5cZwMm5Gg7eflllXRLHxi/N45Jer2PDFecy5Mhq/EP15+1qMVsqym/j0lQL++72DvPiDQ+x9tYDy082YJ4lzTCCYTIhSKYFgbLh9Pe+73/0uH330Efv372fBggUkJyc7ukp597sAenp6HF2liouLURSFZcuW8cQTw+vCIRBcTmi0KtZ9YQ6v/+Qopj4rZqOV7X85zW3fXoRWf+GXsGxwagfe04NisyHJ4196kZKS4hBsioqKuPbaa8d9DONBWloaBoOB7u5urFYrOTk5LF26dMznNalULK7LIaynhQbvIEDCovijldznbLGicNraQL5VZr5fL6E6+yQoyd9EY6/daTCQZXPCUku9rYsrNHGs1MQDYMTKCXMNPZgd+12OuDhuRinc9HUq1ORZiZltf11HpKloLLPR2z79fqqSLBE3O5i42cG01nWT/UkVeYdqsZjsriObTaHwaD2FR+uJSPJn3toYkheEIqvG/31s7ty51NbWcuCAXUTNzc0lOjqaFStWjPtYBHZkl65Snlm51+hUJM4LIXFeCIqi0N7QS8WZZipyW6jOb8VyTqlUW30PbfU9ZO+qQqWWiUoLIG5WEHGzgwmM8BadqgSXPcJxIxCMDbcLN3q9nt27d/PMM8/wpz/9iaKiIsfEbeBDy3mlyt/fny996Us8+eST6JxqlgUCwSABYd5c/eAstv85B4DW2m52v5jPtQ/PuuDNoHOpFIDS24tkMIzLWJ1xLiGqr6+no6MDPz+/cR+Hp1Gr1WRkZDgmdsePH2fJkiVjvlE3qdSoUNhYepB/zt4IgEXxR6M04+45gBkbRR0qQvv/TIL1Vvy1FtpNaocYIwHVtk5eM+Zyp24OWlSYFSsaSQXKyEQbCVBL9uOnAy4ZN6MolRqg5qyVkHgVeh8JSZZIzFRz5uPpvTIZGGHgyntmsPSmJM7sqyFnd5VLEGxdSTt1Je34BOqYe1UMs1ZGuWbljANXX301tbW1lJaWAvDRRx8RHh7uEmAsGD9cMm7GWCo1rOtJEgHh3gSEezNvTSwWs5XawnbK+4Wc1lpXF6zVYqPyTAuVZ1rY/0YRPkE64mYHEz8rmJj0QLRe06gOUiAYJi4ZN2Yh3LgDafqt6wgugUc+OXQ6HT/60Y/4wQ9+wP79+8nKyqKiooKuri4AfHx8iIuLIyMjgyuuuMJRPy4QCC5O0vxQFl4fx4kPKgAoPFpPeKIfGWvPz4aSvVxDbG29vcgTINwEBwcTEBBAW1sbAMXFxS5hvtOJhQsXOoSbhoYGqquriYmJGdM5TSr7W/T15Yf598zrscpqQI1V8UUtdY51yOfRalTT0qciSG8XHpL9TZxoHPyYGLg/mKcKR4eKZqWXYMmLlZo48ixNFFib6ePiIdQSMFsVRmSoNwEab3qsJhr7Oslpr3b79zLemJyEG/UYxCjFCmXHzaRfaV+Z9A2RCU2SaSyZ/kGoeoOGhdfHM/+aWEpONZH1cSV1Je2O57tajRzcWszR90qZsSyCuWtiCI7yucQZ3YdKpeK2227jr3/9K+3t7SiKwhtvvMHnPvc5goKChj6BwK2Mt3BzLmqNithZQcTOCoLboLOlj4pcu4hTmdeCuc/1PaCrxciZvTWc2VuDLEtEJPsTNzuIuFnBhMT4IMnCjSOY/rg6bqb3goRA4Ak8KvlrNBquuuoqrrrqKk9eRiC4bFi6KYn60g6qC9oA2P96IX4hXiTOC3HZT9LrQZahvzW1rbsbQkLOPZ3HkSSJlJQUjh07BsDZs2enrXATEhJCXFwcFRV2Ye348eNjF25kuxjgb+phbnMhp0JnAmBRAlApnW533QCUtGsJ0ttzkSIMFnzbrHSaVY4yqAjZh/nqCFqVPj40FaNF5lptMvPVEfjLOvIsTTQq52f8hMs+pKqCSJIDsaoU+mxmvFQa0v0iiPIK4EBTMZ2WPvd/Q+OExalUSjsGxw1Ae51Cc6WV4Fj7OeMy1LTXmjBdJvmnskomZVEYKYvCqC/rIPuTSoqONWCz2aVDi9lG7t4acvfWED0jkHlrYkiYF4Ls4cmvwWDgrrvu4h//+AcWi4Xe3l5efPFFHnnkEUcpuGB8cJ4A2iZByYVvkJ7Zq6KZvSoaq9VGfUk75bktVOQ201TZ5bKvzaZQU9hGTWEbh94qwctP219SFUTszCC8fC7f7nyC6Y2kHVyotwnHjWCaoCgK27dvZ9u2bWRlZdHcbI8zCA4OJiMjg40bN7J+/Xq3XEt4NQWCKYSskrnus3N4/adH6Wo1oijw4d9Pc8s3FhIWP1iCJEkSsl7v6Cg1UQHFADNnznQIN0VFRXR3d2OYAPfPeLBo0SKHcHP69GnWrVs3phLQAccNwKrqEw7hxoYXNrxQ4f7fa0Ovmk6TjK/WLvqlBho52eCNAqiQWKWJx4pCjqUeM1bMWHnLlMcydQxpqmC0ajVHLFV0KiaH2BMuGVikjiRY8qZDMZLdXEljn90xlOobzhz/KOYERHGkuRTrFA19NbvJcTNA+UkL/uEyaq2EWiuRkKmmYO/F3UzTlfAEP659eDYrNqdw+tNqTn9aTV/X4EptdX4r1fmt+AbrmXtlDDOviPRoGVVkZCSbNm1iy5YtADQ3N/Pqq69y3333ObroCTyPc8YNFguK1Yqkmhxh3iqVTFRqIFGpgSy/OZnudiOVZ1vsbpwzLfR1uzoNejtM5B+qI/9QHUgQFudLTHoQMemBRCb7o9ZOju9LIBgrrqVSwnHjFqbmLdO04dixY9x///3k5dk7wJ4bkXDgwAGee+450tPTeeGFF1i8ePGYrifuMgSCKYa3n5aNj2Ww5ZfHMfdZsZhsvP+nbG799iL8ggdLpCRvbxgQbnomTrhJTEzEx8eHrq4ubDYbubm5LFmyZMLG40lmzZrF9u3b6evrw2w2c/bsWebPnz/q85mcJiJJnTXI9GDDvrJvsQWiUnni9ypR0KZjUVi/68bbgp/WSrtJxRpNIl6oybHWU2ZrA0BGwobCIUsVNbZOgmQvTP3ChQJ4o2GxJpogyYtKWztnLI109LY7RJ2zHbUEaQ2E6/3wVummrOtmrO3AzztfL5SfspC8xH6jGxilIiTBRlPZ9C+ZuhCGAB1LNyWxaF08hcfqyd5V5eJk6Gzu48CWIo68V8KMpZ4to5o3bx4tLS3s3r0bgPLyct5++202b94sAmjHCWfHDdiDTqVzSoQnCwZ/HenLIklfFonNptBY3tkfctxMfWkHLlq1Ag3lnTSUd3Lig3JUapmIZH9i0gOJSQ8kLM53QgK6BQJ34CzcIIQbwRTnk08+YcOGDZjNZmJiYrjtttvIzMwkNDQUgMbGRo4dO8brr79Ofn4+q1at4v333+fqq68e9TUnjXCzfft2Ghsbuf/++yd6KALBpCckxof1n5/Le3/MwmZT6Okw8d4fs7n1mwvReds/GGUvL8f00dbrnvbUo0GWZebOncvBgwcByM7OnrbCjUajYfbs2Rw/fhyArKysMQk3RifHjcZqRSO3YLTZhRt7a3AtsuR+u3F9j5p2o4y/zi4SpAX0kdPgT6hsoEnpcWn9bXNa7qmwtVNpa3dZAMrURBEkeVGvdJNtqadZ6cULu2gzIPp0WvqIkvzxUmmmrnDjhnbg59JUaiM41kZApH2iFr9ATXu9CfNlUjJ1IdRaFTNXRJG+PJLaonayd1VRcqoRZaCMyjQ+ZVRXXnklra2tZGVlAZCTk0NgYCBr165163UEF0Y6x8momEwwSYUbZ2RZIjzRj/BEPxZvTKSv29zvxrHn4/R0uL6fWy02h6vs8Nug1auISgt0CDlBkQYhFgqmDJJGZNwIpgetra3ccccdmM1mnn76ab7zne+guoDr85577uHZZ5/lpz/9KU899RS33347xcXFBAYGjuq6k0a4efrppzly5IgQbgSCYRI7K4gr753Brv/Y7Xmttd1s/0sON355Piq17NJZSpnAUimwr1APCDdVVVU0NzcTHBw8oWPyFBkZGQ7hprS0lPb2dvz9/Ud1LudSKa3VgkwPEkYU7JMWsxKITqof+6DPQyK/Tc+ScLvgF+ptxUvXxyvGHHwkLaZLOEqcRZs0VTAJcgC9WMix1NOiuP4dDog+Xqr+tuNTeAJicbPjZoDSo2bmrtM6SqYSL9OSqXORJImo1ACiUgPobOnj9KfVnNlb41KG4lxGNWd1NDOWRWDwd0/3SkmSuPHGG+no6HB0mvr0008JDAyctjlek4lzHTc2o5GpWFCkN2hIzQwnNTMcRVForu6iKq+VqrxWqgvbsBhd30tMfVbKspsoy24C7A7c6BmDQo6z61YgmGyIUinBdOH3v/89ra2t/OhHP+KJJ5645L4qlYonn3wSWZb53ve+x+9+9zueeuqpUV1X+C0FginMrCuiyNyQ4Niuzm9j13/zUBTFpbPURGbcAERERBAWFubYzs7OnsDReJbY2FgXJT0nJ2fU5zI7qfdaqxVJAo3U6njMqviiKJ6ZrjT1qmjpGzz3jEAjCgqdyvAcPn6SjjSVXZw7Y2mg3tZ1wVLsgTIpi2Kj1TTYUlctyQRovPBV61FLk/+jyt0ZNwOYeqHi1KBQExilIiR+8v88xhPfID3Lb07mgZ+uYO396YTEupZIdTb3cXBrMS88cYBt/5dNWXYTNuvYS87UajV33HGHwxYN8O6771JSUjLmcwsuzfmlUlN/EihJEiExvsy/Jo4bvpTBZ3+9is3/u5AlNyYSlRqArDpf2O7pMFF4tJ5d/8njP//vIP/53kF2vZhH4bF6ertE+KtgciGEG8F04d133yU4OJhvfetbwz7m29/+NsHBwbz//vujvu6kcdwIBILRseTGRDqaeyk4bHde5B+qwy9YT4S3k3AzgRk3YL8hnTdvHjt37gTswb1r1qyZ0DF5ioHvdc+ePYC9XOqKK64YlZvE5CLc2CfvKqkDSQlBQQ3ImJUAtFKzW8buikRBq45lkXbXTZDeSojeSlPf8D42wmUf/CU9dbYuKm0dWC8g26gkmUgvf3SymsLOBky2QcEjyiuAOQHRaCSZJmMX5T0tVPW0nneOycJ5GTeKgrvafjWW2ghyLpla2F8yNTWryjyGSxlVcTvZn7iWUSk2hdKsJkqzmjD4a5mxPJKZKyIJCBt9RygvLy/uuece/v73v9Pd3Y3NZuPVV1/l4YcfJjw83F3fmuAcJFkGjcaRk6FMgs5S7kalkolMCSAyJYDFGxMxG63UFrXZHTn5rTRWdp4XTNrR2MuZxl7O7K0BIDjGx+7GmRFIVGoAWr247RdMHC7twIVwI5jCFBcXc+WVV16wPOpiqFQqVqxYwaeffjrq67r9HXwk34AziqJMaZu8QDBRSJLE2s/MpLvV6GgTfvT9Mubr0gnCXp40kRk3A8yePdsh3DQ3N9PZ2Ymvr+8Ej8ozOAs3jY2N1NbWEhUVNeLzuJRK9YsakgRqqRWzYl/ltygBaJQWJMn9rQVajGqaelWEeNmvnRbYR1OtARj6vTpE8kaFRI2tk07FeMF9grUGYr0D6bGaqO1rd3muw9xHZXcLvho94Xo/orwCqPJu5XBTqUuuzmTB2XEjAyoUrMP4OQ2X0mNm5q3TotI4lUztEyVTF0KSJKJSAohKsZdRndlXQ97BWrpaB/8Ou9tNnNhRzokd5USnBTDziiiSF4SOqoNPYGAg99xzD//6178wm80YjUZeeuklPvvZz07b97jJgKzRYHMINxd+j5lOaHQq4mYHEzfb7mTs6zJTlW8XcaryWmhvOH+Bprmqi+aqLrJ2VjrydaLTA4lNDyI80Q+VWrj3BOOHi+NmGoqtE4EHbv0Ew6CjowOvUeSqeXt709c3+lU3tws3Sn88/khb4JrEC1ggGDUqjcy6L8xly7PHaa2zizRZykIyAg4Q1JbvaAs+kQQGBuLv7097u32CXl5ezpw5cyZ4VJ4hODiY2NhYKisrAXtp2KiEG9k142YAtdSOWQkCVIAKi+KPRmob46gvTH6rjhAv+99PgM5GmJeFht5Lt1vWoSJWZW9Pf25Y8QA+ah1JPiH4qvUUdTXQbOxyeb7N3ENbe7/bR2sgySeEREMI2jA1R5vL6LFOrs8M8zkJGxqsWN1YjWzqsXeZSlrc32UqWkVwvI3m8suzy9Rw8Q3Ss3RTEotvSKTybAtn99VQmt2EzTr4V1ld0EZ1QRufvqImbUk4s66IIjRuZIJLdHQ0t956K6+88goA7e3tvPTSSzz00ENozynrEbgHSadzdE68HCeBeh8NKYvCSFlkL0PubOnrd+O0UJXXSk+768/EZlOoLW6ntridY++XodbKRKUGED0jkOi0QEJifVCJjlUCDyJKpQTTgZ/+9KcAjhbgI+Hs2bNERESM+tpuF26io6OpqamhvLzcJdNiKJYvX86RI0fcPRyB4LJBb9Bww5cyeOPnx+jtNKMgkzPncyw6+SuCJzjjZoD4+HhHvs10Fm7A7roZEG5ycnK49tprR+xIdC6V0thsyIoNmyQjSTbUUjsWJQgAixKIWmlzV2WOC+0mNfU9asK97cJRWqCRhl41l3LdmLBiUWx0YKRbMTtafw+glzUkGkKI8Q6kydhFWVczFuXiAkSLqZvO1j5UkkycdxARXn6UdDW55xt0E86OGwA1VuDSAtdIaSyxd5nyj7BPrhIWqOkQJVPDQpYl4mcHEz87mN5OE/mH6zizr8YhdAOYei2c3lPN6T3VhMT6MOuKKFIXh6M3DO/3mJ6ezrp169ixYwcAtbW1vPnmm9x5553IspgQuxuXsovLULg5F98gPTNX2Mv/FEWhta6nP+i4hZrCNow9rg49i8lGRW4LFbktAKh1KiIS/YhMCSAqxZ/wRH80uqkY+SyYrEhaV+FGVFsIphqPP/44v//975EkiaysLA4cOMCKFSuGdeyBAwfIzs4eUyMmtws3S5Ys4a233uLYsWNs2LDB3acXCASXwC/Ei42PZfDWr05gMduwqr3ImvtFQjqLJ3powPnCzXRm9uzZ7NixA6vVSnd3N8XFxaSlpQ153Jkff83xtaW5mcIdLzu2s5/8H0e3sJq2Xlb/YhcWm4KChp/dcQc3zY8e8TgXP/TrIfcpaNM5hBs/rY0Ig4XanotPZhWgCxPBkjcGWUubMqgsqJFJ9Q0l2TeULouRws4GWs2XdoRJgFmxUtBZT5x3EKk+4ZR3t2C9hNjjegLP3xhazvk41Ujuy7hxpuSYhXnXa+wlUzqJxEwNBftFydRI8PLVMv+aODKujqW+tIMz+2soPNbg0sGnqbKLT18pYP+bRSTND2XWyiiiUwOQhmgrvmzZMlpbWzl8+DAA+fn5fPTRR1x//fUe/Z4uR5xbgtuM079UaiRIkkRQpIGgSAPz1sRgsyk0VnRSlWd349QWt2M1u75/WoxWR0crsIudIXG+RKX492ft+OPlI9xjgtHj7LgBwGKxZ1UJRo8ihK/x4g9/+AN/+MMfiIiI4Mknn+QrX/kKd911Fx999BEzZsy45LF5eXncfffdADz66KOjHoPbl4CWLFmCoigjds8MlFi5i56eHt566y0eeeQRZsyYgV6vx2AwkJGRwdNPP01XV9fQJzmH1tZWvvrVrxIfH49OpyM+Pp7HH3+ctrY2t45dIBgL4Ql+XPvIbAY8DkZ9EAcaZ2Dqm/jJXXx8vOPrhoYGuru7L7H31Mbb29tFqMnKyhrxOaRzSk6dJydRAV7cmDFYfvXXT0vc/j46QIdZRU33oDCRFmBEGiJnptTahgaZxeooQiW72OSDlmXqGNL9IjBaLZxpr6W6d+jA4YErKYqCyWbFqtg89r2OFkWSsDh9pLqzJbgzph4ozxo8d2C0THCccHOMBkmSiEjyZ+19M3no51ew5r50IpL8XPaxmm0UHq3n7d+c5L/fP8ixbWUuWTkX4vrrr3d57R88eJCjR4965Hu4nHFZvReOm0siyxLhCX4sWpfATY8v4LO/XsVNX1vAovXxRCT5I6vPn/zZbAoNZR2c2lnJ9j/n8Pz/7uOlpw6x68U88g/X0dHUO+nehwWTm3OFG1EuJZhKtLa2kpqayoEDB/jiF7/IY489RnV1NQsXLuRb3/oWWVlZWK2D92dWq5VTp07xzW9+k4ULF1JZWcnXvvY1li5dOuoxuN1xc+2113Lo0CEMBsOIjvv+979PY2Oj28bx0ksv8bnPfQ6AmTNnsmnTJjo6Ojhw4AA/+MEPePnll9mzZ8+wy7mamppYvnw5RUVFJCUlcfPNN5Obm8vvfvc7tm/fzsGDBwkKCnLb+AWCsZA0P5QFMU2crLIH2LZZ/fjwH7lseHQu8gTWsAcHB2MwGByCTUVFBTNnzpyw8XiajIwMzp49C9hX3vv6+tDr9cM+Xj5HuFHOWVX+3Koktp6sBiC3poMDxc1ckRIyxlFfmMI2HZHeFiQJfDQ2og1mqrovvvpaYGvG36pjliqUMI2BHsWMt6RBjUyP1cTRljJajN0jihkO1fuilVX0ShKyJGGbZJMGMyrU2Fex1R4SbqC/ZCpmsGQqfoFqWod9jwdavZpZV0Qx64ooWmq6OXOghvxDdfR1DU4sOpr6OPxOCUfeLSFuTjCzVkQRPy/4vFwQWZa59dZb+ec//0ldXR0A27ZtIyAggNTU1HH9vqYzLqVSRiHcjAS1RkXMDHu3KQCLyUpDeQc1he3UFrVRW9KOue/897DWuh5a63ocXat8AnWO0qrIlACCIg1DutIEly9CuBFMZRYsWMBjjz1GcLA9IP63v/0tBoOBn//85/zyl7/kl7/8JVqtlsBA+/tqa2urI8NXlmW++c1v8vOf/3xMY3C7cLNw4UK2bt064uPcXVal0Wj4/Oc/z+OPP+4yMaytrWXjxo2cPHmSxx9/nJdeemlY53v88ccpKipi8+bNvPrqq6jV9h/dV77yFf7whz/w9a9/nX/9619u/R4EgrGQHm+m6eAnVMauBaA8p5m9rxay+u60CaspliSJ+Ph4zpw5Yx9Tefm0Fm5SUlLw8vKit7cXi8XCmTNnWLhw4bCPlzQaUKmgX8FXzkminxXlx6rUEPYW2vNe/rm/1GPCTZdFRXW3hhgf+41WaoCR6m4NyiWybo5aa6hTukiVg9FIMibFSpG1hdbGNroswy9t8FJpCNH5Mj8gFoC8jrpLZuJMFGZJhZdi//l4ynEzgHPJlEYn8f7773PnnXeKvAA3EBRlYOVtqSy/OZmy7CbO7K+h4kyLw/qlKPb30/KcZrx8NaQvi2TmFZEERgwuWOl0Ou655x7+9re/0dnZiaIovP766zzyyCOiTbibkLWDwrZiFsLNWFBrVUSlBhKVap9w2GwKzVVd1BS1UVvURk1RO70d5/+Mu1qNFB6tp/BoPQA6bzWRyf6ONuZh8b6ic5XAgRBu3IwCk67J5mQbjxu58cYbXbYlSeInP/kJGzZs4De/+Q0ffvghPT09NDQ0OPYJDAzk+uuv5+tf/zqZmZljHoPbhZvJwgMPPMADDzxw3uORkZH86U9/YsWKFWzZsgWTyTRkx4fa2lpefvlltFotzz33nEO0AXj22Wd55ZVX+O9//8svfvGLEQUyCwSeRPb2IqV4C336IBpD5wNw+tNq/EK8WHBd3ISNKyEhwUW4mc6o1WrmzJnjKJPIysoakXADdtfNQFewC+U4PLIy0SHcfJzXQEVzD3HB3mMc+YUpaNcRZTAjS+CtVoj1MVPRden3z0pbBzW2TqwoyEjYUPC2DJbtnRtcPIBOVuOr0ROkNRBvCMZHbZ+klXQ1UtHT4sbvyn2YJZXjm9HgWWHJ1AMV2VYSF9k/j/Ly8jh9+jRz58716HUvJ1RqmeSFYSQvDKOzpY+8g7WcPVBLZ/OggNrbaebkRxWc/KiCyGR/Zl4RRcqiMDQ6FX5+ftxzzz08//zzmM1mTCYTL774Ip/73OeEO8oNiHBizyHLEqFxvoTG+ZKxNhZFUWhv7HWIOLVFbRdsP27ssVCW00xZTjNg73gZnuBHVKo9IyciyR+tftpOPQRDIIQbwXRk5cqVrFy5EpvNRmlpKU1NTahUKkJCQkhISHDrtS7Ld8+MjAwAjEYjzc3NREZGXnL/HTt2YLPZWLVq1XkrZTqdjhtvvJHnn3+ebdu28eCDD3pq2ALBiJC9vJBQmHX2X2QFPEGbxv63e2BLEb7BekcL0fHGOeemrq5uxOVDU42MjAyHcFNeXk5ra6vDRjkcJL1+sOVt3/ntg1anhpIUYqCkqRtFgX8fLOPJG2a5Z/Dn0GuRqezSEO/b77rxN1LVpcF2CdcNgLVfzbBdQKKRkFBLMn4aL4J1BnzVOvy13gRqvZGdztti6qa2t50zHbVu/I7ci8WpJbinHTcADcU2gmJs+IfbV7S3bdtGYmIiPj4+Hr/25YZvkJ7FGxPJXJ9AVUErZ/fVUHyqEZtl8G96oNXy3tcKSM0MZ8bSCCKTI7jtttt45ZVXUBSFjo4O0SbcTYhw4vFDkiQCwrwJCPNm5gp7tlp3u5HafhGnpqiN5qouzq1etZpt1BS2UVPY1n8eCIn1JTLZLuKEJ/rhG6wXTsHLBEmlAlkGm31hQwiugumELMskJyeTnJzssWu4XbhpaWlBr9fj7T36Fd+enh76+vo8lhlTUlIC2MuphnONgVDRi62UL1y4kOeff97RLUcgmAxIXl4AqGxmFjRs4XjG1+hosk/8d/7zDIYAHZHJ/uM+rtDQUEf5kKIoVFZWTuvch+joaIKDg2lutq9A5uTksHr16mEfL+kvPTmRZYkHViTwg3dyAXj1WCVfuzYNg84zunxRu44YHzMqCfRqhZhhuG4uhE5WE28IJtorAINah5fKvhJnQ8Gq2OgyG2kz99Bu7qXV1EOzsWtSlkc549wS3JMZN86UHrMw9zp7yVRvby/vvfeeKJnyIJIsEZseRGx6EH3dZgqO1HFmXy3N1YMND8x9Vs7sq+HMvhp8g/SkLg7nyqXXsfvQB4BoE+4uhONmYjH460hZFOZYBDL1Wqgrae8vr2qnvrQDq8X1PVtRoLGik8aKTrJ3VQHg5aclItHPIeSExfuJNuTTGEmjceT1CceNG5jGpUmC83H7nX1oaCgPPvgg//jHP0Z9jscee4z//Oc/WCye6YLzu9/9DoB169ahOyf880JUVFQAEBMTc8HnBx6f7mUfgqmF7D2Yt6DpbuaGL2Xw5i+OY+yxYLXY2PZcNrd+exEBYZ4pq7nouGSZuLg48vPzAfvrZjoLN5IkMW/ePHbt2gXYheBVq1YNe2LtkuNwkVXlWxfF8OwH+XQZLXT2Wdhyspr7lsVfcN+x0meVqXJy3ST7GansunTWzYXw03gx2z8KtSRjtFmo6W2nvq+dLouRHquJbosR6yQLHx4Ks0tXqfERmYzd55dM5ebmMmfOnHG5/uWM3qBh3ppY5l4VQ2NFJ2f211J4pA6TU6hrZ0sfJz6w3xtE+62kxVaG0atRtAl3Ay5dpUQ48YSj9VITNzuYuNn24E6r2UZDRafDkVNX3I6x5/z7+t4OE6VZTZRm2Ut+JVkiONpARKI/4Ul+RCT64x/mJcToaYIQbgSC0eN24UZRFLe0B/RUi8Ft27bxj3/8A41GwzPPPDOsYwZah1/MRTTQQauzs3NY55s9e/YFHy8uLvaovUpweSF7ezm+Vnp6CYwwsOF/5vH2705isyj0dZt57w9ZbP7mIrz9xteyHx8f7yLcTHechZvm5maqq6svKgSfi+RURma7QKkUgI9Oze2ZMfxzfxkA/9pfymeWxnnsRre4Q0esT3/WjUYhymCm+hIdpi5Eo7GTrNZKFgbFoygKbeYeSrqaziunulgGzmTELA1+pI5HqdQADcU21tyaQFlZGQDvv/8+8fHxIkdlnJAkibB4u1PgittSKD7RQMHhOqryWl1KR0wdMj4kYehKxKxp5+THpfh4HeKK1csmbvBTGBdRWzhuJh0qjWwPKk72Z+H18Sg2hZbabmoK26grbae+pIP2xvNzchSbQlNlF02VXZz+1N41UW/QOESciCQ/whL8RFbOFMU550YINwLByPDIu96+fft4+OGHx3S8J8jLy+Mzn/kMiqLw7LPPOrJuBILpiOw1KNzYeu03R1GpAVz9wEw++oc9HLi9sZd3/3CKm7++EJ3X+N0EOefcVFdXYzQah+V+m6oEBgYSHx/vEKmOHz8+bOHGuSW40nfxHIcHlifwrwNlKAoUN3azO7+RNemeyTHqtcjUOHWYSvE3UTNEh6kLUdLdRKOxkxUhKczyi8RPraewq4Em42DZyVQRbQAsLo6b8RNuAG666Saee+45zGYzvb29vPnmm9x///2iFGec0WhVpC+LJH1ZJN3tRoqONVBwpI6G8sGFHQkJrTkArTmAky91Ub5/L4uvSSNhXogoERkBrqVSIuNmsmN30vgQHO3D3Kvsn3+9nSbqSzvsQk5pB/WlHZiN57939nWbHZ3cwJ6VExTlQ0SSvcQqIkm4cqYKLsKNEFzHjDSVbpIEY8YjM7WioiKKiorGdA53v/lWV1ezbt06Wltb+frXv85Xv/rVYR87EPTY0x8Qei7d3d0Aw17dzM3NveDjF3PiCASjwVm4UYxGFJsNSZZJWxxBV4uRg1uLAWiq7OK9P5zixq/MH7cVrMjISPR6PX19fdhsNsrLy0lLSxuXa08UCxcudAg3OTk5XHfddXg5/Y4uhrPj5lKTk4QQA1enh7PzrL0t6//tKfaYcANQ1K4l2mBGksBHYyPaYKZqhK4bgE6LkQ/qclkQGEuKTxh+Gi8KOuup6GmeeqVSTo4b9TiVSg0w0HLyvffeA6CsrIw9e/awZs2acR2HYBCDv46Mq2PJuDqW1rpuCo/WU3Ck3sVlICHTWm7mw3/kotapSMoIIW1JBDEzA1GphOh2KUTGzdTHy1dLwrwQEuaFAPY25K213dSVtPcLOh201nafd5yiQHN1F83VXeTurQFcXTnhSX6EC1fOpMRFuPFQJIZAMF1x+zvaQDnAZKKlpYXrrruO8vJyHnroIX75y1+O6Pi4OHvr5Kqqqgs+P/C4s4tAIJhopHNEAaW3F6m/rG/BdXH0dJrI2lkJQF1JB+//KZsbvpQxLiu+siyTmJjI2bNnAXtg+HQXbmbNmsWOHTvo7e3FYrFw6tQpli9fPuRxkm5wcnKxUqkBHr0yySHcHClt4URFKwvjht/BaiR0W1RUdWuI9RnsMFU9CtfNACdbK6nv62BJcCLzA2MJ1hnIaavGaJs6N3ZmaXCiPV7hxM4sWrSIsrIyTp8+DcCePXuIi4sTJbiTgMAIA0tuTGLxDYk0lHeS/WkZ+YdrkayDkxiL0UrBEbu4o/fRkLIojLTF4UQk+SPJwklwLi7CjSi5mBbITq6c2auiATD2mO0iTkk7df2uHFPv+Z8LQ7lywhL8CAz3Fq+lCUZSD049FfPU+XwXCCYDbhdurrzySnefckx0dXWxfv16zpw5w+bNm/nb3/42YjfPQEnViRMnLvj8wOPz5s0b22AFAjcinyPc2Pr6kPuFG0mSuOLWFKwmm6OGvKawjW3/l83GL85DrfW8eJOUlOQi3Ex3NBoNCxcuZP/+/QAcPXqUpUuXDlnKIuucHDdDBHBmJgSxKD6Q4+WtAPx1Twl/vm/RGEd+cYradUQbBrNuYnzMVI6iw9QANb3tbKvJYVVoGqE6X2xTzHHj0g5csTFKDWvUSJLEDTfcQE1NDS0tLQC8+eabPProo/j5+Y3vYAQXRJIkwhP8uDZhHnOvDeO/f9kK7f7o+kKQlcFbsr4uM6f3VHN6T7WjM1XaknCCo0Wr9wGchRubcNxMW3TeGpfQY8Wm0FLXTX1Jv5hT0k5r3fmO+Au5cjR6FaGxvoQl+BEW70tYvB9+IaId+XjiEiouBNexM7VukwRjZFp7CI1GIzfddBNHjhzh+uuv5+WXX0alGvmEdN26dciyzN69e2loaCAsbLD8wGg08u6776JSqdiwYYM7hy8QjAnpnMyYgZwbx/OSxOq70rBabJw9UAtAVV4r2/+Sw4ZH56HSeNamn5SU5Pi6oaGBzs7OaR+mmpmZ6RBuWlpaKC0tHdIN4fx7VIyXdtwAPHplMp/79zEAPjhTR0ljF0mhnpns9VjsHabifJ1cN10abGNQLEw2Kx/Xn8VLpcGsjM61opIkFgclkN9ZT6vpwiWunmAi2oGfi16v54477uDvf/87FouFnp4eR97NaD7/BJ4jIjKCuz+3iRdeeIEuYyFaYxDexgh0phBs1sG78YHOVCc+KCc42kDq4nBSM8PxCxm61HI64zIBFMLNZYMkSwRH+RAc5cOslVGA3W1TX9ZB/YArp6TdpbvbAOY+KzWFbdQUtjke0xs0hMX7Etov5ITF++ETOH0z9yYctXOplBBuBIKRMG0LqK1WK3fffTeffPIJq1atYsuWLWi1l14J/uMf/0h6ejpPPPGEy+ORkZHcfffdmEwmvvjFL7q0Kf/Wt75FY2Mjn/nMZ1wEHYFgopFk2aVcynaBjCZJlrjqM+mkLQ13PFaR28KOv53GavFsRkdQUBD+/v6O7cvBdRMYGOjS+vzo0aNDHiPpB28gbRdpB+7M1elhJIfanVWKAn/bWzqKkQ6fonYdtv45ppdacZROjZVe6+jPk+obTpwhmGsjZrEkOBG9Zny6prk4bsY548aZiIgI1q9f79guLy9n9+7dEzYewcWJjo7m3nvvRa1RYdI30+afS3vUMRbdFEVMeiDnGgGaq7s59FYJ/3nyIFuePU7O7ip6Oy9P0cI140ZMAC9n9AYN8bODWXJjEpu+Mp/P/no1d31/CWs+k87MFZEERhou6oDs6zZTcaaF49vL2f7nHF54Yj///PY+3n8um6Pvl1Ke20xv1+X5GvMEzhk3iIwbgWBETFvHzR//+Ee2bt0KQEhICF/84hcvuN8vf/lLQkLsoWhNTU3k5+dTW1t73n6//e1vOXToEG+++Sbp6elkZmaSm5vL6dOnSU1N5de//rXnvhmBYJTIej3WfqeNcpF8FFmWuPr+mVjNCsUnGgAoy27io+dzue6R2cgeCsiUJImkpCROnjwJ2IWby6HT2+LFiyksLAQgPz+f9vZ2FwHrXFxa3l6iq5Rjf1niC6uT+dab2QC8eaKKr12bSpivfogjR0evVaaiS0OC70CHKSOV3RpsysRYzzWSipl+kY7tBEMwsekBFDXWUNRQjcXmOSfMZHDcDLBw4ULKysrIyckBYO/evcTHx5OSkjKh4xKcT3x8PHfddRcvv/wyVquVPnM3n+a8w8MPP4yXZpa9M9XRehrKOlyOqy1up7a4nb2vFRI7M4jUxWEkzA1Bb9Bc5ErTC1mEEwsuwoVcOaY+C02VnTSUd9JQ1kFDeecF25ED9LSbKMtuoiy7yfGYb7DeUV4VluBHaJzvuHbjnC64ZtwIwXXMiFKpy4pp+47T2trq+HpAwLkQTz31lEO4uRQhISEcOXKEp556irfeeoutW7cSHh7OV77yFX74wx8SEBDgjmELBG5F9vLC2v9asPVc+AYFQFbJXPvILGxWG6VZ9huV4hON7FSd5ZqHZiF7KMzvXOFGUZRpX2uekpJCQEAAbW1tKIrC8ePHWbt27UX3d+4qZRtGqRTATQui+NVH+dR3GDFZbPxrfxnfWpc+5rFfjKJ2HbE+ZlQS6NUKcT4myjonxmpuVqwcaComIyCGAK03ACpZxYzwWOKDwsmrq6C8pd4z13ZpBz5xjhtwzbtpbraHdW7ZsoUvfOELlxQKBRNDSkoKt912G6+99hqKotDT08O///1vHnroIUdnqraGHkdnqrb6QQelYlOoyG2mIrcZSZaITgsgaX4oiRkh+AR6RrCdDIiuUoKRoNWriUoNJCp1MLC/r9tMY3knDRUdNJR10lDeQVfrhRdIOpv76Gzuo/hEo+OxgHBvwhJ8CYuzizkhsT5oxiEjcCrjItwIx41AMCKmrXDz1FNP8dRTT7n1mKCgIH7/+9/z+9//fmyDEwjGCZdSqb6LCzcAKpXM9Z+dw/a/5FB+2j7RKzxaj0otsfa+mR7pxJCYmOj4urOzk6amJkJDQ91+ncmELMtkZmayc+dOAI4fP87q1atRqy/8duzcVWqocOIBdGoVD1+RyE+35wHwn0PlfHFNCj46z7zlG60yFZ1aEv3s40vxN1HZpcU6Qa6b+r4OPqo7Q4IhhDkBUXip7D9DvUbL/NgUkkIiOV1TRmNXm1uv69oOfGIdNwA6nY477riDv/3tby55Nw888IDIu5mEzJw5k1tuuYUtW7YA0NHR4RBv/Pz8CAjzZvHGRDI3JNBU2UXBkToKj9bT3T74vqDYFKryWqnKa+XTVwoIi/claUEoSfNDCYwwTNS35hFc2goL4UYwCvQGDbGzgoidFeR4rLvdaBdzyu2unIbyDno7L+wMaavvoa2+h4LD9sUASZYIijT0izm+hMT6EhztMy7dOqcKLq9b4bgRCEbEtBVuBAKBa2cppffSwg2ASiOz7gtzeP9P2VTl2Z06eQfrUKllrrxnhtvdMD4+PkRERFBXVwfYXTfTXbgBWLBgAbt27cJqtdLd3U1eXh5z5sy54L4uXaWGaAfuzN1L4/jjJ0V0Gi109ll45UgFn12VNPSBo6S4XUucjwmVDDqVQryviZKOiQt4VIDS7iYqe1qYrQklOSwKtWy/efbzMrAieTb1Ha3k1pTSaRz6tTEcLC6Om4kXbgDCw8PZsGED77zzDgAVFRXs2rWLa665ZoJHJrgQ8+bNw2Qy8d577wF29/CAeGNw6goYGudLaJwvyzenUFvYRsGxekqzmujtcBUw7BPPTg69VUJghDeJ8+0iTli875R3NwrHjcATGPx1GObpSJhnd+MrikJXq9Eu5JQNCjoXakmu2BRHJ6uz+/tjFyQICPMmNNaHkFhfQmLs/3v7jU/22mRDtAN3L5IolbqsEMKNQDCNkZ3LbHqHN+lXa1Rs+OI83vtDlqPzQu7eGmS1zKo7Ut1+s5+UlOQi3CxdutSt55+MGAwG5syZQ1ZWFmAPKb6YcOPcVcpmGjrjZgA/vYZ7lsXxlz320Od/7Cvl/uUJaNWeySwy2mTKOrUk+9snUMl+Jso7L+K6Gcf5ogUbefUVlLXUMTMinrigwRD5cL9AwnwDKGuuI6++EtMYO1y4ZtyMb6nU+tivXvL5pNXehKba/5b27dvH37+3nfaqsd00b6/83ZiOF1yYzMxMTCYTH374IWDP3/vPf/7DAw88gJeXaycpWZaInhFI9IxArrxbob6knZKsJkpONdJxTn5Ha10PrTvKObGjHJ9AHYkZoSTODyEqNQCVh7LMPIkQbgTjgSRJ+Abp8Q3Sk7zA/vmh2BTaG3tdSqwaKzqxmC7wvq8MOnMKjzU4Hvb209qFnFgfQmJ8CI31xT/UyyPu5smEaAcuEIweIdwIBNMYydupVKp3+G2RNVoVGx+bx7u/z6KupB2AnF1VqNQyKzYnu1W8SUpK4sCBAwCUlpZitVovizKOxYsXO4Sb8vJy6uvrCQ8PP28/WT+ycGJnHr4ikef3lWK2KtS29/FOVg23LYoZ28AvQUmHlnhfE2oZtCqFRF8TRRPounGmz2ziZGUhJU01zIlKJMTHnvMiSRKJIZHEBIZS2FBFcWMtNmV0ootrV6nJ4bgZoOxADz4harwC7WNMvtLA6bc6MHWL5brJyIoVKzAajezZsweAuro6XnrpJe67776LdsiUZYnIlAAiUwJYsTmZlppuSk41UnKqkabKLpd9u1qN5OyuImd3FTpvNQnzQkiaH0rsrKApk9HhItyYhXAjGD8kWSIg3JuAcG/SFkcAYLMptNZ2O8qrmio7aarqurCYA/R0mBzZVAOodSpCon0cYk5IrC/BUQbUU+Q1OSxExo1AMGqEcCMQTGNkvVOp1AjKbMAe5HfDlzN457cnaSjvBODURxWoNTJLN7mv5CYuLg6VSoXVasVkMlFdXU1cXJzbzj9ZiY6OJjIy0tHF7ujRo9xwww3n7Sc5d5UaRjtwZ8L99NyyIJrXjlUB8NdPi9m8INpjYdOmftdNSr/rJsnPSFmnFssEZd1ciPbebvYXnybCL4jZUQn46OyvEY1KzazIBBKCIzhTW051W9MQZzqfiXTcDIXNAoW7upi9yQ+VWkKjl0lZ48PZ9ztRhHYzKbnqqqswmUwcPHgQgMrKSl5++WXuueceNJpLd46SJIngaB+Co31YvDGRjqZeSk41UprVRG1Rm8vv3NhjIf9QHfmH6lBrZOJmB5M0P4T4Sd6hStIMCjc24bgRTDCyPPiam7nC3tnQZlNob+ihqaqLpsoumqo6aarsoqfjwn+vFqOVupJ2x4IZgCRBQITBXmoV0+/QifXBy2dqllq5ZtyI1+2YUIBJdH8FiC5XHkYINwLBNMY54+ZSXaUuhs5LzY1fmc/bvz3pWLE9tq0MlVoic0PiEEcPD61WS2xsLGVlZYC9XOpyEG4kSWLx4sWO7JHs7GyuueYa9HrXLjCSk+PGNkLhBuDzq5Mdwk1BfRe7CxpYm36+s8ddlHToiPc1oZFBo4JEPyOF7ZOvs01dRwv1na0kBkcwIzwWrdp+M+mt1ZMZP4PkkChO15TS0tM57HNOZscNQG+rjbIDPSSvtmel+Iaricn0ovKoezJ+BO5FkiSuu+46TCYTx48fB+yuxNdff50777xzRM5EvxAv5l8Tx/xr4ujpMFGWYy+nqjzbgs0yeKdtMdscLh1ZlohydKgKxSdwcrjnBnAtlRIlF4LJhyxLBEYYCIwwkJo5+Lnb3W7sF3M6HaJOW0PPBSe9igKttd201nZTcGSwI6IhQHdObo4PfsGTv9RKUjsJN8JxIxCMCCHcCATTGMnLKeNmiK5SF0Nv0LDpq/N569cnaanpBuDwO6XIapmF18W7ZZxJSUkuws1VV13llvNOdubMmcOHH35IX18fJpOJ7OxslixZ4rKPrBu94wYgJcyHa2eF89EZ+w3fn/eUeFS4MdskSju0pAXYV9IS/UyUdWox2yZfhoaiKJQ01VLZ2kBaWCxJIZHIsn2cgQZfVqXOo7a9mby6Cjr6hi41nMyOmwGaCk34RagJTbP/XUXN09NZZ6GtUkx8JyOSJLFx40ZMJhM5OTkAFBQUsHXrVjZv3uz4ex0J3n5aZl0RxawrojD1WSg/3UzpqUbKTjdj7hsUHG3ndqhK8CNpfsik6VAlsjIEUxWDvw6Dv4742cGOx8xGK83VdjGnsV/Maa7uwmq+8GdJd5uR7jYjZTmupVZBkQaCow0ER/kQ1P//ZApCdg4nRgg3AsGIEMKNQDCNkb28HV8Pp6vUxfDy0XLT4wt469cnaK2zT2APbilGpZLJuDp2zONMSkrik08+AaCqqgqj0YhON7lWdz2BVqtl/vz5HDp0CLCXSy1evNglQ0gaZVcpZx69Mskh3BwpbeFERSsL4wLHMPJLU9qhI9HXhEYFGhmS/Ezkt00+180AZquV3NoySpvrmB0ZT1RAiOO5SP9gIv2DqWlrIq++ks5LCDgWafJ1lboQZQd7MISq8e7Pu0la7S3ybiYxsixz8803YzKZyM/PB+D06dNotVpuvPHGMWWOafVqUjPDSc0Mx2q2UVXQ6iipOq9DVVkHDWUdjg5VSfNDSZgXQliCn8fKLy+FCCcWTCc0OhURSf5EJPk7HrNZbbQ19NpLrCrspVaNlV30dV1YqLQYrY7XqTNevhqCovrFnCgDwdH2/7X68Z8GupRKCafc2BEf25cV4/6KPXXqFBUVFVx55ZX4+/sPfYBAIBg1stfIu0pdDG8/u3iz9VcnaO/vVrLv9UJUGpk5q6PHdO6oqCj0ej19fX3YbDbKy8tJS0sb0zmnCpmZmQ7hprGxkfLychISEhzPSzqnHIdROG4AFsUHkRkfyLFye4v3v+wp5i/3ZY5+0ENgUSRKOnTMCLSPN8HXRGmHFtMkdN0402Pq42h5PkFNtcyJSiDQ29fxXFRACFEBIVS3NZFfV3HBFuImp4/UySzc2CxQ9El/3o3GnneTfJWBs9u6xE3gJEWlUnH77bfz0ksvUVJi7xR34sQJtFot119/vVsC41UamfjZwcTPDh7sUNVfNtXR5Pr50VrXw/Ed5RzfUY7eoCFudhDxc4KJmxWM3md8cnFkIdwIpjmySiYo0kBQpIG0xfbHFEWhp91EY2WnS25Oe+PFF+d6O81U57dRnd/m8rhvkJ7gaANBUT6O/wMjvFF5qPsknNMOXDhuBIIRMe7CzebNmykvL+fZZ5/l61//+nhfXiC4rJD+P3vvHd7WeZ/9fw4mAZAA995ToiRqT2sPL20PeciW5dix077vL0mTNmnTpk2atNlukybNm3jJSx6yZcuyLNvay9qDWhTFvfcEQRLz/P44JAhIlERJHCB5PtfFi8TBwcEDgADOcz/39/56ZtzcheOmG0OgltV/J4k35gbpRP7A5lwUSoHMe6Lv+LgKhYKkpCRycnIAKCgoGDXCTWhoKMnJye7J2MmTJ72EG8+W7ndSKtXNtxak8PybpwD46nINBXVtpIT53/HxbkWRWUOS0YZGKaJSSO3Bc3zYdeNJo6WVg3nniTIGkxEZj0nXUxYSExhKtClEEnBqymjzEHA8HTe+WirVTUdzV97NAumxGSPVxEzyo+Ls3Qm8MgOHSqXi8ccf5+2336a0tBSAY8eOodFoWLx4cb/el1eHqodTaaiwUJTde4eqToudqydquHqiBkGAiCQTCeNDSBgfQmicf792IfREdtzIjEYEQcAQqMUQqCVxQo871NbpoLHKQmOFhYbKNhorLTRUtNFhvrGrxdzYibmx06vcSqEQMEXoCYk2eIk6/ZWfI5c4yvSF06dPs2vXLk6cOMGJEyeoqKgAJOHyZmzatIn//d//5fLly2g0GmbNmsW//Mu/MGfOnMEY9oAzqMLNgQMH3DkWmzZtkoUbGZkBxqurVD8INyCt0KzpEm/amiQhYd/bVwDuSrxJTk52CzfdIsZoYfr06e7HnJOTQ2trK0ajEQBBe3fhxN0sHhNOarg/+bVtiCL8y8cX+Z8nJ9/dwG+CUxQoaNUwtst1kxBgo9Cswer0bdeNJ1WtjVS1NhJlCmFMRBzGLgFHEARig8KI6XLgXK0tx9zZjh3PjBunlCo5QJPW/qA+34YpRkVoqvQ/FjNJyrtprZJXQX0VjUbDk08+yRtvvOHuSHfw4EHUajXz5s0bkPsUBEEKP4317lBVfKGBqrxmXK6eE2lRxN0V5/inhehNGhLGh5A4PpTYsUH9WprhKdzgciE6HN75GTIyowiNn4rIJBORSd7VDO2tNhor22iotNBY0fW70oLd2rsrtLuteVOVhfzTPdu783NCYwwEd3XPCokx3H53K9lx028IgOBjLtn+OuP52c9+xrZt227rNt/97nf5/e9/j06n495776Wzs5Ndu3bx1Vdf8eGHH7JmzZp+Gt3QMajfcG+88QYglQacPn2aM2fOMGXKlMEcgozMqEKh71/HTTfGUJ1UNvXSGdpbbCDCvreuYG13MHnZnXWESk7uaTFeV1dHc3MzgYGB/TRi3yY9PR2j0Uhraysul4vjx4+zbNky4Jpw4jvMuAFpFe2F+cn84MPzABwtbOD+/z6ITeuP1tp2i1vfGSVmDclGG1qliFIBYwKtZDfobn1DH6OqpYGqlgaiTSFkRMZj9JOyo7oFnNigMCqb66mszoOuaAEFoMSFk753/hkKir5uxz9MhZ9JiaAQSF1k4OI2Oe/Gl/Hz8+Opp55i06ZN1NXVAbBnzx5EUWT+/PkDfv+eHapsHQ7KrjRScqGBkosN17U5bm+xkXOkipwjVSiUkosncYLkxgmM0N+VG8dLuEFy3cjCjYyMN3qjBr0xmNgxwe5tokvE3NjZJeK00VAh/W6qbsfl7P2z/1b5OcGRBoKjDQRFSb9vJOh4lUrJjhuZGzB79myysrKYPn0606dPJzExEetNFi93797N73//e0JCQjh69ChpaWkAHD16lIULF/Lss8+ycOHCYT+vGLRvuPb2dj788EPGjh3Lb3/7WxYuXMibb74pCzcyMgOI4FFm47L2bwlEYISe1d+dzLb/PiuJN8DXH+VjtdiZuTr5tk/IQ0JCCA4OprGxEZA6p1zbYWmkolQqmTVrFl999RUglUvNnTsXnU7n5bi521XlhybH8NWlGnbnSEHF9W02CIzBr6MFg7kWhdi/5T1OUeBqs5YJIdL/Xqy/ndI2NXfuGxpaKlsaqGxpICYwlIyIOAL8esK/uzNwzocaSCzZidFcimoYCDcuO+TtszBuRQAKlYBapyBtsT+Xd5jp538HmX7EYDCwYcMGXn/9dfdn5t69exFFkQULFgzaODQ6FSmTw0mZHI7oEqkvb6PkYj3FFxqoKW71ykxyOUUqcpuoyG3iyIf5GEP9SBgfSsL4EGLSA1Fpbu+94hlyCvIkUEamrwgKAWOoDmOojqSsnnIrp9NFc027u8yq+/e1GVee3Cg/RxegdufzdIs5wVEGr3bgOGXHjUzv/PCHP7yt/V966SUA/uVf/sUt2oAkAH3rW9/iD3/4A6+++irf//73+3Wcg82gCTdbt26lra2Np59+mvnz5xMXF8fmzZv57W9/i0peIZGRGRAUOs9Sqf7PrgiOMvDQ30/l09+fdX+xn/6ihM52B/MfT7/tTiMZGRkcPXoUgNzc3FEj3ABMnTqVgwcPuluDnzhxggULFniJbwCuTitK/zv7zFQpFfz16am8dayEX+zMobOrzWinzoRNoyegpQqNvf+cWQClbWriA2yYNNJ9jQvu5EyZlv4z1A4+Fc31VDTXE20KIT0izisDpz40i/rQLIIbLhFS2kKl+dZtxIea9gYnxV+3kzxfehz+4SoSZukp/tr3xz6aCQgIYOPGjbzxxhs0NEgZFfv27UMURRYuXDjo4xEUAmHxAYTFBzDtwSQ62myUXmqk5GIDpZcbsFq8J2mt9Z1c2F/Ohf3lqNQKYsYEkTg+hPjxIRhDbu3M681xIyMjc+colQpCov0JifYnbVqEe7tnfk59RZtUclVhodNyY7G0w2ynwtxMxdVmr+1aVRK6id/B0F5FSGcg5DZJDp0A32lZPqyQzbF0dHS4O9M+8sgj113/yCOP8Ic//IHt27fLwk1f2bRpEwqFgqeffhqAp556il/+8pfs2LGD1atXD9YwZGRGFZ7Btq67KLO5GaYwHQ/9w1S2/+EcDRUWAC4drMDWbmfJxszb6k7gKdwUFxePmrbgAFqtllmzZrF//35ACh2dNWsW6usmJ1bAcP0B+ohCIfDMnETmpoXyvQ+yyS5rBsClVNMSHI/O0oihrR6h384GBC41+jEnUhIBTBoX0WEOKusGp/PMQNLtwIkyBpMeEUegvifsuTFkHFNCIL6pkaulhTS2NA/dQPtAXZ4NQ7iKiDHS+y1irBZLnYO6PHky7MsYjUY2btzIpk2b3OLN/v373eLNQAUD9wWdv4aMmZFkzIzE5RKpKWql5EI9JZcargs4dthdUrlVV0hqUJSBxK6A48hUE0rl9d8jsuNGRmZw6C0/RxRFOsx2GivbJFGnqt3997UirSdWhxJrUDrNQelUuOD8f50FwM+/y6HT5czpdurojbKgI3NzcnNzsVqthIWFERsbe9313dU958+fH+yh9TuDItyUlZWxb98+Fi1aREyM1DZ4w4YN/OIXv+CNN96QhRsZmQFCGIBw4t4wmLSs+d4UPvtjNjVFUv1z3qlarB1O7n9xPOo+WuDj4uLcbcGdTicFBQVkZmYO2Lh9jRkzZnDkyBHsdjsdHR2cOXOGWdOne+1zN52lPEkJ8+ejb80m6ztv0m4IdYfodhiCsWkNBLRUoXb0z301WVWUt6mJ9ZcmVsmxdmobVTicw9d140l3iHFEQBDLQvWYjYnu60KDggkNCqahpYm8kiLqmxuHbqC3oORoO4ZgJf7h0qlB4hw97U1OLPW+29pcxtt5U19fD0jNIERRZNGiRUMq3nSjUAhEpZiISjExa00KbU1WSi9JuThlOY3XBaV2h6Oe3VWKxk9JXGZXu/FxIRhMkrgoKJWgUIBLcvPJwo2MzOAhCELv+Tlegk67JOr0QdDpbLNTmddMZV6z13a3oBNlIDTOn3HzYgbqIckMU7q7LPYm2oBUWhwYGEhTUxNms5mAgIDBHF6/MijCzVtvvQVIYk03GRkZTJ06lc8//5yGhgZCQkIGYygyMqMKhW7gHTfd+BnUrP7uZHb+v/OU5TQBUHqpge1/OMfyv81Cq7+1w0KpVJKWlsaFCxcASUUfTcKNXq9n+vTpfP311wB8/fXXTJ8+HZRKcEoTm/4SbkAqnTJYGtFYLZhNUThV0oTIqdLSHJyA3tKA3tLQL0VNV5q1ROrtqBSgVknizdWSkbWSVmNuYkLpX7AEpVKc+CAtphT3dSGmIEKygmhqbSavpIjapoabHGloEF2Qt7eN8auNqHUKFCqBtCUGLn5ixmGV/di+jKd40x1YfPDgQVwuF0uWLPEJ8cYT/yAtmXOjyZwbjdPuorKgmZKLkuOmuca7RM/W6aTgTB0FZ6THFRxtIDYjiNixwTh1ASgtLYBcKiUj4wvcStAp3byDsi1fYtFH0RGVTntA7E1LrjwFnZAYWbi5Fl/rKgVQUFDAuHHjer3u0qVL/X5/bW2Sg1Ov199wH4PBQHNz87AXbgalL+sbb7yBXq/n4Ycf9tr+9NNPY7PZePfddwdjGDIyow5hEEqlPFFrlSz/24mkTAlzb6vKb+GT/zp7XbeRG5GRkeH+Oy8vD5drdCWkzp49G6VSciiZzWays7O9Oku5rP0/OVE7rAQ1lKCzNEr9fAEEgXb/UJqD43Eo776syepUkNfS8ziiwxz460bea+sQlIQ0XWHK2ZfIz95/ncMmyBjIjAmTmTt5BhEhYTc4ytBhs4jk77MgdrV41vorSV1kGM6RRKMGf39/nnnmGcLCev6vDh8+zO7duxFFHzy770KpVhA3Jpi5j6Sx/qezeOpns5j3WBrx44J7LbVtrLRwfl85n//veQ5O+xmnJn+fwsQVVBa14bSPvM8UGZmRQLegExkmEltxgIy895jTsZNv/HYuz/56Lqv/bjLzHktn/PwYotMC8TNcf94RHH3nZeIyMiOBAXfcHD16lLy8PNavX4/B4P2Ge+KJJ/j7v/973njjDf7v//2/Az0UGZlRh2c4MXY7ot1+XS5Af6NUK7j3+fEceOcKl49UAVBf1sbW35xm1Xcn3TJ0MjU1FYVCgcvlor29nfLycuLj76zF+HAkICCAyZMnc+rUKUCaeN3n5wft0iq02M/dwboREPFvq0NjbcNsisLVJdY41DqaQhLxN9fh19F8V/P3olYNcf52/NUuBAHSEmycvTK8g4qvxdG1HiIA1uZqjrU4CDKaSItPJjy4x1kaGGBk+riJtLaZySstoqq+dohGfD2tVQ7KTnUQP0NavTLFqImd4kf56YEXf2XuDn9/f7fzprZW+p86cuQIoiiybNkyn3Pe9IYpTE/WIj1Zi+KwW51U5DZJbpyLDZgbvf8HRUFJqymZVlMyxVubUG0/SFRaILEZQcSNDSY01h/hNkPyZWRkBg5B7dEO3On0cOhoiM0I8tq3vdVGY1fZZGOlhcgU07WHk/FBTT4lJWVAnDU3wt9fyhdsb79xQwWLRcrgHM5uGxgE4eaNN95AEASvMqluwsLCuPfee9m5cyeXLl26oa1KRkbmzlBc25HIakU5wMINSHkGC58ag1av5uwuqfa0pa6Drb85w6rvTCI46sarJn5+fiQkJFBUVARI5VKjSbgBmDNnDqdPn0YURZqamiiLjSG2q+Vvf5ZK9YbG3kFQQzGWgHA6dV0nSYKCNmMEVq0/Aa3VKF131sJT7AoqnhkhfbkGBriICHZS0zhyOgvaBaX7REqFtPrf1NrCiYtnCQwwkhaf5OW0MfoHMDUzC7OljbzSIirraoZi2NdRdcGKIUxFSJJUzhYzSYel3klTiZwj4usYDAaeeeYZ3nzzTWpqpP+nr7/+GpfLxX333TcsxJtu1FoliVmhJGaFIooiLXUdlF9povxKI+W5TddlZjjsLsouN1J2uZGjHxegNaiITZfKqmIzgjCF64bV45eRGXEoezIPRcfNzyVuJOjIyHjSPUcoLy/v9XqLxUJzczNBQUHDXrgZ0FIpq9XK+++/T1RUFEuXLu11n6effhpRFHnjjTcGcigyMqOSa1tJD2RA8XX3LQjMeTiV2Wt7cj4szVY+/u0Zaopbb3pbz3Kp3NzcARujrxIcHMyECRPcly8lJroXVQaiVOpaFKKLgNZqjM0VCB4ijV1roCkkkU6/gDte5KnvVFHX1HPilhJnR6nwwSWjO8RBz2NT4x242mxu5eSlbA6dOU71NQ6bAIM/U8ZOYOG02SRExaBUDEol800pPGSho6nnMaTMN+BnGvpxydyabvEmMjLSve3YsWN88cUXPl02dTMEQSAwXM/4+THc/8IEnvvNPGaXvU5KwccEN172nA+6sVocFJyt48DmXN75t2O8+c9fs+fNHHKPV2NpGVgRXEZG5noEVc/ioeiQFwJk7p6MjAy0Wi11dXVUVFRcd/2ZM2cAyMrKGuyh9TsDusx59uxZJk2axOrVq2+4wrF69WqWLFlyQ5VMRkbmzhGuaaU9GDk31zLlvgS0ehX7N+eCCJ0WO5+8dIZ7nxtH0sTeMz4yMjL44osvAKivrx+VAeZz5851ty5s1uupjI4mprKyqx14/3Hy9e/d9Pr6Nis/2nqBry5LK/eiQonZFM28uZH8fM0Egg23HzB830O/JNjkRKkArUYkMdpOQfnICCp2CD3CRrfj5lpa2sycunyeAIM/aXGJRIVFuL8j/fUGJqSNJSMxldLqCoory+gcYJfVjXDZ4eqeNsavMqLUCCg1AmlL/Ln0aSt3aLqSGUT0ej0bNmzgrbfeoqpKKls9fvw4oijywAMPDHvniaAQMNGEruwUCWW7ifrT/2KJm+R25NQUm91ZTd20NVq58nUVV76Wno/gaAOxY4KIHRNMTFogGt3Icf/JyPginqVS2OUvkrtCxPdKpYZgPDqdjsWLF7Nz5062bNnCd7/7Xa/rP/zwQwBWrlw5+IPrZwZ06WzWrFns27fvuifQEz8/P3bt2sXmzZsHcigyMqMSQRAQPHJuXIPouPFk3LwY7n1uHAqlNFFw2Fx8/v8ukL23rNf9g4KCCA8Pd1++evXqoIzTlwgPD2fMmDHuy5czM6Xv6EEW30L9tfzl6an89tGJBGh7Trg+v1DNspcOsO1cxW2v4HdaFZRV9RwrNsKBzm9khIrab+K4uRazpY0zVy5y4NRRymuqvJ5HjVpNalwii2fcw5SxEwgyDk1tf2eLi4KDFvdlfZCS5HlyQORwoVu8iYqKcm87ceIEn3/++bB13njimdmmcDmISQ9i5qpkHv7BNJ7/3Twe/NssshbH3jDUtLHSwvm9UtDxK98/xEe/PsXxTwupuNokBx3LyAwAgmeplPPm35EyMn3le9+TFiF//vOfk5eX595+9OhR/vKXvxAYGMhzzz03VMPrN+SlBRmZEY7Czw9nl2Az2JN+T9KmReBnUPPFXy5g63SCCIc/yKO1voN7HklDcU2AZHp6ujtcMzc3l9mzZw/FsIeUuXPncuXKFQAaQ0OoDQ8nehBKpa5FEAQemRrLrORg/mHLeY4WSq2sGyw2vvPeOT45W8HP104gJvDmwdOelFSriQx14qcVUSggLd7G+avDP6jYIfSclN7IcXMtbR3tnMu9xNWSQhKj44iPjEalkr6eFYKC6LAIosMiaG5toaiyjMq6mkGddDeV2KnM7iR6olR6GZKsoa1OXikdLuh0OrfzprKyEoCTJ08iiiIPPvggCh8oy7tTBI2HU8/uXXah0alIygolKSsUAEuLlYrcJsquNFGe00hbk7eTTXSJVBe2Ul3YyqnPi1GpFUSlBRKdFkh0aiDhiQGo1L3UY8nIyPQdlUc48S0ybmRGLzt27OBnP/uZ+7LNJp37zpo1y73txz/+McuXLwdg6dKlfOc73+H3v/89kyZNYtmyZdhsNnbt2oUoirz++usEBgYO6mMYCGThRkZmhCPo/KBJ+tvVMbRdYeLGBvPQP0zlsz9l09YonTSf31uOuaGTZd8Yh1rbc1KckZHB4cOHASgpKaGjowOdru/CwEggNjaW5ORkCgsLAcjJHMvEISqbAYgN0vPO8zPZ9HUxv/kylw67tFq2L7eOZS8d4Af3ZfD07ESUfeji4nIJ5JepGZ8qfRmHmFyEBjqpbx7eX0u347i5lvbODi4XXuVqSQFxkdEkRsdh0Ond1wcaTUw2mhiblEZxZRklVRXYBykjoOx0B4ZQJaYYyeEQP11HUVERSUlJg3L/MneHp3jTnQFw6tQpXC4XK1asGLbijafjxmW7uahtMGlJnxFJ+oxIKei4toPyXEnEKb9686BjAKVKQXhiANGpgUSlBRKVbJJLq2RkbhM546Z/EYa/cbJX6urqOH78+HXbPbfV1dV5Xfff//3fTJo0iT/+8Y/s2rULjUbD0qVL+fGPf8ycOXMGfMyDgfyNIyMzwlH49YgdYufQlEp5EhLjzyM/nMaOP52nrtQMQFF2PZ+8dIYH/zYLg0nK5YmJicFgMGCxWBBFkfz8fK/A3tHCvHnz3MJNTWQkVa0tDGV/BYVC4Btzk1iWGcGPPr7Aobx6ANptTn6y/TLbsiv51cNZpEfcOrm/rklJU6uCIKPkTEmNs9PYosQlDl/XjWfGjbKPjpvrjuF0UlRRRlFFGREhYSTFxBEaGOy+3k+rZUxSKmnxSVTUVlNUUYrZbLnJEfsBEfL3Wxi/2ojWX4GgENiyZQsvvvgiJpPconU44Ofnx9NPP83bb7/tzhU8c+YMoiiycuXKYSneeAo3or3vk0BBEAiM0BMYIYUdiy6R+vI2ynKkblVVec04rimVcjpcVOW3UJXfAl+UIAgQEusvCTmpkjNHbxwZWV0yMgOFoPJwrTnkUimZ3tm4cSMbN24ctNsNF4bft7SMjMxt4dkSfKgdN90YTFrWfn8KiV0WdoDaEjMf/eo0DZVtACgUCtLS0tzXj8buUgCJiYmEe9iJT3W1BR9q4oL1vPmNGby0biKB+p7J09nSZpb/4RAv7bqK9ZYnZQJXSzR054fq/ETiIoe3ddq7q9TdZ2TUNNRx7PwZDp4+Rll1JU5XzzGVSiXxUTEsmDabmTPnEB4ecdf3dzMcnSJ5e9pwOaUXrL29nQ8++ACHbHcfNvj5+fHUU08RFxfn3nb27Fk+/fRTXK7hl+kiaDyEm1s4bm56HIVAWHwAU+5LYNW3J/H8S/NZ83eTmb48kZiMIFTq60+XRRHqy9o4v6+cL1++yOs/OMzb/3qUvW/mkPN1FS117SMiR0hGpj8R5FIpGZk7RnbcyMiMcLzCiX3AcdONWqvkgW9N4MiWPM7vk1Z/zY2dbP3NGe5/cTxxY4LJyMjg3LlzAOTl5eF0OlH21vN1BCMIApNdIl92XS7s7KS2ttYrvHmoEASBh6bEMj89jJ99dplt56T8DLtT5A978vj8QhW/fGgC0xKDb3iM9k4FFTUqt2CTEGWnukGJ1TY81xXsnhk3orPfIntaLW1kX71MTlE+CVExJEbHotX0dI0LCw0jLDQMi6WNoqJCysrLcDr7/6TYUu+k+Ot2d0BxRUUFX3zxBStWrOj3+5IZGLrFm3feeYfS0lIAzp07hyiKrF69elg5bwR1j8Pldhw3t0KpVhCTEURMhuRvdDpc1JWaqcxv7nLdNGNtv/791VLbQUttBzldXasMJo2Uk9PlygmJNiD0oZRURmbEIgs3MjJ3jCzcyMiMcDwdN0MZTtwbCoXAvMfSMYbqOPxhHohg63Dw2R+yWfjUGFKmpaBUKnE6nVitVkpKSkhOTh7qYQ86CWo1puZmWrqC1Q4fPsxDDz00tIPyINRfy+8fn8yaSTH888cXqGyR/s/ya9t45P8d5elZCfzg/gwC/NS93r6oUk1EiAONGpRKqWTqUoG21319Hc9w4tvNuOkLNruNvNIiCsqKiQqLJDkmDlOA0X29weDP+PFZZGSMpbSshOLiIjo62vt1DHVXbfiHqwjPkF6jU6dOERMTw+TJk/v1fmQGDq1Wy/r1673Em+zsbERRZM2aNcNGvPFy3PSjcHMtSpWCyGQTkckmuFcKMm6sslCV30xll5BzbdgxgKXFRv6pWvJPSUH7Wr2KyBSTW8gJTwhAqRoez7WMTH/gmXGDLNzIyNwWQy7ciKLI2bNnKSsrw2g0MmfOHLTa4XnCLiPjiwg63yuVupaJS+IICPFj16uXcNhduFwie9/MobEqnqSkZPLzpdZ+ubm5o1K4UWg1jL2cw7E5UmetCxcusHDhQoKDb+xkGQoWjQnnq+8t4Ldf5vLG0WK6qwTeOlbCzotVfGdJGo/PiL/udk6nQEGZhrHJUqlDeLCTyjonTa3Dz11l96hA7mtXqTvBJYpU1FZRUVtFsCmQpPBoIiOjEARpNV+tVpOSnEpyUgo1NdUUFRfS0FDfb/dffLSdSYuS3F2KPvvsM0JDQ71KcGR8m27xZvPmzZSUlABw/vx5HA4Ha9euRa3uXWj1Jbwybu6iVOq271chEBLjT0iMP+MXxCKKIuaGTknIyZPEnOaa6wVTa7uDkgsNlFyQOvOp1Aoiko3ujJzIJJNXSL+MzEjDM+NGdtzIyNweQyrcFBYWsmbNGi5evEhAQABtbW2cPHmSKVOmcOTIEcaPHy+HHsrI3CUKradw078r7/1J8qQw1nx/Cjv+lE2HWVo5PberFGN0LIKrCFHhICcnh/vuu2/YrAb3FwqtH3FlZVw0j6ctIABRFNm/f79PuW668deq+MmqcayaFM0/fnSeqzVSZlF9m40fb7vEa0eKsRiN6FtbvaqIqhuURIcrMPlLYkdGgo0Tl/xwuYZXWcFAO256o7GlmcbyCnQ6PYmJScTHJbgn3YIgEBkZRWRkFK3mVoqLC6moKMfpvLuxiU5Yt24df/3rX2lvb8fpdLJ582aee+45QkNDb30AGZ/AU7wpLi4G4PLly7S3t/P444/j5+HY9EW8hZuh61AjCALGUB3GUB0Zs6IAaG+1UVXQTFVeC5X5zdSXmbk28sZhd1GR20xFbjMguVBD4wOISjZJgk6KCf8g334NZGRuBznjpp+RY7RGFUM6+3nhhRcwmUyUl5fT0NDgFeL29ttv80//9E9DODoZmZGBp+NG7By6VtJ9ISLRyCM/nEZIjMG9rbXSSVDDFFR2A62trZSVlQ3hCIcGQatFIYpkXrrs3nb+/Hlqa2uHcFQ3Z0p8EJ/9f/P43rJ0dOoeMaOo3kJ9QhzVKUl06vUet7g+qDg5Zvi1CvUMJ77TrlJ3SkdHOzk5l9i95ysuXjqPxdLmdb0xwEjWhEksWXIvY8eOQ6fT3+BIfSMwMJBHH33ULaR2dHTw9ttv09bWdotbyvgSGo2GJ598kpSUFPe24uJiXn/9dVpbW4dwZLfGS7jxsdbCeqOGlMnhzF2XxrofTef5/5rPym9PZNqDiUSnBfZaIuVyidQWt5K9t4yvXrnEG//0NW/80xG++OtFsveUUV3UgtMx/EKkZWTcKD08Ay6XHOAtI3MbDKlwc/z4cf7lX/6F6Ohot727m0WLFrFv374hGpmMzMjB03EjWn2zVMoTY6iOh38wjdRpPeG7SqcfgQ2T0HaEc/HixSEc3dAgaKUAzoSSEgI9nBJ79+4dqiH1CY1KwbeXpLH/HxbyxIw4PDM5bXo9NSlJ1CbEY+sqj21rV1BW1XNSFxvhwGgYXu1CPduBD2Sp1M1wOh0UFxexb/8eTpw4Sm1tjdf1GrWGlORUFi9ayrSpMwgLDbvj+0pKSmLt2rXuy83NzbzzzjtYrb4tEst40y3eZGVlubfV1NTw6quvUldXN4QjuzkDFU48EGj8VMRnhjBzVTJrvz+Fb/7XfB76+ynMWpNM/Lhg1H69l0i1NVkpOFPL4S15fPSr07z83YNs/c1pjnyUT+HZOiwt8ntNZvjg1Q4c4C7dnzIyo4khLZUKDg6mvr73mvvIyMhRubIuI9PfKDwzbnzccdONWqvk3ufGER5v5OjH+YgiCCgxtowh72ANtmV2NBrfz1/oLxRdwoZCFJnS1sberhLSK1euUF5eTmxs7FAO75ZEGP34xUNZPDc3iV99kcuuyz1CQocxgI4Af/ybmjHV1FJcKRIa5MSgExEEGJNk4+QlP0RxeJRM2Rn8UqmbUVtXS21dLQaDP4kJScTFxaPqsqp7llG1t7dTXl5KWXkpHR23131uwoQJtLa2smvXLgCqqqrYsmULTzzxxKjrAjecUSqVrF27loCAAI4cOQJAS0sLr732Gk8++aRP5hd5Om6GW9CpUq0gqiukeOr9ktumobyNqoIWqgtbqClqobX++sUWp8NFVUELVQUtnOvaFhDi5w5Pjkw2EhLrj1I5ukqKZYYHwjXfCaLT6VU+JXN7CLJhaVQxpO+URx99lJ/85CcsWbKEsDDvFb+qqioCAgKGaGQyMiMHwdNx40PtwG+FIAhMvjee0Dh/vnzlIlaLdFKubongw1+fYM23p6M3am5xlJGB4NH2OaHVTNSYMVRVSe1m9+7dy4YNG4ZqaLdFangAL2+YxsxH/0hzZARWQ1epjiDQFhyEJdBEQH0DOSU1TM3oQBDAoBNJjLZTVDE8XmvPjJuhctz0hsXSxqXLF8i9mkNsbByJCcn4+/u7r9fr9aSnjyEtLYP6+jpKy0qoqanG5erbY5gzZw4tLS2cOHECgPz8fD777DNWrVp1naNWxncRBIFly5YREBDAF198AUglcG+88QaPPvooGRkZQzxCb7xKpXzccXMrFAqBsPgAwuIDyFokifGWFis1ha1UF0piTm2JuddSKXNDJ+aGTvJOSqK4SqMgPMFIZEqPmKPzHx6foTIjnGtFGocD5KY0MjJ9YkiFm5/+9KccOnSIrKwsvvWtbyEIAi6Xi/z8fP7zP/+TefPmDeXwZGRGBIJfzxficHHceBI3Nph1/zSdzb88iLNNOklvKrey5Rcnuf/FCUQkGm9xhOGP4HlSY7WyZMkS3n77bUAKeS8sLBxW3bb82tuJKCyiwxhAU2QEjq7HJyoUtIaHcdkRRHBrHskmKSslPtJBbaMKS4fvryA7Bqmr1J3icEhlVMXFRYSFhZMQn0h4eIQ7p0YQBMLCwgkLC8dms1FRUUZpWSlm882zTgRB4P7778dsNpOTkwPA2bNnMZlMLFy4cKAflkw/M2vWLPz9/fn4449xOp04HA7ee+89VqxYwdSpU4d6eG68gk6HMJx4oDCYtCRPDiN5srS46XS4qCsze4k5vbUhd9hcUnervGb3NlO4zsOVYyI42oBCIYuqMoNLb44bGRmZvjGkwo3BYODQoUP8x3/8B//zP/+DKIrMnDkTgLFjx/Kb3/xmKIcnIzMiUPjp3H+Lnb6fcdMbxlAds56MYs+bl/DrjACkuv+Pf3uG+U+kk3lP9BCPcGBRaHtWSl02GykpKSQkJLhb+O7du5ekpKRh5WwQAH2rGV2rmbbgIJrDw3B1rZ67VCq+VqUT7rqAv8KOQiGVTJ25rEXEtx+jt+PGt09I6+pqqaurRavVEhsTR1xcgpcLR6PRkJSUQlJSCs3NTZSWlVBZWYHjBiUpCoWChx56iDfffNNd6rx//36MRiNTpkwZlMck03+MHz8eg8HAe++9h9VqRRRFtm/fTltbG/Pnz/eJz5uR5LjpC0qVgsgkE5FJJiYukUrX2po6qS5spbqgheqiFupKzbic19dPtNR20FLbQe6xagDUfkoiEo1EJpuISDQSlhCAwSQ7H2QGFlm46WfkUqlRxZAXFWo0Gn7605/yr//6r5w9e5bq6mqioqKYOHGiuw5fRkbmzvF23AxP4QZg7LgMPgv5FEerGYM5BQEBp8PFvreuUFdiZu66tF67dIwEPB03otWKIAgsWbKE1157DYDy8nJyc3MZM2bMUA3xjhGAgMYmDM0ttIaG0BoagqhU4kDJ144k7tVcBcBocBEX6aC02rezjXzdcdMbVquVgsJ8CgrzCQ4OIS4unuioaJQe3T8CA4MIDAxiXOZ4KqsqKSsrRRTF6ybvarWaJ554gtdee82dYbd9+3b8/f1JT08f1Mclc/ckJSXx7LPPenUL27dvH2azmQcffNDt1BoqRptw0xv+QX6kTvUjdaoU6O+wO6krMUtiTpcrp73Vdt3t7J1Oyq80UX6lyb3NEKglPCGA8IQAwhKMhMcHoAuQS6xk+pHeSqVkZGT6hM8oI0qlkmnTpg31MGRkRhwKP8+Mm+Er3Gi1WjLGZHDp0iUcagtB5gmIdmnScPFgBfXlbdz/4vgRuWLomXEjdnXriY+PJz09natXJWFj7969pKenD/lE6k5RuFwE1tYR0NhIc3g4bcFBVLpM5DlCSVNJAkBirIPKDgOOlusnIb6C3UczbvpKY2MDjY0NXLp0gejoGOLjEggMDHJfr1SqiIuNJy42nnf+7Rhj50QxZnaU1/tOr9ezfv16Xn31Vdra2hBFkS1btrBx40ZiYmKG4mHJ3AWRkZE899xzvP322zQ0NABw6tQp2traePjhh1Grh05M9W4HLk8AAVRqpTv0GEAURcwNnV0ijiTm1Je3IbquX6q3NFsparZSlN3TOCQg2K9LyAkgPMFIWHwAfgbfFtBlfBfhmnMU2XEjI9N3BkW42bRpE1u3bqW2tpbo6GjGjx/PpEmTmDRp0rDKZZCRGY4IHsKNa5i36B0/fjyXLl3CrmmhOfQsqeoF1JVKq8DVhS188J8neeDFCUQmm4Z4pP2LoPEslep5DRcvXuwWbmpra7l48aJXO9/hiNLhJKSyCmN9A82R4Zw0xRGjbEEv2FEKIqkpTg40xWOqrUdrafe5wimHj3WVulMcDgelpSWUlpYQEBBAXFwCsTFxaDz+F1tqOzj2SSHHPy0iYXwImfdEkTA+BIVSQVBQEOvXr+f111/HZrNht9vZvHkzzz33HMHBwUP4yGTuhKCgIL7xjW+wefNmKioqAKmr3ZtvvskTTzyBXq8fknEJGtlxcysEQcAYqsMYqiN9RiQAdquT2pJWt5hTV2rG0tz7+YG5sRNzYycFZ3vawhvDdJIzJ94oiTrxAWh0PrMWLOPLXFsq5Ri+35M+gVwqNaoY8E/Z3/zmN/zjP/4jotjzn/XJJ5+47dUBAQFkZWUxadIkJk+ezLPPPjvQQ5KRGVV4OW5us82vr5GamopWq8VqtWITLYx5UEfI+QCufC11WGpvsfHx784w77F0xs2L9okMhv7AM+NGtPa4TSIjIxk/fjwXL14E4NChQ4wfP97nXTcHdvygz/ueLW3ij1td6JuzAYhSmokxWinwT2JaQhD/d3EqC9LDbvpaL5vz87sec18Z7o6b3jCbzVy+fJErVy4TERFJfFwCoaE9z7noEik+X0/x+Xo6OzooKy6irKgQS5sZU5yWjFUhKJQCFouFX/30JS5tqcPRefvPzReNL/f3Q5O5DQwGA8888wxbtmwhLy8PgLKyMl599VWeeuopgoKCbnGE/scrnFgWbvqMWqskJj2ImPSe18zSYqWuxExtSSu1pWZqi1vpMPf+nLbWddBa10H+qVr3tsAIfVeZlZSXExrrj8ZPFnNkvBEUClAooLtjoVN2ysnI9JUB/0T9y1/+gkKh4JVXXuH++++nvr6e8+fPc/bsWffP4cOHOXz4MIIgyMKNjEw/45mPMtwdN2q1mjFjxpCdLU3iL1+5xGNPP0ZEQgCHPsjD5RRxOUUObM6ltqSV+Y+no1Irb3FU3+fajBtPFixY4BZu6urquHLlCpmZmYM6voFkcnwQL397NX98pZnGSimMebq6jHJrIKdKmtj4+kkmxJj4v4tTWTY2Ysi7pAyncOLbxeVyUVVVSVVVJTqdjtiIKOISk9EbDO59/HQ60sZmkjY2k4a6WkoLCyneW0fyMskFpwtSkbEyhJyP63E55KXC4YZGo+Hxxx/ns88+4+zZswA0NDTwyiuvsH79eqKjBzcoXs646T8MJi2GLC2JWaGAVGJlabZS2yXmSKKOmU5L789zc007zTXtXD0htSQXBAiKMhAe35WX0yXmqDTD/ztZ5u4QlErELuFGdI6MBQ4ZmcFgwIWbqqoqlixZwjPPPANAREQE48aN44knnnDvU1ZW5hZxZGRk+heFbvh3lfJkwoQJbuEmLy8Pq9XK+AWxhMT488VfL7pDGHOOVNFQYeGBF8fjH+R3s0P6PDcTbsLCwsjMzOTy5csAHDx4kLFjx44YtxFI3Yo2rFvLn/70J+x2O36Cg6mqMr52JAFwoaKFF986TXqEP/9nUSorsqJRDpGAYx+G4cR3QkdHB1cvXeTq5UuEhUcQn5xCZHQMCg8bfEhYOCFh4djtdpqvVqBKasShaiMgSkPqfUFc/bxRtnkPQ5RKJatWrcJkMrF//34ALBYLr7/+OuvWrSMtLW3QxiILNwOHIAj4B/nhH+RH8iSpHXl3Xk5tiZm60tYuUceMreN614QoQmOlhcZKC1e6OlkJCoHgKIPbkdP9o9XLmTmjCpUKut+vsuPmzhFB8LXvUF8bzwhjwIWbhIQEAgMDb7pPXFwccXFxrFq1aqCHIyMz6vBy3IwA4SYpKQm9Xk97eztOp5OcnBwmT55MVGog6340nS/+eoHqwlYAaotb+eA/T3L/C+OJTht8G39/4RVObLcjulxeAX/z5893CzfV1dVcvXqVjIyMQR/nQBIYGMjChQvZtWsXAOmqeowxqXxR0uNquVrTxnfeO8d/787jbxamsHZyDGrl4JaNOUZgqdRNEUXqaqqpq6lGo9EQk5BEfFIyRo/vfbVaTZg6ERoScaja6NRVE5JYR+J8J8UHWoZs6DJ3jiAILFy4EJPJxKeffoooiu4co5UrVw5e+3c5nHhQ8czL6e5iJYoiLXUdPWVWJWbqSs3Yrdc7DkWXSENFGw0VbV7b/YO1hMb2iDkhsf6YQnUIQ+yglBkYBKXSPb+Xw4llZPrOgAs3jz32GK+99houl8vncxdkZEYi13aV6q2F73BCqVSSmZnJqVOnALh48SKTJ08GpFama743hUMf5HHpoBSg2WG288l/nWPmqiSm3JswLE8EPTNuAESbzSt0OjIykoyMDHJzcwHJdZOenj6sX+femDVrFufPn6emRrLij3fm87d/+yT/e6CILy5Vu/crqrfwgw/P8/vdeXxrYQouQUAhDs4ykGc4sRIRQRQRR9jrcCNsNhtFebkU5eUSGBxMfFIK0fEJXl2HVA5//M2pGMwpGOOa8V9QwpWv83HIbolhyeTJk/H39+eDDz7AbrcjiiKffvopra2tLFiwYMA/g7wdN77bbW4kIwgCgeF6AsP1pE2PACSBprm2XRJxSszUlkoByA5b72J2W6OVtkYrxed7ulmptUpCYrpcOXGSmBMS7Y9aK5daDXcED2emHE4sI9N3Bly4+Yd/+AfefvttfvKTn/Dv//7vA313MjIy1+A5wYeuSb92eLfMHj9+vFu4KSwsxGKxYOjK2VCqFCx8MoPw+AAOvJeLyyEiukSOfVJI+ZUmlm7MxBA4vB7/ta+XaLXCNa/r/Pnz3cJNRUUFBQUFpKamDtoYBwOlUsmKFSt49dVXAaivr6e5+CL/7+n5XK0x86d9+WzPrqS7y21Fcwc//uQiyhnjCCqvwVTVgMI1sC4Yh+C9QKHCiX1wGjj6FM2NjTQ3NnLp3Bmi4uKJT0omJCzcfb2AgMYWRFJEEAmrJ1BTWUlFaQm1VZU45RXYYUVaWhrPPvss77zzDhaLBYD9+/fT0tLCihUrUCoHbqItl0r5JoJCICjSQFCkgYyZUicrl0ukqdpCbbGZ+nIzDeVt1Je3YW3v3Slltzq7ul55uPIECAzXu1053Q4dQ6B2xC1UjGg8QsXlUqm7RC5NGlUM+Nnk2rVrmTZtGv/xH/9Bbm4u//qv/8q4ceMG+m5lZGS6UFwr3HR0wDAXbuLj4wkICMBsNiOKIpcvX2b69Ole+2TOjSYkxp8vX76IuVEqESu/0sR7Pz/BkmfGkjghdCiGfkdcK9y4rFaunQrFxMSQmppKfn4+ILluUlJSRtzJbFxcHNOmTXMLdwcPHmT8+PGkRwTz+8cn892l6fx5fz5bz1Tg6FJwnFo19SmxNMVFEFhRh6myDuUABSLar3ll1LgYzdNJp9NJeXER5cVFGAICiEtMJjYxAZ2uJ9BYoVASFRtHVGwcDrud6opyKkpLqKup9upIKeO7REdH8/zzz/P222/T0NAAwNmzZzGbzTz66KNoB+g7R1DJws1wQaEQCImWXDMQBUhlVm1NVurL26gv6xFzWupu0AFT7AlBzj/d09HKz6D2EnJC4/wJijSgVMlOf1/Ey3EjC/UyMn1mwIWbXbt2IQgCoiiyZcsWPvzwQ5KSkpgxYwaTJ092/4SEhAz0UGRkRiXXCje9TfqHGwqFgnHjxnHs2DFAKpe6VrgBiEgysu6fp7P/nSsUnKkDoLPNzo4/nWfi4jhmr01Bqfb9EztBc32pVG/Mnz/fLdyUlpZSUlJCYmLiQA9v0FmyZAk5OTlYLBYcDgc7duzgqaeeQhAEkkIN/PqRiXx7SRp/OVDI+6fKsDkkkcapUdOQFE1TbDiBlXUEVtSh7GebtmfGDYByNOTc9BGL2cyVC9lcuZBNZEIEmfMy0NnDUIg9/98qtZrYxCRiE5OwWa1UlpdSWVpCQ13dEI5cpi8EBQXx3HPP8e6771JWVgZAfn4+mzZtYv369fj7+/f7fcqOm+GNIAgEBPsREOxHUlbPYoqt00FDhYWGcrMk6pRLuTg3KrXqtNipyG2iIrfJvU2hlFw/oXFduTnRkktHb9T0egyZQUTlWSolO25kZPrKgAs3eXl5ZGdnk52dzblz58jOzqawsJDCwkLee+8992pwTEwMkydPZtu2bQM9JBmZ0YVaDQoFdLde7LjBStYwY/z48W7hpqSkhJaWFkwm03X7+RnU3PfN8Vw+XMnhD/Jw2KXnIXtvGeW5jSzZmElYXMCgjv12EQQBQaNxCzbXdpbqJj4+nsTERIqLiwGpXOGZZ54Zca4bnU7H/fffz0cffQRAQUEBFy5cICsry71PbJCen60Zz/+3OJV7/2YzLdGhiF2rfC61isaEKJpiwgmsqiewvBaVvX9OHp14C4HqEdYSvL+oLqmhzdpE5towtK4g/DrC0XSGoPA4LdFotSSmpJGYkkZHezuHP8wjbVoE4QkBI+5/eqSg1+vZsGEDW7duJScnB5C6i7788ss8/vjjREVF9ev9eQo32GThZqSg8VMRlWIiKqXnO93lEmmt66Cu25lT0UZ9WRuW5t6/D13OniDkXI/tugA1ITGSkBMcYyA01p+gKANquU35oCEoPUul5O/Iu8HnukrJDCgDLtykpKSQkpLCQw895N7W0tLiFnG6BZ3Lly/z2WefDfRwZGRGHYIgIPj5Iba3A5LjZiQQExNDUFAQTU3SCtu5c+dYsGBBr/sKgsC4eTFEpQTy5SsXaayUchgaKix8+MtTTF+exJT74lEMcgei20HQat3Czc26gy1YsMAt3BQXF4/IrBuQhLtz585RUFAAwOeff05CQsJ14l240Y+wokqCy2poig2nJToMV9dqn6hS0hQXQXN0GKaqeoLKa1Hd5eRPFAQcKNwdpUZFZ6k7pK3aRt5XDaQ/KGLXNoGoQGgy4SwNJDQs2isbRafXk727jOzdZRjDdKRNCydtekRX2YWML6FWq3n00Uf58ssvOX78OCCd97366qusXr2aCRMm9Nt9Ceqe01jZcTOyUSgEAiP0BEboSZsW4d7e2Wan3sOZU1/eRlOVBZez9xlth9lO+ZUmyq/0uHO6s3NCog0Ex/gTGiOJOnJnq4HBsyumHE4sI9N3hiQx0WQysWDBAq9JltPp5MqVK0MxHBmZEY9Cq8XZJdyII6AlOEhizKRJk9i3bx8g5SnMmzfvpt3rgqMNPPqP0/h6awEX9pcD0qrc8U8LKcquY+mzmQRFGm54+6FE0GrBbAZuXCoFkJiYSFJSEkVFRQDs3r2b5OTkEdfVTxAEVqxYwZ///GdsNhudnZ188sknPP30070+VqXDSWhxFUFltTTHhNIcE46ra9InKhU0x4bTEh2KsbqBoLJa1NY771AjCzd9p6mgk+L9LSQtCgTBhRjchFWoY9+2k4QERROTkEBoeITXa9pa18HpnSWc3llCSIyB1GkRpE2LwBSmG7oHIuOFQqHg/vvvJzAwkK+++gpRFHE4HHz00UdUV1ezZMmSfvlMEjxCTuWSi9GJn7+a2DHBxI4Jdm9zOlw0VVt6yqy6Sq06zDcQ9zyycwrO9pRlqjQKgqP9CYkxSC6dGOlvnb9cbnVXeAaWu2ThRkamr/hMqwulUimHFsvIDBCenaVGiuMGYNKkSezfvx9RFGlubqaoqIiUlJSb3kalUTL/8XSSJoay980c2pqk56O2xMz7/3GS2WtSyFoU63OrbAqNxl10I97EFSIIAkuXLuXll18GoLq6mosXL3qVEY0UgoKCeOCBB9wltkVFRZw4cYJZs2bd8DZKp5OQ0hqCyutoiQ6lKTYcp0YqtxAVClqiw2iJDCWgtpHg0ho0nbf/fnEIShClSaRKLpW6JTUXLAgqgcR5kltKF6QibaWJy1tLKC8pQqPVEhUbx32PLaUqv8Xrtg0VFhoqCjm+rZDwRCPp0yNInRo+7DrHjUQEQWD27NmEh4ezZcsWOrsWDY4cOUJNTQ0PP/wwOt3diW1eGTeycCPThVKlIDQ2gNBY7zLo9lYbDZVdQk6lhYbyNhqrLDjtvQvsDpuL2uJWaotbvbbrTRovISck2p+gKD0qtVxu1RcED3ezOECNAkYNcqnUqMJnhBsZGZmBQ+ERbnujfJThiMlkIi0tjatXrwJw5syZWwo33cSNDebxf53J4S15XPm6CgCn3cXhLXkUnqtjyTNjMYb6zgq+Z0CxaLv5axgTE8O4ceO4dOkSAHv37iUzMxOVauR95E+aNInc3Fy3Y7PbYRQeHn7T2ylcLoLKazFV1tEaGUJTXAQObddzrBAwR4ZgjgjGv76ZwIo6/Fot9FXKc3jk3MjhxH2j+mwbCiXEz5HEG32ImrFrQri8tR6b1UpJQT4P/f0PMTd2kn+6lryTNdSVmr2O0T3BOvxhHjFpgaRNjyBlcjh+/ure7lJmkEhJSeGFF17g3Xffpa4rZDo/P5+XX36ZJ554grCwsDs+tqfjBpcL0eXyKsOQkfFEb9SgNwYT5+HO6c7OqS9v8xJ1Wus7bjgpbm+x0d7SSNnlRvc2QSEQGK7zEnSCIg0Yw3QofGwhaMhRyI4bGZk7YeSdxcvIyFyHl+NmhJRKdTNlyhS3cNPdachg6Fu5k1anYsmGsSRPDGXfO7l0tErlMZV5zbz3sxPc80gqmXOjfSII1bMleF/Et+7OSy6Xi+bmZk6ePMns2bMHcohDgiAIrFy5krKyMneXqY8//pjnnnuuT0KVwiUSWFmPsaoBc0QwjfEROPy03QenLSyItrAgtK0WAivqCKhvRrhFi2rJcSP9LZdK9Z3KU20olAKxM40AGMI0jF0dSs4n9Tht0hMaEOzH5GXxTF4WT3NNO3mnasg7WUNTdXvPgUSouNpMxdVmDr57lbjMYFKmhJOYFSKXOAwRwcHBPP/883z88cdukbWxsZGXX36Zhx9+mIyMjDs7sMpblBMdjuu68MnI3AzP7JzUqT2Cv63TQWOVhcYKC/UVbTRWSIHIVkvvzi7RJdJU3U5TtXercqVKQWCEjqAoA8FRkpgTFKUnMFw/etuVy44bGZk7QhZuZGRGAYKfx6T/Dko/fJm0tDT8/f1pa2vD5XKRnZ3NnDlzbusYSRPDiEwxcWBzrrttuN3qZP87uRSeq2fx02OGvPTCS7i5ScZNN8HBwUybNo0TJ04AcPDgQSZPnozfNe3hRwIGg4HVq1ezefNmQOpic+DAAZYsWdLnYyhEEVN1A8aaBszhwTTGRWDX9zxXVqOBGqOBequNwMp6TFX1N2wl7um4kYWb26P8uBmFSiB6qlTi4B+pYcyqEHK2NVy3b2CEnunLk5j2YCINFRa3iGNu6BGnXS6RkosNlFxsQBAgKjWQpImhJE0MkzNxBhmtVsu6des4ePAg+/fvB8Bms/Huu++yaNEi5s+ff9siuWc4MQB2O8jCjUw/oPFTEZlkIjKpJ/BeFEXaW2xd3aos0u9KqdzK5ehd0Hc6XF37Wry2CwoBU5iuS8zRu4WdwEj9iO9wJciOm/5DLpUaVcjCjYzMKECh7ZmA3qrMZrihVCqZPHkyhw4dAqRyqdmzZ9/2BEDnr+G+b44n/1QtB97NxdouraqVXmrg3X8/zvzH00mbHjFk7htB07Oy7OpjcO78+fM5d+4cNpuNjo4Ojhw5cltixnAiPT2dqVOncvr0aQAOHz5MWloa8fHxt3UcQQRjTSMBNY1YQkw0x4TREdiTk+DUamhIiqYxPpKA2kYCK+rQtnu72BxCz0mpnHFz+5QeaUVQCkRNkjpGBURryVgZgs1mQ9PLpFwQBEJj/QmN9WfW6mRqilvJO1lD/qla2lt73iuiKLnpKvOaOfJhPsHRBpInhZE0MZSweLnF+GCgUChYuHAhkZGRbN26FVuXCL1v3z6qq6tZs2YNWm3fRXLhGlednHMjM5AIgoAhUIshUEv8uBD3dqfTRUtNh1epVWNlG60NnTecWIsu0R2I7H0nYAzx63LmSKJOcJT0t1Y3QqZtsuNGRuaOGNBPgLKyMs6ePcuYMWNIT0+/4X47d+5EFEUefPDBgRyOjMyoxdOtMdJKpQAv4aa+vp7S0lISEhJu+ziCIJA2PYLotED2vX2FkovSKr+13cGu1y5TeLaOBU9moAsY/BVdheb2SqUA/P39mTNnjnt1++jRo0yfPh2j0TgQQxxy7r33XgoLC2lqakIURT7++GO+9a1v3dGxBMC/oQX/hhasBh1NMWG0hQchduVniEoFrVGhtEaFomtqJbCiDkNjKwKy46Y/KDnYgkIlEDFeKns0xWp5//33efzxx1Grb5xZIwiCe5X8nkfSqMxrJv90LcXZdVhavAXPxkoLjZUWTn1ejH+QlsSsUJInhhGdHjh6SxgGiTFjxvD888/z3nvv0dgo5YTk5OTQ0NDA448/TnBw8C2OICELNzK+gFKpIDjaQHC0watVucPmpKmmnaYqC03V7TRWWWiqstBS24HLdSNFB1rrO2mt73Sfg3RjMGkkMafLnRMcpSco0jAk5yR3g+y4kZG5MwZUuLHb7axZs4ZFixaxZ8+eXve5cOECy5cv54EHHpCFGxmZAUIxgkulQCoL8myBfebMmTsSbroxBGpZ/n+yyPm6isMf5GG3SicWBWfrqMxvZtFTY0iaeOeBmnfC7ZZKdTN79mxOnjzpzn85cOAAK1euHIghDjlarZaHHnqI1157DVEUaWpq4quvvrr741o6iLxaiqOokpaoUFqiQ92dqAA6gox0BBlRt3cSWFmHxeJHt9FGFm7unKK9zSiUAmFj9QAUFBSwZcsW1q1b17f8IoVAbEYQsRlBiI+nU1tipii7jsLsepqqvMsW2pqsXDxQwcUDFWj8lCSMDyFpUhgJ40LQjJRVbh8jPDycb37zm3z44YcUFBQAUFtby8svv8yjjz5KcnLyLY8hCzcyvoxKoyQsLoCwOO/uVk6Hi5a6DpqqLJKY0yXqNNe037DDFYClxYalxUb5lSav7X7+aqncKtJAYLiewAgdgRF6jKE63xShZcdNvyAguYR9Cdm3OrAM6NlIcnIy99xzDwcOHKCsrIy4uLjr9nnrrbcQBIFnnnlmIIciIzOqEbSe7cBHnuMGpJDibuHm0qVL3H///XfValYQBDLviSY2I4i9b+ZQcbUZgA6znc//fIExsyKZuy4NrX5wOtZ4Czd9F9+0Wi0LFizg888/ByRRa9asWXfVycWXiYuLY968eRw8eBCA06dPExSqoKn+7k9eVXYHIaXVBJXV0BYeRHNMGFZ/vft6u96PutQ4/iXhb3iw+Birio6g6pBPSu+Ggt1NCEoITZee56tXr/LRRx/xyCOPoFT2PQdCUAhEJBmJSDIya00KzbXtFGXXU5RdR1VBi1c5g63TSd6pWvJO1UphyRlBJE0MJTErDP8guc14f6LT6Vi/fj27d+/m66+/BqCjo4O33nqLe++9l1mzZt28hO0a95Votw/kcGVk+gWlStHlmDHg2QfT5RIxN3TQVNXlzqm20FglOXa6F5B6o7PNTlV+C1X5LV7bBYWAMcRPCl/uEnRMXX/7B2oRhqjbley4kZG5MwZ8GemZZ57hyJEjvPPOO/zjP/6j13WiKLJ582YCAwNZs2bNQA9FRmbU4hVO3Md8lOHG2LFj0el0dHR04HA4uHjxItOnT7/r4xpDdaz+7mTO7y/n6McF7tWwK8eqKc9tYvGGscSN7Zut/27wzri5PdfU1KlTOXbsGI2NjYiiyJ49e3j88cf7e4g+w4IFC8jLy6OqSmrzPn2ejr/927/tc7exviKKIieKGnntSBFfXa6hu9lUp9qPrWkL+SR1PguNDn765AKmJwYNaIbKA/HfHbBj35BBOukv2C05b4JTJCE2JyeHTz75hLVr16K4w9bPgeF6d3eq9lYbxRfqKcqupyyn0WvF2+UUKb3cSOnlRg68e5XwhACSJoaRNCmU4CiDnIvTDygUCu69914iIyP59NNPcTgciKLIl19+SXV1NStWrLhheZwgCKBSQZfTRhZuZIYzCoWAKUyPKUxPYlaoe7soiliarV2lVu00VkslV01V7XRabvw/L7pEWuo6aKnroATvsiuVRoEpXO/l0JH+1uNnGOAFKU/HzQ1C/mVkZK5nwIWbxx57jO985zu8+eab1wk3e/bsobKykhdffLHXwEEZGZn+wSuceARm3ACoVComTpzIsWPHAMlp0R/CDUirVhMXxxGfGcyeN3KoKWoFpPKKT39/jvELYpjzUCpq7cB1glB4OW5ub3KiVCpZsmQJW7ZsAeDKlSs3dEGOBJRKJWvXruWvf/0rDocDi8XC9u3beeyxx/p1oi0IAjOTQ5iZHEJpQztvHC3mg5NlmK3SJNIlKNhr1rD3L0cZH2PkG/cksTwrCq1qZHcM6W9EF+R92cT6lyaQn58PSGXWKpWKlStX3rF4043eqCHznmgy74nGbnVSltNIUXYdxecbrpsU1ZaYqS0xc/zTQoxhOpK7OlRFpphQDNHq9UghKyuL0NBQ3nvvPVpbpc/Y7Oxs6urqePzxx2+YzSWoVD0lUnKplMwIRBAE/IP88A/yIz4zxOu6DrPNnZ3TXNtBc207zdXttDZ0It4oRwdw2FxSkHJ523XX+RnUXS3SvQUdU5gOVT90vBKUHtNP2XFz54j4XlcpXxvPCGPAhZuAgADWrFnDe++9x6lTp5g2bZr7OrlMSkZmcPAKJx6hpVIglUt1CzfV1dVUVlYSHR3db8cPijTw0N9P4cxXpZz8rAiXU/qGuniggtLLjSx9ZixRqYH9dn+eCHcQTuxJZmYm0dHRVFZWArBr1y6effbZEesYCA8PZ+nSpXzxxReAJFadO3eOyZMnD8j9xYfo+fGKTP5uWTqv/PiPvN8eRJV/z4rpxYpWvvdBNr/YeYWnZiawflY8of5y2U1fEV3SQtDmzZvdJZFnz55FqVSyfPnyfvs/VmuVJE8KI3lSGC6ni+rCFgrPSSVVrfXen52tdR2c213Gud1l+PmrScwKJSkrlLjM4BHfznegiFCNtFsAAQAASURBVI6O5oUXXuCDDz6gtLQUgMrKSv7617+ybt26XrvECSqVe64gZ9zIjDZ0ARpiAjTEpAd5bXc6XLTWd0hiTk27W9Bprm2nveXmzutOi53qwhaqC71LrxDAP0hLUJeYYwqXxBxTuA5jiA6luo8iupxxIyNzRwxK4t4zzzzDu+++y1tvveUWbtrb2/n4449JS0tj1qxZgzEMGZlRy0gPJ+4mPDycuLg4ysrKACnPpT+FGwCFUsG0BxJJnBDC7tdzaKiQVqta6zrY+rszTF4Wz4yVSajU/TtxEzxciXfS0l0QBJYtW8Ybb7wBQGlpKVevXiUjI6PfxuhrzJgxg6tXr1JYWAhIHQwTExMJCgq6xS3vHH+tinXqOpbu/isnI8eyY/7jnLL15ODUma381+6r/Gl/PqsnRvPsPUlkRo/MLl/9jVqt5oknnuDtt992T+pPnTqFSqXivvvu63cRUqFUEJ0WRHRaEPc8kkpjpYWi7DqKsuupLTF77dvZZufK11Vc+boKlVpBXGYw8eNCiM8Mxhh651lboxF/f382bNjAF198walTpwBoa2tj06ZNLF++nKlTp3rt7xlQLAs3MjISSpVCaikeeX2JsK3TQYuHoNNU3U5LrdSa3NZ5EweMCG2NVtoarZTleAckI4B/oBZTmA5jmE76HSr9NoXpvPIA5YwbGZk7Y1CEm2XLlhETE8N7773HSy+9hFKp5JNPPqGtrY0NGzYMxhBkZEY1oyGcuJspU6a4hZvz589z7733DkgpZmhsAI/+0zRO7ijizBclUr6JCGe/KqXkYgNLnhlLeEL/TcgFbc9jcN1GVylPkpKSSE1NdZeb7N69m9TU1NsKeR1OKBQKVq9ezZ///Gc6Ozux2Wx8/PHHbNy48a7La26GoNGgRGRW9WUe9C+m8ekX2XSkmI/PVWBzSKuLNoeLLafL2XK6nFnJwXzjniSWjI1AKZfb3BSNRsP69et56623KC8vB+DYsWOoVCqWLFkyYA4yQRAIifEnJMafaQ8m0dbUKYUbn6+n4kqTV2tfh93VFXxcD0BghJ74cZKQE5MW2C+lBiMdlUrFihUriIyM5PPPP8flcuFyudi+fTuVlZU88MADPZ3F1B7CjV0WbmRkboXGT0VYfABh8d7drkRRpMNsv86h01zTTktdh9tl3CuiVD7e1mR1N3PwxM+gdgs6AuNRRnag66gjoEMgSBRHrPt3wJFLk0YVgyLcCILAU089xa9//Wt27tzJihUreOutt1AoFLJwIyMzCChGQThxN+PGjeOLL77AarVis9m4dOnSgJXHKFUKZq1OITErlD2bcmiuaQegsdLCll+eYsL8GGauSUHbD+2EvTJu7uI1XLp0qVu4qaurIzs7mylTptz1+HwVk8nE8uXL+eijjwDJafT1118zd+7cAbtPhZc7ysbYKCO/eiSLH9yfwebjpbx1rIRac49r6lhhI8cKG4kP1vPMnEQemRKLaZC6lQ1HtFot69ev580333QHUB8+fBi1Ws2CBQsGZQz+QX5MWBjLhIWxWDsclF5soDC7jpKLDdivWbFurpEmPuf3lqNUKYhODyQ+M5j4zBCCovTyhOUmTJs2jbCwMD744AMsFqmF++nTp6murmbdunWYTCYEVc97RXTI4cQyMneKIAjojRr0Rg3RaYFe17mcLsyN1h5Bp6adljpJ0DE3Wm+apwNS+VWnxU5tcSswBsaMAeDMWVB9+0CPSydMhym05++AED+USh9saS4jMwQMinADsHHjRn71q1/x5ptvMn36dHbv3s2iRYuIjY0drCHIyIxavFpJj9Bw4m40Gg0TJkxwW+zPnDkzYMJNN5FJJtb983SOfVLA+b2SCwARLhyooOBsHfc8mkratIi7mqDdbcaNe6yRkUycOJHs7GwA9u3bx4QJE27YtWUkMGHCBHJzc7l48SIAe/fuJTU1lcjIyAG5P+Ea4aabEH8t/9+SNF5ckMLnF6p49XARFyp6MgRKG9v52WeX+fUXV1ieFcX6mfFMiR/YblTDFZ1Ox9NPP82mTZuora0FpP9llUrFPffcM6hj0epUpE2PIG16BE6Hi4qrTZRcbKD0UqNbzO3G6XBRdrmRssuNHCEf/yCtJOKMCyF2TJBXOYGMREJCgjv3pqKiAoCKigr++te/8sgjj3iVSsnhxDIyA4NCqXCXPSWM8w5IdjpdtDV20lLXQWtXF6vun9b6Dhy2m+fYOOwuGistNFZarrtOUAgEBEslWGEJRmavSenlCDIyo4NBE24yMjKYPn06n332GWPHjsXpdMqhxDIyg4R3qdTIzbjpZsqUKW7hpqysjNraWsLDwwf0PtUaJfPWpZM8KYwDm3NpqpYmbO2tNna9epmcI1UseCKDwAj9LY7UOzcSA+6ERYsWcfHiRZxOJ2azmePHjw+oA8UXePDBBykpKcFsNuNyudi6dSvf/OY3B0SwEtQ3f600KgVrJsewelI0p0uaeO1IEV9crKZ7wdLqcLH1TAVbz1SQHuHPEzPieWhKLCadPKn3RK/Xs2HDBjZt2kR9vVSWtGvXLlQqFTNnzhySMSlVCuIzQ9ydX1rrO6R24pcaKM9tus6N09Zk5fKRKi4fqUJQCEQmGd35OOHxAQhy6RwgOeeeffZZdu7cyenTpwGwWCy8+eabTImNJaWsDAG5HbiMzFCgVCrcbcyvRRRF2lttXqJO9ZdHaG2y06ELxa72v+mxRZdIa30nrfWd2K1ykPG1CHKp1KhiUL1nzzzzDJ2dnfziF78gICCAhx9+eDDvXkZm1OIdTjyyHTcgdSbxdFN0n+gPBjHpQTz2LzOYuTrZq8NC+ZUm3v3343z9UT62jttfFfbMuLmTcGJPAgMDmTFjhvvyoUOHaGu7viXoSEKv17NmzRr35draWnbt2jUg99VXkU0QBKYlBvO/66dy8AeLeHFBMsEG7zymqzVt/HT7ZWb+527+8aPzXKxoucHRRifdQbaegdM7d+7k6NGjQziqHoyhOsbPj+HBv8niud/NY+33JzP1/oTrsiVAmqBUFbRwYnsRH/7yFK/94DBfvXqJ3GNVtLeO7BLXvtDd/n3lypXuXC5RFDmdEM+Rufdg1WjkcGIZGR9DEAQMJi3RqYGMmR3FzFXJTDNcYNqZ3zDvyA9Zk5nLuh9N575vjmfWmmQy74kiJj0Q/yAtXKNbm8LkoHeZ0c2gOW4AnnzySb7//e9js9l45JFH0OnkN6CMzGAwmsKJu5k6dSo7duwApLbBixYtws/P7xa36h+UKqnzVNq0CA69f5WSiw0AuJwiZ3eVknu8mtlrU8iYGdnnFXVPMcDVDzlF8+bN48yZM1itVqxWKzt37uTRRx+96+P6MikpKcycOZPjx48DcOLECWJiYpg4cWK/3o+XcGPv22sVG6Tnnx4Yy/eWpfPVpRo2Hy/laGGD+/pOu4v3Tpbx3skyJsUF8vSsBJZnReHXz93LhiNGo5FnnnmG119/nZYWSdj68ssvsdlszJ8/32dKzZQeXapmrUmhvdVGWY7kxinLaaTD7O0W6Wyzk3eyhryTNQCExvkTPy6EhHHBRCSbRm3uw9SpU4mIiOCDDz6gtbUVgIrYWBqDg1nZ0EjmEI9PRkbm5nh2ldLg6DUoGcBhd2Ju6HSXXd2pY1lGZqQwqN/6gYGBfPvb32b+/Pm88MILg3nXMjKjGm+3xuiwkmdlZbmFGpvNxrlz5wZ9DKYwHcv/Txb3vzge/+Ae11N7q409b+Tw4a9PU1PU2qdjeYUT32WpFEgOlCVLlrgvX7p0idzc3Ls+rq+zdOlSoqKi3Je3b9/uDrjtL7wdN7f3ftOqlKycGM27L8xi7/cX8ML8ZAKvyT05V9bM97dkM+sXe/jPz3Moabg+F2C0ERgYyMaNGwkMDHRv27dvH7t370YUfdNLrjdqyJgZybJvjOPZX83l0X+axszVyUSlmnoVdOvL2jjzRQkf/+4sr37/EJ//+TwXD1bQ2tAxBKMfWmJjY3nxxRdJSenJu+jQ69ly+RL79u3D6ZRbDMvI+CxeXR1v/PmsUisJijSQOCGUiYvjrsvWkUF6+nzpR2ZAGfTlml/96lfs27dvyOrPZWRGI94diUZ+xg1InWc8uyUNhXADkk04ZXI4T/5kFtOXJ3qVT9UWt/Lhr06x543LWFpu/rp4iQH99BpOmzaNuLg49+UdO3ZgHeH/H2q1mscee8zt+HQ4HLz//vu0t7ff4pZ9R/DIzemr46Y3ksP8+dGDYzn2T0t4ad1EJscHel3f3G7nrwcLWfCb/ZQunIw5JgzRN8wlQ0JQUBDPPvssISE9J/dHjhxhx44duFy+nY0gKATCE4xMeyCRh/5+Ks/9bh73vziezLnRUsnANdg7nRRl13Ngcy5v/fNRNv/kGAffv0rhuTo6LaNDnDcYDKxfv55pdXUIXa+vCBw4cIA33njD7b6SkZHxMTyEadHHP5tlZHyJ0emzlZEZZQijULgBvLpJVVdXU11dPWRjUWuUzFiZzJM/mUnKFO+g5CtHq3nn345x9qtSnI7eT2L6M5y4G4VCwcqVK1F0rX61trayZ8+efjm2LxMYGCh1o+kqoWlubuajjz7qt8n93ThuesNPreShKbF8/Lf38Nn/N5cnZsShu6ZEyhIdSvmCSeSvmkt9ZiIOP80Njjay6Q6xjYiIcG87deoUn3zyybByYWh1KlImh7PoqTFs+M85PPFvM7nnkVTiMoNRqq4/dWuqbufCvnJ2/r8LvPr3h/jgP09y5MM8ii/UY+scubkvCoWCCa1mluzeg8Ejp6u0tJQ///nP5OTkDOHoZGRkekMQPD7DbtFGXEZGpgdZuJGRGQV4Cjeufpr0DwfCwsKIiYlxXz579uwQjkbCGKLj/hfGs+bvJhMSY3Bvt3c6+XprPu/97ATFF+qvu51XO/B+fA3Dw8OZN2+e+/KJEycoKyvrt+P7KikpKV6lYgUFBezfv79fji1oehw3rrtw3PTG+BgTv3goi2M/WsK/rcwkOczgdb3DoKNuUhp5q+dRMWcC7WGBo8697O/vz8aNG4mNjXVvO3/+PFu2bME+DLsOCYJAcJSBSUvjWfXtSTz30jxW/N+JZC2K7T3zQYS6UjPndpex40/neeV7h/jwV6c4+kkBZZcbsduGj4DVJ1RKQhobue+LL8kwGt2bOzs7ef/99/nss8+G5esuIzNi8SyVco2wz6NBRhB960dmYJGFGxmZUYBXqVRnp89mPgwEnq6bCxcu4PCRriMxGUGs+9F05j+ejtbQkxPfXNPOjj+d57M/ZdNc01O+4yUG9LP4Nm/ePEJDQ92XP/30U595ngaSe+65h7Fjx7ovHzx4kCtXrtz1cb1LpQZmwmjSqXn2niT2fG8Bm785k4DSGvB0DCkVtCZGUrJsOkUPzqYxLRanavQEGet0Op5++mkSExPd265cucLmzZuHfTmgWqMkYXwI8x5LZ/1PZ/H0z2ez4MkMUqeGowu4vmW86BKpKWrlzBclfPqHc7zydwfZ+tvTnNheSMXVJpz24V2qIKikx6x2OLg3IoI1a9ag9ngPnjp1ipdffpna2tqhGqKMjIwnXqVSo+d8VEbmbpGFGxmZUYCn4waXC0bBpLyb8ePHo1JJwkh7eztXr14d4hH1oFAqmLAwlqd+OpvxC2LwbH5TcqHBq334QJRKdaNSqVi1apX7cl1dHUeOHOnX+/BFBEFg9erVXqLV1q1bqa+/3vF0W8cdwNfquvsSBOakhBJ7+Dyp2w4Ter4AVbt35zhroD8108eSv3Y+VdPH0GnyH9Ax+QparZb169eTnp7u3lZUVMRbb73Vr5lGQ013y/H7vjmeZ389l8d/PIN5j6WRNDEUrf765qEup0hVfgsndxTzyUtnefl7B9n232c5tbOY6sIWnM7hJeQIyh5BUnC6mDRpEi+++CKRkZHu7bW1tfz1r3/l1KlTo2rhQkbGF/HsKoWccSMj02dk4UZGZhTgJdzQP+2khwt+fn5eroqhCim+GX7+ahY8kcG6f55BTHqge3t3+/B3/u0Y+Xl2RCRlZyByiuLj45k2bZr78sGDB6mrq+v3+/E1/Pz8eOyxx9B0iS02m43333//rlwZXo6bQezipu6wEnaxkNRth4k5mI2+usHrepdaRXNaHEXLZ1O8dBotCZG4+tiOfrjSHUY9YcIE97by8nI2bdqE2WwewpENDIIgEBLjT9aiOB78myy+8dt5rPvRdOY8nErC+BDU2utdV067i/IrTRzfVshHvz7Nq987xPb/yebMVyXUlrTi8vEVcUHdI06JXTlGoaGhPP/8816NMBwOB5999hlbtmyho2P0deKSkfEZPEulRFm4uSuGuouU3FVqULl+KUZGRmbEodB4B5WKNitg6H3nEcikSZO4cOECAHl5eZjNZgICAoZ4VNcTGuvP6r+bTMGZOo58lEdboyQetLfaOPhFI8Ypf0963gcY20oRRdEdrttfLF26lNzcXMxmM06nk+3bt7Nx40Z3ePFIJSwsjLVr1/L+++8DkuNo27ZtPProo3f0HHu+3waqVOpmCKKIsbwWY3kt1gA9zWmxNCdH4/Iot+sID6IjPAhlZwamokpMxdVom8yMRBlHqVSydu1atFotp06dAiQHxuuvv86GDRu8WoiPNBQKgbD4AMLiA5i8LB6X00VtqZmK3CYqcpuoym/BcU2plN3qpPRSA6WXJOFPq1cRnRZITHoQMRlBhEQbem1XPmQoPYQbR8/7TaVS8cADD5CcnMy2bdvcLqvLly9TUVHBww8/THx8/KAPV0ZmtCPIpVIyMnfEyD4bl5GRAa533IymzlIASUlJGLtCK0VR5Pz580M8ohsjCAKpU3tvH95qTOTU1B9wOX097Y39X+rh5+fH8uXL3ZdLS0s5c+ZMv9+PLzJ27Fjmzp3rvnz58mW+/vrrOzrWYJZK3QqtuZ2IM1dJ+/ggUccu4dfQ6nW9009D49hEih6YReHy2dSPS8Lmrxui0Q4cCoWC5cuXe73GjY2NvPbaa6PCWdaNQqkgMsnE1PsTWfWdyTz/0nzWfn8K01ckEZ0WiEJ1vSBjbXdQlF3P4S15vP/zE7z2g8N88dcLXNhfTn1525A7cgSVxxpkL53DMjIy+Na3vuWVd9TS0sLrr7/OwYMHfb5VvIzMiMOrq5T8/pOR6Suy40ZGZhQgqFSgUrmzbUabcKNQKJg0aRIHDx4EpHKpOXPm9LtjpT/pbh8+Zk4UX39UQMGZnmDN6qjZvPPvJ5m2PImJi+N6bQ98p4wZM4axY8e62+ju2rWL9PR0t/A1klm8eDGVlZUUFhYCsHv3bqKiokhOTr6t4wxGOPG17Cz97z7vm13WzFvHStieXYnVo/28zeRP3cRU6iamMikukNWTolmRFU1YgLbX49wf+sLdDvu2uE/3dL8cJ3pmIAkLQwBobW3lv3/zB3I+qMRSc73I9mXHW/1yn76KUq0gOi2Q6LRAWJGEw+akqrDF7cipKTZftyLe2Wan4EwdBWckwUvjpyQi2URksomoFBMRSUY0foN3eumZcSPae89vMxqNbNiwgcOHD7Nv3z5EUUQURfbu3UthYSEPPfTQqPiMk5HxCeRSqf7BF8uTfG08I4wR67g5ffo0v/zlL3nooYeIjY1FEIQ7nqQlJia6b9/bT390IZGRGWg8yzdGU8ZNN5MmTXL/XVdXR0VFxdAN5jbobh++8ltjMbT1jNludXF0awHv/vvxXtuH3w0PPvgg2i6XltVq5fPPP+/X4/sqCoWCRx55BJPJBEjurC1bttDc3Hxbx/Elx01vTIwL5LePTuT4j5bw01XjmBIfeN0+58qa+en2y8z8z908/epxPjxdjrlzZLRUrjzeTOGXde6QWrVeSeYT0QTE+g3xyIYelUZJ3JhgZq1O4eEfTOP5rtbjk5fFExYfQG+1dLZOJ2WXGzn5WRGf/l7qWvXez09w4N1cco9X01rfMbCBwF4ZNzcO3lcoFMyfP59nn33W/R4HKC4u5s9//jO5ubkDN0YZGRk33qVSsnAjI9NXRqzj5mc/+xnbtm3r12M+88wzvW73PAGQkfFVBK0Wumr8RWvnLfYeeQQHB5OQkEBJSQkguW5iY2OHeFR9J25cKNNP/5LKqHsoTFqBQy11Bmqp7WDHn84TPy6E2WtTCI29+45BAQEB3HvvvWzfvh2Q2ijn5OR4hTyPVPR6PY899hivvfYaDoeDjo4OtmzZwrPPPuvuTnYrvMOJfU+46SZQr+GZOYk8MyeR0oZ2tp+v5JOzFeTVtrn3cYlwKK+eQ3n1/PPHCpaMDWf1pBgWZoQN4cjvnppzrTitLlJXhCMoBFRaJWPXRXH142qai+Tg2m40fioSxoeQMF5yKFnb7VTmNVPelY9TX2bmWk1GFKGhvI2G8jYuHpDEZr1RQ1SKicgUyZkTFhfgVQZ6NwgeGTd96ZgYHx/Pt771LbZv387ly5cB6Ojo4N1332XmzJksW7asz+91GRmZO8CrVEq2aMjI9JUR+800e/ZssrKymD59OtOnTycxMfGuuoQAbNq0qX8GJyMzBHjm3Iy2UqluJk2a5BZuLly4wH333YfaY5Lt06hUKBCJrTxERO0ZGr79F3LOtrgnTd1hoqnTwpmxIomgyLsLn548eTLnz593P187duwgMTERnW7k5Z9cS3R0NMuXL3eL/xUVFXz55Zde+T83w9Nxg8uF6HR6lXP4IvEhev7PolT+dmEKOVVmtmVXsP1cJZUtPSKv1eHi8wvVfH6hmgA/FYp5kzDml6OvrkcYhufe9TltOG0u0tdEoFApUKoVZDwcRd72GhpzLUM9PJ9Eq1eTNDGMpImScGfrdFBb3Ep1YQtVBa3UFLVgbb9ePGlvtVFwto6Cs1J5lVKlIDwxgEiPEitdgOa62/UFr1Ipx/UZN72h0+l49NFHOXPmDDt37sTRJfgcP36ckpISHnnkEUJDQ+9oPDIyMrdALpXqN3y34F9mIBixws0Pf/jDoR6CjIxPofAQbkZjqRRAZmYmn3/+OXa7HavVypUrV7zaBPsygiAgaDSIVitqh4U5i01MeDCDwx9cpeJqs3u//FO1FJyuJWN2FNMfTMQYemdCi0KhYOXKlfz5z3/G6XTS1tbG7t27WblyZT89It9m8uTJlJWVucOZT548SVxcHFlZWbe8rXBdFzcbwjARvARBIDPaSGa0kR/eN4ZTJU1sO1fBjgtVNLf3lEqZOx2QkUBLRgIqSwcBhRWY8svRNrQMqxPJpoJ2cj6oYszDUSi1ChRKgfRVERR+WUft+ZHXLry/0fipiB0TTOyYYEDqENNYbaG6oKVLzGmhpfZ6B5PT4aIqv4Wq/Bb3NlO4jqjkLldOiongyL51r/JqB94Hx437doLA1KlTiYuL48MPP6S2VsoRq66u5i9/+QsPPvggkyZN8uksNBmZYYlcKiUjc0eMWOFGRkbGGy/HjW10Om60Wi3jxo3j3LlzAJw9e3bYCDcgvYbdbimX1UpoqtQ+vCi7nuOfFtJYKbkERBGufF3F1ePVjJsbzdQHEzGYeg+YvRmhoaEsWLCAvXv3AlJ2WFZWFgkJCf33oHyYBx54gKqqKqqqqgDYvn07ERERRERE3PR2wjUuLtFuh2Ei3HiiUAjMSApmRlIw/7ZyHIfy6th2rpJdl2vosPc4GxwGHU0TUmmakIqmuQ1jQTnGgnI0rcPDtdJa1sml9yoZuy4KtU6JoBBIeSAcpXbExgAOGIJCICTan5Bof8bNiwGgw2yjurBHyKktMeO0Xz9Za6ntoKW2gyvHqgHQ6FREJhvdjpzwxBuEHiv7lnFzI8LDw/nmN7/JV199xcmTJwGw2+1s27aNgoICVqxYgZ+fnH8kI9NfCHKplIzMHSELN7fBb37zGwoKCtyTv7Vr1xIWNrzr/GVGD3KplMTkyZPdwk1hYSHNzc0EBgYO6Zj6Sm+ht4IgkDwpjKSsUPJO13Bie5F7hdvlFLlwoILLX1cxYWEsU+6LR+d/e+UIc+bM4eLFi+7V6E8//ZRvfetbw6fE7C5Qq9WsW7eOv/zlL3R2dmK32/nggw/45je/edOJXG+Om+GORqVgydgIloyNwGJ1sDunhh/9+gssseFetndboD/1U8dQP3UMfrVNkohTWIGqw7c/cyzVVi5triBzXTSaAOnUKHFxKHv37mXRokWy6+Iu0AVovMqrnA4XdWVmL1dOe8v17xFbh4PSS42UXmoEQBAgJNaf8AQjEYlGwhONBEfpvduB97FU6lrUajXLly8nOTmZbdu20dkplQhevHiR8vJy1q5dO2oEaxmZAUchtwPvN2Tda1QhCze3wQ9+8AOvy3/3d3/H//zP//CNb3xjiEYkI9N3BK1nVynfnkQNJPHx8QQHB9PYKE0GsrOzWbBgwRCPqm8IGs/QW+8OP4JCIH16JKlTwrlyrJqTnxXR1iS9zk67i3O7Srl0qIKJS+KYtCQOrb5vwotKpWLVqlW88sorADQ0NHDo0CEWL17cT4/KtwkKCuKhhx5i8+bNgPT4t23bxrp16244mb/OcTMChBtPDFoVqyfF8OevjuPw02BOiqY1JZaOyBCv/TrDg+gMD6J25nj0VfUY88sJKK5EeYOWzUNNR72di+9UkPl4NH6B0mt48OBBOjs7uf/++1EoZAdOf6BUKYhMMhGZ1NO9zdzQKblyClqoKmyhobyt19Dj+rI26svauHy4EgCVRkGgMhVdykMYW4tRWVWIonjHQtvYsWOJjo7mo48+orS0FIDm5mY2bdrE3LlzWbBggRxcLCNzt3iWSskZNzIyfUb+9ukDq1atYtGiRUydOpWwsDAKCwt57bXX+P3vf8/zzz9PSEgIq1ev7vPxxo0b1+v2goICUlJS+mvYMjJexP7+9yAICBotCt3otX0LgsCkSZPc5T/nzp1j3rx5w2JSptDcutxNoVSQeU80GTMiuXS4glM7S+holYQDe6eTUzuKOb+3nIlL4pi4OLZPAk5sbCwzZ87k+PHjABw+fJjMzEwiIyP74VH5Punp6cyfP5+DBw8CkJOTw8GDB28o+AlKJSiV4JRW/0X7yGij3RuqThtBOcUE5RRj99fRmhxLa2oM1mCPbosKgfaYMNpjwqi5ZwIBxVUY88sxVNQhDGSb6DvA2uKQxJvHotGHSmL3iRMnMJvNrF27Fo3mzgJ0ZW6MIAgYQ3UYQ3Wkz5A+U2ydDmqKWyVXTpczx9Z5vZvGYXNRjwHilgBwqRUO/eAwEYlGIpKMRCSaCE8M6LNQDVKn0GeeeYZDhw5x4MABRFFEFEUOHTpEbm4ua9asITo6un8evIzMKERQyKVS/cVwbAwgc+fIwk0f+MMf/uB1edy4cfzud79jzJgxvPDCC/zwhz+8LeFGRmYoUIWE3HqnUcLEiRPZt28foijS1NTE1atXGTNmzFAP65b0Vip1I5RqBVmL4hg7J5oL+8s582WJu9uLrcPByc+KyN5TxsTFsUzsgwNn8eLFXLlyhZaWFlwuF1u3buWFF14YNavPCxcupLy8nMLCQgD27dtHUFDQDcOKBY0GsUMqWRtpjpsboW7rIOR8HiHn8+gMCsCcEktLSiyOAL17H1GlojU1jtbUOJQdVgKKKjEWlKOrafSZUGN7m5NL71Qwdl0U/lGSyJ2Tk0NzczNPPPEERqNxiEc48tH4qYgbE0ycZ+hxlYWa4lZqi1upKW6locKC2Mukr8Nsp/hCA8UXGtzbAiP0XUKOJOiExPijVN1YrFcqlSxcuJDU1FS2bt3qdmjW1tby8ssvc88997BgwYJRUTIqI9P/eHzay6VSMjJ9RhBFH1vuGiD8/PywWq3058N1uVxERUVRW1tLUVERiYmJd3W8bifOpUuX+mF0MjIyN+P9998nJycHgMTERDZu3Di0A+oDRY88SufFiwDE/NdLGB94oM+3tXY4yN5dSvbecmwd3qUqGp2qTwJOQUEBb731lvvy3LlzWbp06W0+iuFLe3s7r7zyinsSp1Qq2bBhQ6/ZF7kzZuJqbQUgaetH+GVmDupYB4P7Q1+45T4i0BEeJIk1yTG4/Hp3rKjM7e5QY7+m3rs5iZbruxMNJEqNwJN/upf8/Hz3toCAAJ544gnZceEDOGxO6svbKHz3SypPFdFqTKRD17fcQaVKQVi8v+TISQogItGEMdSv1xIrq9XKrl27OHXqlNf2brd1fHx8vzweGZnRQv1f/krdf/0XAMYHHyDmpZcG9P5G4vxq3LhxFFQ3kPG0b3VRzn3rV6REhoyo59qX8P3aAB9GoVC4S5u6u47IyMgMD2bPnu3+u7i4eFi8h2/HcXMtWp2KGSuT2fAfs5m+IgmNrscpY+twcHJHMW/+6GuOby+k09J7aU9KSgrTp093Xz5y5Ajl5eW3+SiGL3q9nvXr16Pr6hDldDp57733qK+vv25fz5ybkVwqdSsEQF/bROTX50nd/CXRu0/gX1yJ4PQue3EE6GmclE7xw4spfGgR9RPTsPnrez/oIOG0iTzxxBPMnDnTvc1sNvP666+7RV+ZoUOlURKZbCIjup1xOZuYffwn3Kf8jOX/J4vpyxOJHxeM1tC7I9DpcFFd2Er23jJ2vXqZt398lNd/cJjP/pTNyR1FlF5qcH8OarVaVqxYwTPPPENQUJD7GA0NDbz22mvs3LkT2yhx1cnI9AuCZ8bNqPAPDByij/3IDCijw+M+gDQ1NQFgMBiGeCQyMjK3Q1xcHNHR0VRWSiGXx44dY+3atUM8qpvjKdy47nCioNWrmbEiiYmLY8neW072njK3A8fWnYGzp4ysJXFMXByHn8HbgbNs2TIKCgpobGxEFEW2bdvGiy++OGpKpkJCQnjiiSd44403cDqddHR08M477/D88897fQ/Iws31KFwujMVVGIurcGpUmBOiaU2NoT0qzCus0hZspD44k/rpmehqGjEWlBNQWIFykB03ILmqHnjgAUJCQti5cyeiKGK323n//fdZunQp99xzj9xxaogRlEr331pXJ3ETQkmcEApIk8KW2g5qusqraopaqS8343L0XmJVcqGBkmtKrMLiAwiN8ycs3sSzG57n6+OHOHbsmHuf48ePc/XqVVauXElycvIAPlIZmRGC50emPNmXkekzo+NMe4C4dOkSubm56PX6YZGPISMj04MgCMyaNYutW7cCUtvXpUuXEhAQMMQjuzHeXaXuboXXU8A5v6+cc7tvIOAsjmPikh4BR6PRsGrVKjZt2gRAXV0dBw4cYMmSJXc1nuFEfHw8a9eu5cMPPwQkAf+9995jw4YN7swLWbi5OUqbg8C8UgLzSnHotLQmx9CaEktneJDXfh0RwXREBFMzazz60hqMuSX4F5ajtA1uZ6oZM2YQEhLCBx98gLWrK9/u3bupq6tj5cqVo0a49EmUPeZx0en9fyEIAoERegIj9GTMlIKPnXYX9eVt1BS3UFMkCTottb2Lgs017TTXtJN3ssa9LSDYyISwB6hqKqLVVotD3UZTUxNvvvkmU6dOZdmyZfj5jd4GADIyt8JL7JYdNzIyfUY+0+jij3/8I3/84x9Zu3Ytv/jFL9zbP//8c/z8/K5rfXv+/Hkef/xxRFHk+eeflztNyMgMQ8aNG8euXbswm804nU5Onjzp022uvUul+kcM0OrVTF+eRNYiScDJ3lPWE2Lc6eTU58Wc3+st4CQmJjJjxgxOnDgBSF2mutvojhbGjx9PU1MTe/bsAaCsrIxPPvmEhx9+GIVCIQs3t4Gqw0rwpUKCLxViMxokESc1Flugh4iqUNCeGEV7YhSCw4GhqBJjbgmG4ioUzsEJt0xJSeH5559n8+bNbrdtdnY2TU1NPPbYY7LzdogQlB6nsn34X1CqFVJQcZIRFknbOi12tyOntuv3jUpGzY2dmBtBIBwT4dLdKqw4VBZy9jdQcOYdFi2fQ9bUMbIbS0amN2Thpv+Qn75RxYgVbnbs2MHPfvYz9+Xu+uNZs2a5t/34xz9m+fLlANTX15Obm3tdzsWJEyf46U9/SkJCAhMnTkSv11NYWMiZM2dwOBwsXLiQX/7yl4PwiGRkZPobpVLJjBkz3JPvU6dOMW/ePJ/tFKK4i4ybW+EWcBbHcX5vWa8CTvbeMiZ2CThLlizh6tWrNDc3u0umvvnNb44q58HcuXNpbGzk7NmzgOTCDAoKYunSpbJwc4doWi2EnrtKyLmrWIONtKbG0poci8Nf595HVKloS4unLS0ehdVGQH45Abkl6MtrB7y9eFhYGM8//zzvv/8+paWlAJSWlvLKK6/w5JNPEhbWt3BcmX7Ey3FzfcvwvuBnUJMwLoSEcVL3RVEUaa3voLbYTF2ZmbpSM/VlbTcUc5QuLUqbFq0tGCxw+JUqjmyqJDLJRESCibD4AMLiAzCF61EoZDFHZrQjCzcyMnfCiD3Drqur4/jx49dt99xWV1d3y+Pcd999lJWVcfLkSY4cOUJLSwtGo5G5c+eyfv16nn32WZQe9dUyMr6INT8fy4kTaFNSMcyccd319qoqnGYzOJ2IDieiw45otyPa7IjWTgJGcBnM1KlTOXjwIHa7nfb2di5cuMCUKVOGeli9IqgHTrjpRqtT3VDAsV8j4Ny/bDnvbXkHgJqaGg4fPszChQsHZFy+iCAIrFixgpaWFneb8MOHDxMUFESwLNzcFQLg19iK34nLhJ24TEdkCC0JkZhT43DptO79XFoNLeOSaRmXjNLSgfFqKQG5JfgNYHtxg8HAhg0b2L59O9nZ2YBULvfKK6+wbt06d9MCmcHB23FzZ8LNdccUBExhekxhetKmRwCSmNPWZKWuVBJz6kslQcfS0vtnsegQqMprpSqv1b1NpVEQGhvgkZsTQHCU4aatyWVkRhyCHHIjI3MnjFjhZuPGjbfV3vcnP/kJP/nJT67bPnv2bK/uMzIyw5GmDz6g6a23ifnD73u9vnnLh7R88gkuiwWX1SqtWjqdKPz8EEWRjOPHvMp0RhJ6vZ6JEye6W70ePXqUyZMn+6TF/W66St0ungLOhX1lnNt9vYCjUitIippNaXs2TlU7Bw8eZMyYMURGRg7o2HwJpVLJunXreO2116itrQXgs88+Y6nJRHDXPrJwc3cIgL66AV1BORH7z2CJj6A1I4G2lFhEdc9pjNOgo2lyBk2TM1A3mzHmlhCQW4L2Bu3F7waVSsWaNWsICwtj9+7dgNQ2+u233+bBBx/06r4mM7AI/eC46dP9CAIBwX4EBPuRPKnHWdXeapOEnDIzZVfrqchvAFvvrk2HzUV1YQvVhS3ubQqVQEi0P2FdQk5oXADB0QY0fiP2FF1mtCN3leo3BPnpG1XI3woyMqMAa84VlCYT/vPn93q9Yc5sGl55BWVoCLqxYxE0ahRaP6x5edhKShDt9hEr3IBUQtkt3NTV1VFYWOiTq+bewo11UO5Tq1Mx7cEkJiy6XsBx2F20laoJZho2TSMdhgo+/vgTXnjhm6PKiejn58eTTz7JK6+8QltbG6Iosj8mmsUmE4EtLQMuso0mBJcL/+Iq/IurcKmUtCXH0JqRgCUhyqtkxh4YQMPM8TTMHI+2tpGAvDL8iyrRNLT0mxNHEATmzp1LSEgIW7duxW63I4oiO3bsoK6ujvvuu29UvQ+GDA/HzbXhxIOB3qhxl1lNvT8Rp9PJ4YNHObrnDIJVh8ruj8rhj9KhR+jlv8/lECUXT6kZjvSU6wcE+xESYyA4xp+QGAMh0f4ERuhld47M8Ec23MjI3BGycCMjMwpw1NaiSU0BV+/BjbqsLASNBuO99xH+g39AUEgnhrW/+x0Nr7yKy2ZDMYKDN0NDQ0lLSyMvLw+QXDe+LtzcaTvwO6VbwMlaFMf5feWc31dGh7nHSaKxBaOxBWNrbefTTYdY8dQ81NrRM2kNDAzkySef5PXXX8dut2NXKDg0fx5Ld+0esY6bL+r/OtRDcNNksfH5xSq2navkRFGj13XW8GCs4cHU3zORmEAdi8aEsWRMBLNTQvBT3/x/dJni0T7dvyHSj7GPx6M1Sk6LEydO8OXmPeR+VI7TenvhybtcW25r/9GOoPJ4DQcpqPpmKJVKFiyay7gJY/j0008pLc2VrhAVqOwGYoJTiA5OpqXaSkNFGy5n7zNXKQS5k2KP9uQKpdQlK8RDzAmOMRAQ7OeTLlEZmd6Qu0rJyNwZsnAjIzMKcHV0oFKpe/2CFF0uBI0GQaPBVlSE2NmJoNdLVwqSgDNSJ56ezJo1yy3c5OfnU1dX53NBo4NZKnUjNDoV0x5MZNKyOPJO1pC9p5yGijb39SqnnsqTLl6/eJgJ82MYvyCWgODR0Ro3OjqaRx55hPfeew9RFGk3GDg0fx7RnYPjjhrNBBk0rJ+ZwPqZCVQ2d/DZ+Uq2navkUmWr134VzR28fayUt4+V4qdWcE9KKIvHhrN4TDhRJt0Njn5rLNWdnH+1kLGPxeMfLR0nKDWAic8lk/N+KR0NsutqwFAMTqnU7RIaGsrGjRs5efIku3fvxm6349CYKWk7R7U9h/vuv4+HJsynqbpdCj8uNVNX1kZDZRv2zt4fh8sp0lhpobHSQt7Jnu1qPyUh0V3unOguUSfGHz+Dbwbty4xyZOGmfxDxPceSr41nhCELNzIyowBlUBD20lJcVisKvR5RFBEEQfqtUGCvqgKXC0Gn8/oSFbo6BPVX62lfJjk5mfDwcHdOybFjx1i5cuUQj8obQeMReDvEr4lKrWTsnGjGzI6i4mozZ3cVU3Kx0V0KYO9wcubLUs7uKiNlShgTF8cRmWwa0jEPBhkZGdx///3s3LkTgKbgYL6sruZplwuFQi5xGAyiA3W8MD+FF+ankF9rZsf5avZeqSG7vMVrv067iz1XatlzRXrPj40ysmRMOIvGhDMpLhDlbXb/sZkdXHijiLTVMYRmSv/rulAtWc8lk7u1nOb8tlscQeZOEFT9H07cXygUCmbOnEl6ejqffvopRUVFgJSH9Omnn3Lx4kVWrVpF5j3RcI90G1EUMTd00lBpoaGijcau383V7bhcvc+K7J1OqgtbqS70Fir1Jo3kzok2dLl0/AmK1KPSjB43pIwvIgs3MjJ3gizcyMiMAvwyM2n55BM6zp4jYPEit021+3fLp9txtrTgNy4Twa/HHSFope4ton3krxYLgsCsWbP49NNPAcjOzmbJkiXou91HPoAvOG6uRRAEYjOCiM0I4tzxy+x6/zR+HREoxC7RzyWSf6qW/FO1RCQZmbg4juQpYSiVI1fEmDlzJmXbtnGx6/Uq6uzgiy++4MEHHxzikY0+UsMD+M7SAL6zNI1acyf7c+vYm1PLobw6LDbvSX5OVSs5Va38cV8+wQYNC9PDMGckoi+uRGnt2/vNZRfJ/bCc9vlW4heGA6DyU5L5eDzFu2uoPNZwiyPI3DY+6rjxJCgoiA0bNnD27Fm+/PJLrFbJhVdYWMj//u//snTpUqZNm4ZCoUAQBIyhOoyhOpKyQt3HcDpcNNe001DRRkOFhYbKNhorLJgbO294v+0tNtpbGim73FM+KAhgCtf3OHRiDARHGTCG6Ub057KMDyE7bmRk7ghZuJGRGQUE3HcvbQcOUPWjHyH87rfoJkyQTnAdDtpPn6Hh5ZcB8J8/H0GpRHQ6u35LQY9i541PDEcSEyZMYM+ePVgsFhwOB6dPn2bevHlDPSw3Ch8UbjyZNDOTospczp89jl9HJLr2GJTOHiGwpqiVr169hOEjLRMWxjBuXsyItfLPcok0lZdTERsLSJknwcHBzJo1a4hHNnoJD/Bj3bQ41k2Lw+pwcrKoiT1Xath7pZaShnavfRstNraerYDVC8HpQldRg6GgHENBOerGWwcclx2sw1LbSfqaWJQaBYJCIOneSAwRfuR/Vol4g1wTmdvHqx24Y/DDifuKIAhMmTKFlJQUduzYwdWrVwGw2Wx8/vnnXLp0iVWrVhESEtLr7ZUqhds144mtw9Hjzqloc//dHSJ/LaIIzTXtNNe0U3C2zr1doRAwhesIijQQFKknKKrrd6RhVOWVyQwCnl2l5NqaO0bA97pKyUlbA4ss3MjIjHBEl4uAhQsxL15E67ZPKXv+m6hjYlBFRuCorMJeVYWgUhHxjz9Em5Qk3ajrS1Wbmop+1kwUPuQ6GUjUajXTpk3jwIEDgDTZnj17NiqVb3xU+qLj5lruu+8+CgoKaFNU0KGvIMo/nTAhg6r8njIVS7OVY58UcmpHMRmzo8haFEtw1MgKv1aq1cw6eoy9ixfTFCI1Bv/iiy8wmUyMHTt2iEcno1UpmZsWyty0UP51RSaF9Rb2XallT04tJ4sbcXiWpCgVdMRH0REfRf2i6aibWjEUlKMvKENXXoPiBoG4jVfMnH9dyr3xC5Teu+ETA9GFarjyfhm2Nt8VGYYTnuHE4g0C+H0Jk8nEE088wYULF9i5cycdHR0AlJSU8Oc//5lFixYxa9asPnck0+hURKWYiErpKUUVRZH2FpuXO6ehoo2mqnacjt6fI5dLpKm6nabq9uuu8w/W9gg6kQaCo6TfuoCR221SZgDx6irlY8qDjIwP4xuzERkZmQGju0NU9M9/jjYxkab3P8DV2orNbEbw88Nv7FgC160j8LF1PSVUXbfxX7AA/bRpKE0jP5ukm+nTp3P48GGcTidms5nLly+TlZU11MMChodwo9frWbFiBe+99x4IUGW5yoR7E5n76DTO7y0n71SNu4uKw+7i0sEKLh2sIH5cMBMXxxGXGTwiuqMIajUqp5N5hw6xd+0a2rpOTj/66COeffZZYmJihniEMt0IgkBKmD8pYf48Py+Z1k47h67Ws+dKDdsOF+DUe4dr24OMNE/LpHlaJoLNjr64EkNBGYbCClSWDq9922usZL9SyJhH4zAlSOJkQIyerOeTufJBKW2Vo8PNOKAoPISbIWgHficIgkBWVhbJycl8/vnnXL58GQCHw8GuXbu4cOECK1euvOPPCUEQMARqMQRqiR/X4+BxOV201HV4lVo1VLbRWtdx0/lzW6OVtkarV8kVgJ9BTVCUnqCIboeOJO4EBPsh3GZGlMwowqtUauiGISMz3JCFGxmZUUTI888T8vzzWPPycDY3ozCZ8EtPv24/0eVCUChQaLUounJuRgv+/v5MmDCBc+fOAVJr8AkTJviEmDAchBuAMWPGMH78eC5evAjA3r17yfibDJY+m8nsh1K4eKCCiwcr6GzrCVguvdRI6aVGgiL1ZC2OI2Nm5LC25wtqqQRM19nJg4KCbRoVVqsVh8PB5s2bef755wkKChriUcr0htFPzfKsKJZnRXH+if+kMzIUS0os7SmxWCO8y1hEjRpLegKW9AQAtFX1GArK8M8rRVPXhAA42p1cequEpPsjiZomua+0RjUTNiaRv72Sugst1w5B5jbwtXbgt4O/vz/r1q3j8uXL7NixA4vFAkB1dTWvvPIK06dPZ/Hixfj59U9nPoVS0SWuGEidGu7e7rS7aK5rp6mqnaZqS5fzxkJzdTsO+42f006Lnar8Fi9HJYBKoyAwwsOdEyXn6Mj0ILcD70fkp29UIQs3MjKjEG1amvtvV2en1IlDqZTagisUbseN2PWF6guixWAya9Yst3BTVVVFUVERycnJQzsoQFD3CDcuHw+MfuCBBygqKnLnBXU7TQwmLTNXJTP1gQSunqjh/N4yGios7ts1VbdzYHMuxz4pYMycKCYsiMUUdudtmocKzw5gQXY769Y/yTvvvIPL5cJisfDWW2/x7LPPEhAQMISjlLkVgiiiq6pDV1UHh89i99fTnhIrCTkJ0Yhq79Moa1Qo1qhQGudORtVsxj+/DEN+Gbryago/r6K9ppOk+6NQKAUUKgXpa2Mxxukp+qoal0M+A78jPMOJfTjj5mZkZmaSmJjIV1995f7uEUWREydOcOnSJZYuXcrEiRMHrDOdUq2Q2ohHe+fniC4Rc2OnW8hpqpJEncZqC1bLjZ9rh81FfVkb9WXendQUSqFL0NFLvyP0BEYaCIrQo9HJU5JRgyzcyPSBkydP8pvf/IbDhw9TV1eHwWBgwoQJfOMb32Djxo2jbm4CsnAjIzPqcHV24mxpwVZUhLWgAGdjE6LNCggojAGoIyNRhYWhTUlBFRY21MMdEiIjI0lKSnK3bt27dy9JSUlD/iXh6bjB7tst2g0GA8uXL+eDDz4AoLKykp07d7Jq1SpAaieeeU80Y+dEUZHbRPbecoov1LtXj6ztDrJ3l5G9p4zE8SFMWBRL3NjhU0bV7bgBaTKZkpLCihUr3F3LGhsbefPNN9m4cSMGw8jK9xnJqNvaMWVfxZR9FZdKSUdcJJaUWCwpcThM3pNeR2CAu6RK0WlDX1iOOb+Mtg8qyFwdiVovnYJFTgsmIFZP7kdldDT4tiDriwieWTDDIOPmRuj1etasWcPEiRP57LPPaGiQOpBZLBa2bdvGqVOneOCBB4jtCjwfDARFT4erhPHebrMOs42maguN17h02hqtNzyeyynSWGmhsdJy3XV6o8Yt6HS7dQIj9ASE+KGQy65kZEYVH330EY899hhOp5MpU6Ywb9486urqOHToEIcPH2b37t288847Qz3MQUcWbmRkRhGdubk0vvY6LV2Tx5vhP38+pkceJmDhQq9J6Ghh4cKFbuGmvLycq1evkpGRMaRj8hRuXD5cKtVNZmYmU6dO5fTp0wCcOXOGmJgYpk6d6t5HEARixwQTOyaY5pp2zu8v58rRKuydXW19RSi+0EDxhQYCI/T8/+z9d3QU6Zrmi/4iM6VM+ZQ3yEtIgJDByICENwWFL4py1C63y+3dd6b7zunTd62566zZ58zM7Znp3T3TPdtU1S5H7aIMZXBVhbcCJOQQCAECCQmBvE95pbt/pBTKRAIEyOf3W0srpYjMiE8KZWR8Tzzv885ODyQ2NQAXj0lewmcVaD3gApg/fz6dnZ2cOHECgIaGBv7617/y+uuv4+Q09VxF9o7CYMSlvAqX8irMxy/S56OlMyqEjpmh9AbZit4mjSMdcyLpmBNJrdHE3Zp7ZHjXotVaJqQuARoS34mk7KeaifhVpjaKqRVO/CgiIiL4zW9+w/nz58nMzMTQf/6oqqri448/Zt68eaxatQpXV9dHbGlscXJzxMnNkaCZtiWffT0GWussIceyQ6emk7aGbsymB7srunR9dOn6qLrZarNcqVJYul35O6MN6Hfp+LugDXBGLVw6U58pcjNmsjLZukqNBgaDgd/+9rcYjUZ2797NK6+8Iq+7fv06GRkZcsn5ihUrJnCk44844wkE0xyz2YwkSegOH6bmP/0Ok06HyscHla8vDiEhKL08UTiqQaHA1N2Fsa0NQ0MDHWfP0nH2LIH/+P9Du3XrRP8a405YWBgzZ87k1q1bgMV1M3PmzDGzqo8EGxdH3+R23Aywfv16amtrqaqqAuCXX37B399/2LvGWn9nlr4YQ9rmSG5k11B0uorWusEOJ611XWT9WEb2vtuEx3sze3EgoXO9J2Vmgs2xsnJHLVmyBL1ez9mzZwFLlsWXX37Jr371q1HLsRCMPxKgbmxF3diK18UiDK5OFhEnOoTusCDM1jksSgWNM0I5QDALDPeIU9VZFjsqiXkumAMHDrBu3TocHUXHnpEgWb//jcaJG8goolKpWLZsGYmJiRw7dozi4mJ53aVLl7h27RrLly8nJSVlxN2nxgtHjQq/MHf8wtxtlhv1JlrrLSJOS22X3JK8pa4LQ++Dj5vRYHqoS8e69GrAqSNcOgLB1OXGjRvU19cTGxtrI9oAzJ49m1dffZV/+7d/Izc3Vwg3AoFgeiFJEr1lZTT95WNMOh1er72G569+hWPwg7tVGJqaaD96lIZ//Tca//RnNLGxaOywhfHKlStl4aauro5r164xd+7cCRuPdW6KeZKXSg2gUql44YUX+Oijj+js7MRoNLJnzx7ee++9B5YIOTqpSFgRQvyyYO5eb+bK6Xvcudokl1GZTWbKLzdSfrkRZ3dHYtMCmL04EM+AyVNyZFsqZXusVqxYgcFg4MKFC4DlTvpXX33Fq6++Kibr0wRVR/dgSZWDiq7wIDqiQ+iKCpG7VJlQkGsIpc7kRrpDOWrJMnktKCigpKyCV156kRmB/hP5a0wNFNOjVGo4tFotO3bsYOHChRw6dIj6+noAent7OXLkCAUFBaxfv35SZLA9CqWDAu8ZrnjPuC9Hx2yms7WXlrouWmstQo7FsfPwsisYdOlU32q13Ze1S6ffqaP1c8bD1wmNq8OUKbmdtohcG8FDUI+wKYq3t/ejnzTNEMKNQGAHdF68SM+1a/j+h/83Pu+8AzzAUt7/Yary9sbz5Zcx9fRS/z/+Bz3FxXYp3AQGBjJnzhy5VevJkyeZPXv2hN3hnCpdpe7Hw8OD559/ni+++AKz2YxOp+P777/n1VdffejfUlJIhMZ5ExrnTVtDNzeyariRVUNHy+DFfJeuj0tHK7l0tJLAKA9mLQ4keoEfjpqJ/XiTVA8W2SRJYs2aNRgMBnJycgCorKzk66+/5pVXXsHBDksTpzMKvQHXW5W43qrELEn0BPnSGW1x4+i9tVSaPGnuc2aZQxm+CouroLOtmT9/8CEd/gmkpyxg5Sw/vF0neXngBGHddno6lEoNR0REBO+99x55eXmcOnWKnh5LG/mGhga++OILZs+ezdq1a6dkpzpJknD11ODqqSFklpfNOn2fkbb6LtmhIz8+hUvHUaPEo1/E8fB1wsPPCQ9fy8/OHo5C1BlvxN/76ZiGGlhkZCRRUVGUlJTw1VdfDSmV+vLLL/H09GTbtm0TOMqJQQg3AoEdYKivR3J0xCkuDrBkbkiqB7/9zX19SI6OqKOjkBwcMLS0jNdQJx0rVqzg+vXrmM1mmpubuXz5MvPnz5+QsTyo/GYqEBERwZo1azh69CgA5eXlnDhxgrVr147o9R6+TqRujiR5YwT3rjdz/UINty832HTiqSlro6asjcw9t4he4MecxYEERHlMyIW4TS6Ufmj3FUmSWLduHXq9nkuXLgGWv8m3337LSy+9hOoh70/B1EUym3Gqqsepqh6fM/n0ebrLIs6hGTHMd6xmbn/plEoyoa0vZN++e/xHYyhJYT6snu3P6jn+RPlObL7JpMJa/J0mpVLDoVQqSU1NZe7cuZw4cYKCggJ53fXr17l16xYZGRmkp6dPG/HXwVGJT7AbPsG23fcsLp0+WuosLcsHxJzW2i7aW3oeOpnt6zHSUNlOQ2X7kHUqR0W/oONsJeo44eHnjKtWbSMSCgSCsUGpVLJr1y42btzIzp07+ed//mdmzpxJfX09mZmZzJkzh88//xwvL69Hb2yaIa4MBQI7QOnqitlgwKizXKhYizZma8uq2WxpB97v7NBX12DW61E4O4/reCcTvr6+JCYmyi1aT58+TUJCwoRMrBVT1HEzwKJFi6iqqpLzGi5cuMCMGTOI6xcUR4LCyoXT06GnJKeW6+draKoabDtr6DVy40INNy7UWAKNFwcSmza+gcY277EHiGwKhYJNmzZhMBgoKioCoLS0lO+//54dO3ZMuuwKwejj2KLDMbcYz9xijE5q7kYGM+P/tQTn6gK5dGqmqhEfRQen70STW9HCPx66QaSPC6vn+LNmjj/zQz1R2vGEUrJuB24HJRguLi5s3ryZBQsWcOjQIe7duwdYAj1Pnz7NpUuXeOaZZ5g9e/a0dY9YXDpqXD3VI3bptDV009f98Hbxhj4TTVWdNFUNdeooVBIePk6Dwo7foGPHzUuDYhJmrU1W7OF9as+UlZU98LrOOq/rYaSnp3PmzBm2bdtGQUGBLFQ7OjqyZs2aKVEeOhYI4UYgsAPUsbOQHBxo3fsjTvPnofL2lluo2lzY9X9v1OnovlJE82efofL3x3mCHCaTheXLl3PlyhVMJhM6nY68vDzS0tLGfRw2Lg6jEbPRaNsKd5IjSRKbN2+mvr6ehoYGAPbv34+vry9+fn6PvT2NqwOJK0NIWBFMQ2U71y/UcDOnzubivLWui6y9ZWTvv03YXEugcVj82AcajzSPSKFQsHXrVgwGA9evXwcswXw//vgjzz33nBBv7Ahldy/uxWX863v/jbrGRXz59be0N1ncN56KHjY5XiPbEEap0YfbjZ18dPY2H529jaezAytn+bNili+LIr3tr6RKMf3CiUfCjBkzeOutt7hy5QrHjh2js9MiNrS1tbFnzx4iIyNZt27dE51bpzIPc+n0dhpobeiirb6btoZudA3dtDVYRJ3u9oe7WE0Gc3/L8y6gyWadQiHh6q1B6zvo0HH3dcLdW4Obt2bCS3cnNdNTWxw/pqkG9vXXX/Pmm2+SlpbG119/TVxcHNXV1fz+97/nn//5nzl16hQXLlwYcR7OdEGcSQQCO8BlURpev3qVpo8/oeKll9A+tx3nhQtR+Vla1pr1Bsx9fZg6O9Hfu0tXXj5tBw+CyUTA735nl/k21mi1WhYuXCjnkWRmZjJv3rxx/8CQ7guuNev1U0q4AUvo3EsvvcRHH31Eb28vfX19fPvtt7zzzjtP3FVJkiS5i0n69mhuFzZw/UIN924MlviZTWYqrjRScaURJzcHYtMCmb04EK/AsQk0loZpB/4glEol27dvZ8+ePdy8eROw3JVSKpVs3bp1QjuZCSYGfx8v/u6373LixAk5xFolmchwKCdAoSNbH4YBy3u/pUvPDwX3+KHA4ryYHejO4ihvFkd5kxLhhZtmepTNPBDrcGKzWe6kaA8oFAqSkpKYNWsWZ8+eJTs7G1N/zs/t27f54IMPSElJYfny5XbftU6SJDSuDgS4ehAQ4TFkfW+3AV1DN631FiGnraGbtvoudA3ddLY93OFqMpnR9QtBw+Hk5oCblwZ3HyfcfTS4eVse3b0tbh2lgzjHC6YPUVFRI3bWDMetW7d4/fXX8fPz46effsLV1VIaPHPmTD788EOqq6v56aef+PTTT/nNb34zWsOeEgjhRiCwAySVCu/33gelkpa/fknjn/708FR/lQqn+Hi0L72Ix6ZN4zfQScySJUsoKCjAYDDQ2dnJxYsXWbp06biOYYhw09cHU/Bi3Nvbm23btvHNN98A0NTUxL59+3jhhReeWqRQOSqJSQkgJiUAXWM317MsJVPWgcbd7XoKj1VSeKySgEh3ZqcHjXqg8ePmEQ103/r6668pKysD4MqVKyiVSjZt2iTEmwnimOm7Cdu3Uqlk7dq1hIeHs3fvXrq7LZPCaGUTs90N3HaN5+y9PvRG23P59Rod12t0fHKuHKVCIiHYg/QoHxZHeTM/zBONw9QSex+FdL97zmSyzb2xAzQaDWvXrmXevHkcPnxYPoeYTCays7MpKipi9erVJCYminPJA1A7qfANdcM31G3IOn2vEV1jN2313RbHTkN3v2uny/LZ8gjXQ3e7nu52PfV3hubqIIGLh3pQyOl/tAg8ltDmadfaXJRKCR7CN998g16vZ926dbJoY80LL7zATz/9xNmzZ4VwIxAIpidKVxf8/u7v8HzhBdoOHKC76CqG+nqLa0OlQlKrUbq74xAcjGb2bFyXLkHl4zPRw540uLm5kZaWxrlz5wA4f/48ycnJODk5jdsYpPsCJ6daQLE1s2bNYunSpZw9exawlAedP3+eJUuWjNo+3H2cSN0USfKGCKputHDtQjW3C20DjWtv66i9rSPz25tEL/Bj9uIgAqNHIdD4MRw3gy9R8dJLL7F7924qKioAuHTpEkqlkg0bNtiNi0BgS0xMDO+//z7ff/89d+/eBUDf2UZEbzZvbX6GZk0QJ280cL60kfp22/bJRpOZS5WtXKps5Q+nSnFUKVgY5mlx5ET7kDDDA9VUz+a4X4gwGu1OuBnA19eXV199lZKSEg4fPkxraysAnZ2d7N+/n7y8PNavX09wcPDEDnSK4aBWDtvKHMCgN9Le1COXX7XVd9Ha0I2usZv25h6bz5thMUNnay+drb3UlLYNWa1QSLh6qS1uHW8Nbj5Wbh1vDc7uU7wT1lQe+0RjBmmyaWCjMJ6B3C4Pj6HOOOvlLXbYOEUINwKBneEQFITP+++P6Llmk8km+NHeWbx4Mbm5ufT29tLb28v58+dZvXr1uO1/WMfNFGb58uVUV1dTWloKWNqtBwUFERUVNar7USgkQuZ4ETLHi55OPTdz6rh+oZrGu1aBxn0mbmTVciOrFg8/J2YvDmTWosAnDjR+0g5gDg4OvPLKK3z55ZdUVlYCkJeXh0ql4plnnpnaF+iCJ8bDw4M33niDU6dOyeKxwWDg2KGfiY+P579t3YijoyNlDZ1klTVyvrSJrNtNtHXb/u/1GUxcKGviQlkTHL2Jq1pFaoQXi6K8SY/2Idbfbcrd3b//M8psMtl1bIYkScyaNYuoqCguXLhAZmYmhn7xuKqqio8//ph58+axatWqYe9mCx4PlYMSzwAXPAOGlt2aTWY623rRNfaga+pG19hDe/+jrqmbzpbeR5pPTCaz5fmNPQ/YvwI3b0sZlpuXBlcvNW5emv7vNbh4OIrgZMGUIiAgALBc+wxHbm4uAOHh4eM1pEmDZBbR3pOGgQTup6kLFAhGirm/Dh5JQpIkS8r/wOmgf5lgKGfPnuXkyZOAZZL9t3/7t+N28Ws2m7kxJ04+TlFHDuMYFjYu+x4rurq6+Oijj+Q7w05OTrz77rt4enqO+b4bKtu5fr6am7l19HYN07JbIREyy5OoBX5EJvmicRl5VkjnxRwqX38dAFVQIDP7/2dGSk9PD3/961+pqqqSl6Wnp7N69Wrx3rRzbt26xd69e+nq6pKXeXt7s2PHDvmCFywTvms1Oi70Czm5Fc109T08vNfLxZFF/fk4i6N8CPd2nvT/b4bmZm4tTpd/js3PQ+EyNtlVU5HW1laOHTs25NpSrVazfPlyUlJSRAj6BGE0mOho6ekXZrppb+pB12T5XtfUQ7fu6W/OSAoJF62jRcjxtAg6lhKsQYHH0Wl87+M3f7mbuv/yXwBwWbaU0A8/HNP9Tcf5VVxcHLerm5iz4/8z0UOx4dp3/53IIO+n+lsXFBSwYMECAP70pz/ZlENlZ2ezevVqOjs7OXbs2LjePJ0MCOFmEjEdTywCwXSjt7eXf/3Xf5UnTampqaxfv37c9n8jMQlzr6UcIvKng6ijo8dt32NFTU0Nn3zyiXxXODAwkLfeegsHh/EJVTXojZQXNnLtfDX3SlqGtfoOuHaiF/gRkeiD2vnhY+squMSdV14BQOnrQ0xm5mOPq7u7my+++IKamhp52bJly1ixYsVjb0swvdDpdHz//feyKwsGM3FSUlKGFVv6DCau3GvlfGkTF8oauVTZSp/R9ND9BHloWBTlQ3q0RcgJ8Jh8mVqGlhZuLVos/xyTl4tSOEmGUF5ezqFDh6ivr7dZ7uvry7p160bd6Sh4evR9Rtr73TntVoLOgMgz3A2HJ8HRSYWblxrXfiFHdu54jo1rx1q4cV22jJAPPxi1bQ/HdJxfycLN85NMuPn+6YUbgP/z//w/+f3vfw9Yftc5c+ZQXV1NVlYWJpOJd999lw/HWPCbjAjhZhIxHU8sAsF0JCsriyNHjgCWydK/+3f/Dq1WOy77LklOwdRuCTiM+PEHNHPmjMt+x5rLly+zd+9e+eekpCS2bNky7nf7dY3d3Miu5caFGtqbh7emK5QSobKI4zvs3cruoqtU7NgBgFKrJSY764nG09XVxa5du6irq5OXrVq1alSzgARTE6PRyOnTp8m8TxScOXMmW7ZseaQTsLvPSN6dZktZVVkjRVVtmB5xRRjp6yK7cRZFeuPp4vjwF4wDRp2Omymp8s8xF7NRPiAbwd4xGo3k5eVx6tQpenpsz29RUVGsXbsWf3//CRqd4HHp7dKja+oZFHeae+ho7rU8tvQ8ssX5SJEUEq5atVyGNSDwuHqqcfW0PKqdVSP+vBbCzdMz3YUbgL179/LBBx+Qn59PW1sbbm5uJCUl8c477/Dyyy+PwminHiLjRiAQCB6ThQsXkpWVhU6nw2g0cubMGbZs2TIu+37S7JTJTmJiIvfu3ZNrlwsLC5kxYwbJycnjOg53HydSNkaQ/Gw41aWtlOXXU3qpwcaybjKaqShqoqKoCaWqhNA4i4gTnuAjd6aSHKzCiZ/iODk7O/Paa6/x+eef09DQAMCJEydQKpUsXrz4Ea8WTGeUSiWrVq0iLCyMvXv30tnZCVhKqf785z+zdetWZs6c+cDXOzkqWTLTlyUzfQFo69Zz8XZTfwZOIzfrOoa85nZDJ7cbOvky2+L0ifV3IznCk+RwL1IivAj0GL+wdhmFbZmPXAYsGIJSqSQ1NZW5c+dy4sQJCgoK5HVlZWV88MEHJCUlsWLFCtzd3SdwpIKRoHZ2wNfZAd+QoZ2wwOLY6RgQc1p6+oWdHtqtxJ1Hhidjyeppb7a8voahAcpgydpx8VTjqlX3P1oEHRetWhZ4nFwdkBSS6ColGBHbtm1j27ZtEz2MSYVw3EwipqMiLBBMV/Lz8zl48CBgCYP8m7/5G3zGoQvXreUrMNTWAhD21y9wHmdhYywxGAzs2rVL7pyjUCh48803CQkJmdBxmUxmqm+1Uppfz+1L9Q+8i6l0UBA215voBX4Euui4u20zAJJazazLhU81hvb2dj7//HOamprkZc8++ywpKSlPtV3B9KCjo4P9+/dz69Ytm+WpqamsXr36icoO69t7yCprIqs/zLiyueuRrwn2dCIl3IvkCC+Sw72I8nUZc9ecqbubknnz5Z9nnj+Hytt7TPc5XaiurubIkSPcuXPHZrlKpWLx4sWkp6ejVj9ZQLtg8mM2melq77Nx6bQ399De1ENHi2VZT8fo3SBSKCVctGrUfW0oyopQ97biHuJD8Duv9os7apzdRz9MeTrOrwYcN3Hb/2Gih2JD8Q//Y9QcN4KhCOFmEjEdTywCwXTFaDTyxz/+kebmZsDy/t3RXxozlpSufQZ9f65FyCcf45qe/ohXTC10Oh0fffQRHR2Wu/1ubm689957k6b7iclooupWK6V59dy+1EBP5wNEHJWEV3U+/g0FeLdcZ+7VS0+977a2Nj7//HObFpgbN25k4cKFT71twdTHbDaTk5PD0aNHMRoHQ4j9/f157rnnnroE5m5zF1llTZwva+RCWRMN97UeHw5vF0eSw71YHG3pWhXpM/pCjqm3l5LEJPnn6LNncPDzG9V9TGfMZjMlJSUcP36cxsZGm3UuLi4sX76c+fPniwBjO8XGtdNs7dqxiDsdrb0Y9aPncpMkcPawcupo+8uxvNR4+DrhF/b4TrDpOL8Swo19IoSbScR0PLEIBNOZoqIifvjhB/nnd955hxkzZozpPss2bKSvrAyA4D//CbdpGFR7584ddu3aham/5CE4OJjXX3993MKKR4rRaKKqpKXfidPwwKBIhbGXiIXBRC/0JyzeGwfHJ58Atba28tlnn9HWNmhXX716Nenp6ZO++49gfKirq+OHH36wCaFVKBQsW7aMjIyMUZmAm81mbjd2klveTE5FM7kVzdxt7n7k6wI9NKRH+7Bkpg+Lo3zwdXt6N4dZr+dGfIL8c/TpUzhYddcSjAyj0UhBQQGnT5+Wy+4G8PT0ZMWKFcydOxeFQrSWFgxiNpvp7TTQ0WoRcjpbe2VBp7OlX9xp6UXf+/COdiPBN9SNF/7j47uMp+P8Sgg39okQbiYR0/HEIphcmPr6MPf0YNbrkdRq0XnjKTGZTHz44YdycGxISAhvvfXWmE6gb297jt7r1wGY8b//Dfc1a8ZsXxNJdnY2hw8fln+Oi4tj+/btk3bSYDSYuHejhdL8Om4XNtLXPbyIo3JUEB7vQ/QCP0LnPpmI09zczGeffUZ7f0g1WEpinnnmmUn79xGML3q9nmPHjpGTk2OzPCAggC1bthAYGDjq+6xp6yan3CLi5Ja3UFLX/sjXzApwIz3ah4yZPqSEe+GifvzoRbPRyI24ufLP0SdP4BAU9NjbEVjo7e3l/PnzXLhwQe70N4Cfnx+rVq0iJiZGCMWCx6Kv2yALO3U/n6T++Hl61Z4YgqIwzphJR2sPvZ0P75IVkejDs79JeOhzhmM6zq9k4ea5SSbc/CiEm7FECDeTiOl4YhFMLmr+0+9o/fZbALzf/jV+f//3Ezyiqc/t27f54osv5J+3b99OfHz8mO2v/IUX6blyBYCgf/49Hhs2jNm+JhKz2czBgwdtwjOXLFnCqlWrJnBUI8NoMFGRU0nh//iKBp9EjKrhA1tVaiXh8ZZMnLA4b1SPIeI0Nzfz5ZdfyqV6YPkM2bZtGyqV6DsgsHDr1i0OHjyITqeTlykUCpYsWcKSJUvG9H+ltauPvIoWsm43cb60kRu1DxdyHJQS80I9yYj2IT3ah8RgD1QjyLowm83cmD3YXS/6xHEcxtj5aA/odDrOnDlDQUEB908VgoODWbVqFRERERM0OsFUpnnXLur+8b8B4LpqFSF//ANgKcvqbO2ls9+x02Hl2Olo6SFsrjdpWx6/bf10nF8J4cY+EVd3AoEdMV07Ek0kkZGRxMbGUlJSAsCxY8eIjY3F0XFs2uTayzGUJIkNGzbQ2trK7du3AcjMzMTT05P58+c/4tUTi1KlIDzem74bf8UkfU2z1yx6Xvv/UnG9jb6eQbu4oddIaV49pXn1qNRKIuK9iZrvR8gcL7k71YPw8vLirbfe4quvvqK6uhqwXJR2dnby0ksvodFoxvR3FEwNZs6cyW9/+1uOHj0qi6Amk4kzZ85w/fp1tm7dStAYuVO0zo6snuPP6jmWbJ2G9l4ulDVy7lYj50obqWmzbUetN5rJKW8mp7yZfzl2Eze1irQob1nIeVDQ8f3LxP3I0cHd3Z1NmzaxePFiTp06xdWrV+V19+7dY9euXURFRbFy5coxLxEWTC/MpsH3qKQYfP86OCrR+jmj9XOeiGEJBJMeIdwIBHaEZCUmTOdJ/3izdu1abt26hclkQqfTkZWVxbJly8ZkX/Yi3IClde0LL7zAJ598IrfC/umnn9BqtURGRk7w6B6O1J8jojAb8Gm6ysztwUgeCVReb6Y0v47yy43o7xNxbuXVcyuvHoVKIjjGk7B4H8ITvHH3Ht6x4+rqyuuvv86ePXso6889qqio4LPPPuPVV1/FzW34FrEC+0Kj0bB582bi4uI4cOCAnI9UX1/PX/7yFzIyMli2bNmYO7V83dRsSZrBlqQZmM1myhs7OVdqEXKybjfR3mNbJtHea+DYtTqOXbOUogZ6aFgU5S13rbIJOpasWgyLduCjire3N88//zzp6emcPHnSpnNZWVkZZWVlzJ49m5UrV+Lr6zuBIxVMGazfo5Io730aJKFT2xVCuBEI7AjrSb+pr28CRzK98Pb2Ji0tjQsXLgBw7tw55s2bh7v743c/eBSSo/0IN2CZdL7yyit8/PHHdHZ2YjKZ2LNnD7/+9a8n9SRBum8SbDYYUDkoiEjwISLBB4PeyN1rzZTm11tEHKvgRpPBTOW1ZiqvNZP5LXgFuRCe4EN4vA/+Ee4orO5QqtVqXn75ZQ4cOMCV/hK6uro6PvnkE1599dVxaVEvmBpERUXx29/+lmPHjpGXlwdY3CmZmZncuHGDLVu2EBwcPC5jkSSJSF9XIn1deW1ROAajiaKqNtmNU1DZgt5oOyOpaevhx4IqfiyoAsDH1dKxKjncC19tMBEt91BiHhRwBKNKYGAgO3fu5M6dO5w4cYLK/u6GANevX+fGjRskJiayfPlytFrtxA1UMPkxWwk3IpdNIBgxQrgRCOwIa+EGO5j0jydLly6lsLCQrq4u9Ho9x48f57nnnhv1/UgOViVYdnIMPT09efnll/n8888xGAz09PSwe/du3nnnHVxcXCZ6eMNzXwcss8G2o4bKQUlEoi8Rib4Y9EYqiy0iTmVx05DuVM3VnTRXd1Jw+A4aVwfC5noTHu9D6BwvHJ1UqFQqtm7dipubG+fPnwcs3ac++eQTdu7cOW6TccHkR61Ws3HjRuLi4ti/fz+tra0ANDQ08Mknn7Bo0SJWrFgx7h3cVEoF80I9mRfqyb9bNZOuPgM55c2ykDNcPk5jRx+HrtZy6GotLPtbnPXdzGm+w5K8Ohab3UgI9kCtEi2sR5uwsDDefPNNSktLOXHiBLW1tYBFBCwsLKSoqIiFCxeyZMkSXEUDBMEwWJdKITKuBYIRI4QbgcCOEKVSY4dGo2HVqlUcPHgQgCtXrpCWljbq+RH2VCplTXBwMM899xx79uwBLMLE119/PSnbhEN/7oZSCcZ+wcbw4GOlclASmeRLZJIvRqOJ2rI2KoqaqLjSSGtdl81zezr0lGTXUpJdi0IhERSjJby/pGrNmjW4urpy5MgRALq7u9m1axc7duwgJiZmzH5XwdQjIiKC3/72t5w4cYKLFy8Clon3hQsXKCkpYcuWLYSGhk7Y+JwdVSyP9WN5rB8wmI8z0LXqZl3HkNd0OTiR5z+LvNwG/mduA44qBUnBWpIjPEmJ8GZBmCeuT9C1SjAUSZKYOXMmUVFRXLt2jVOnTtHU1ARY2opfvHiRgoIC0tLSWLx4MU5Ow5d7CuwUK1ecJEqlng5hMLQrxCeYQGBHiFKpsWXevHnk5OTI7cGPHj3K66+/PqptU+35GM6ZM4fVq1dz/PhxwBKQuW/fvknbJlxSqTD3Czdmw8PbnA6gVCqYEePJjBhP0rdH01rXRUVRIxVFTdTcasVkdafSZDJz70YL9260cO67W3gGOBMe78uqRZs4lf0zJrMJvV7P119/zebNm5k3b96Y/J73o+814qAWTofJjqOjI+vXr2fOnDns379f7lDW1NTEp59+SlpaGitXrhyzoPXHwTofB6Cls4+8Oy3klDeRU9FC0Z0mTArb/7k+g4mcimZyKpr546kyFBLMCXInJdyblAhPFoZ74eOqnohfZ9qgUCiYO3cus2fP5vLly5w+fVruYKbX68nMzCQ3N5eMjAxSUlImxf+SYBIgSqUEgidCCDcCgR1hb/ko441CoWDNmjV8+eWXgCUo9tatW6PqdrD3Y5ienk5zc7PcIae4uBgvL69J2SZcUqkw9/YCIxdu7kfr70ySfyhJq0Pp7dJTea2ZO0VN3LnaRE+n7fFvqe2ipdaSOxGgWUqnop4ehwb61C3s37+f9vZ2lixZMqpC4nAc/+waDXfbCYrWEp7gQ8hsT9TOk88VJbAQFhbG+++/z6lTp8jKypKXZ2dnc/PmTbZs2UJYWNgEjnAoni6OrJnjz5r+jlWXFqRy3dmfq94RlK3YwuXGXnr0tiHFJjNcrdJxtUrHp+fLAYj0dSE1wkvOygn2dBrz98d0RKlUMn/+fOLj48nLyyMzM5OuLotbsKenh+PHj5Odnc2yZcuYN2/emAdhCyY3ZutwYoV4vwkEI0WcOQUCO0Jk3Iw90dHRREZGyi2sjx07RlRUFErl6DgQ7P0YPqhNuJeX17g5SkaKdUCxWf9kwo01amcHZi70Z+ZCf0wmM3W322Q3TnN1p81z9T0mHPHBER/MmNE7tJF1sITm2k42P//MmDmUejr16Jq6aW/u4fblBkpyLPkXWj9nQuO8CJvrTchsLzE5nmQ4OjryzDPPMGfOHPbt2yeXvTQ3N/PZZ5+RkpLC6tWrJ61jwslsYF7DLeY13CLif/wNishoiqrayK1oJre/vErXM/Q9eLuhk9sNnXydcxeAIA8Nyf1CTkqEF9G+rjZh4IKH4+DgwKJFi5g/fz5ZWVlcuHCBvn5naEdHBz///DMXLlxg+fLlxMfHT0qnpGAcMIlSqVHBPAm7Sk228UwzhHAjENgR1sG29lZmM56sXbuWDz74ALCEfhYWFrJgwYJR2bb1MbRHxw1Y7u7u2LGDTz/9VG4TfvDgQbRaLRERERM8Oius84geknHzJCgUEoHRWgKjtSzaFk1bQzd3rjZScaWRqputmKw68khIOOq1OOq1VJ2Ej7JOMCctlMhEXwJnalEqR+/Cubm6g+bqTgKjPFj8XDSNd9tpuNtBQ2U7V09XUXy2mq3/xzwCIjxsXmc2m4WYMwkICQnh/fff5/Tp01y4cAFzfxZFTk6O7L6ZVO+xfiRJGpwvmM04qhQsCPNkQZgn7y+LwmQyU1LXTm5Fs5yTU6frHbKd6rYe9hdWs7+wGgBPZwcSgrUkhmhJDPYgIViLr5sor3oUarWa5cuXk5yczLlz58jJycHYXzba0tLC3r17OXPmDEuWLCEhIWHUbmwIpgg27cDFeV8gGClCuBEI7Ah7L7MZLwICAkhMTOTy5csAnDp1irlz56JWP/0Fv72GE9+Pk5PTkDbh33777aRqE27TEvwJS6VGioevEwkrQkhYEUJfj4G715upuNLInatNdLfb/p8Yu5UUnaqi6FQVjholwbO9CI71JHiWJ1p/56cSUGpv6zCZzITN9SYg0oOASItA09HSS1N1B33dBrR+zoCtWCNJErrGbpQOClw8xMR4InFwcGDNmjXMnj2b/fv3y+Joa2sru3btYuHChaxZs2ZUzmejhvX/rMk0ZLVCITE70J3Zge68tigcs9lMZXOXLOLkVrRQ3tg55HUtXXrO3GzgzM0GeVmQh4aEYC0JIR4kBmuJD/bAXSNKAYfDxcWFZ555hrS0NM6ePUtBQYEsBjY3N7N//37OnDlDRkYGSUlJooTKbrCyZQjXlUAwYsQZUiCwI2wm/X32O+kfD1auXElxcTEGg4GOjg6ysrJYvnz5U2/XWnyzd9fUcG3Cv/rqK95+++1J0SbcplRqjIUbaxw1KqLm+RE1zw+zyUxdhY6ywnqunLuNqct2gtnXY+T2pQZuX7JMTF08HJkxy5PgWC+CZ3ni5qV5rH3XV1iCSWfEeNosd/VU4+o5/ES/8V47N7JquXu9GV1jNxoXByKTfJm7bAaeARN/HO2V4OBg3nvvPc6cOcO5c+fkCXdeXh63bt1i8+bNREVFTfAo+7Ge/Jkf7dWXJIkwbxfCvF3YsTAEgHpdD7kVLeRWNHOxvJkbtbphN1Xd1kN1Wy2Hi2vlZZE+LiT0O3ISQzyIC/JA4yBcJAN4eHiwadMmFi9ezOnTp7l69ar8/9Ta2spPP/3EmTNnSE9PZ8GCBZOyU6Bg9BAZN6OIKE2yK4RwIxDYEbbtwO170j/WeHh4kJaWxrlz5wA4f/48CxYswM3N7am2a+8ZN/cTHBzMtm3b+O677wCLDf+bb77htddem/CL/4kSbmzGoJBk50valkj27vmJ0ku1OPZ449inRcL2bmdnWx83L9Zx86KlM5qHrxPrfxOPd5DrI/fV0dJL470OHDUqejr0NFS24+7rhNpJhdlkxmw2o+gvyxpw2zTea+fUlyXU39Gh9XMmZLYXPZ16rpy+R2t9NytfmyUcOBOISqVi1apVzJ49m3379lFfXw9AW1sbf/3rX0lKSmLt2rU4OztP6DitXWJm05PNZPzcNWxICGRDQiAAbd16Lt9t5cq9VgrvtnHlXiv17UPLqwBuN3Zyu7GTff0lVkqFRIy/m1xelRDsQWyAGw6jWJY4FfH29mb79u0sX76czMxMrly5gql/Et/e3s7hw4fJzMxk8eLFLFy4cHK5ugSjh8i4EQieCCHcCAR2hCizGV8yMjIoKCigq6sLvV7P6dOn2bRp01NtU2TcDCUuLo7m5mZOnDgBwN27d9m/fz/bt2+f0NwUyWF0w4mfFqVSyfaXNnPS7ySZmZlgUuDYp8XJ5IO3JpT2+qFibntTz4hdN4132zEaTPT1GDjySTFqjZLAmVpmLwokNM4bicFjIUkSRr2Js9/cpP6OjqgkX1a9MQcHtZKeDj1FZ+6R81M5V89UkbIxAknclZ1QgoKCePfdd8nMzCQzM1OebBcWFnLz5k3Wrl1LYmLixL3frPdrHloq9SR4ODmwNMaXpTGDpZe1bT1cvmcRc67ca+PKvTbauoeeh40mM9drdFyv0fFNriX4WK1SMCfIncR+ISchWEukj4tdhh97e3uzdetWli1bxvnz57l06ZKcgdPZ2cmxY8c4d+4cixYtIiUlBY3m8Zx/gkmOaAcuEDwRQrgRCOwIhbXjRpRKjTkajYZly5Zx6NAhAAoKCkhNTcXPz++JtynEt+HJyMigubmZS5cuAXD16lW8vLxYuXLlxA1Kae24mRzHSpIkVq1ahaurK4cOHaJP00wfzXQoy9jw1hbcFP7cK2nh3o0WdA3d+Ee646gZ2aWCxtWBlE2ROLk50N7Uw52rTVQUWb6SN4STuCIEpcPgRXr5lUZqytrwCXYl44UYHNRKzCYzGlcHElaGcPVMFUVn7rHw2XCUdji5nWyoVCpWrFghu29qay2lQl1dXezbt4/CwkI2btyIj4/P+A/uMUulnpQADw0BHgE8ExfQvyszd5q6+sUciyvnapWObr1xyGt7DSYuVbZyqbJVXuamVjF3hgcJIR4kBWtJCNES5KGxm6BuT09PNm7cyJIlS7hw4QL5+fkY+t2J3d3dnDx5kgsXLpCamkpqauqEO7sEo4NNqZR9/KuPCRKTr6uUOJxjixBuBAI7Qkz6x5+FCxdy8eJFmpubMZvNHD9+nFdeeeWJtydyioZHkiQ2btxIa2sr5eXlAJw9exYvLy+SkpImZkzjGE78uKSmpuLq6sqPP/6I0WjEaDRy4JcfWbNmDctfWWwJC27qprdr5OO2DiMGiF8eTGl+Pcc/v0buzxUERWvl9T0dem7lWsqxYlMDcPVUYzaZZWeNBAREeVBT2kpzdSe+oU9XYigYPQICAnjnnXe4ePEip06dQt//WVJRUcGf//xnMjIyyMjIGN9SxUeEE4/dbiXCfVwI93FhS9IMAAxGE6UNHVy52yYLOjdqdeiNQ2dY7b0Gsm43kXW7SV7m7eJI3AwP5ga5M3eGB3ODPAjxcprWYo6Hhwfr16+XBZzc3Fz5/6qnp4czZ86QlZVFcnIyixYtwtX10aWbgkmM1VtBEo4bgWDECOFGILAnhHAz7iiVSlavXs2ePXsAuHnzJuXl5U/cUld0BnswSqWSF154gU8++YTGxkYADhw4gIeHx4S0MLbJuDEOvQM/0cTFxeHm5sbXX39Nd3c3AMeOHaOlpYX169fj7u0E3iPfnnWXqAERJnqBH93tfZz99ibF56rxC3dHoZBoqu6gpqwVtZOK8Hhbh4bZZMbRSYVCIdHdoaezrRdf3ETL8EmEUqlk8eLFzJkzh0OHDlFSUgKA0WjkzJkzFBUV8eyzzxIdHT0+A7JyZJnH0HEzElRKBbMC3JkV4M4LyZbg4x69kRu17Vy518rl/ryc0oaOYc1BTZ19nL3ZwFmrTlZuGhVxQe4khXgyP1TL/DBPfFynX/6Lq6sra9euJT09nYsXL3Lx4kV6ey25Qn19fZw/f56LFy+yYMECFi9ejIeHxyO2KJiU2DhuhHAjEIwUIdwIBHaEbamUCCceL2bPnk1ISAh371qyDg4dOsS77777RK1PbTJuxDEcgpOTEzt37uQvf/kLXV1dmEwmvvrqK1599VXCwsLGdSw2ws0kyLgZjtDQUH7961+ze/duWlpaAEvXoPr6enbs2PFYYdrWooqkkDCZzCgUEv4R7gA03GlHoZAwGkw0VXXQ3aEnpL8F+cBrLN9YHpprLO2Z3bw1Q7YvmBxotVpefvllrl+/zi+//EJ7eztgafX85ZdfEhsbyzPPPIOXl9eYjsMm4HQcHTcjReOgJClES1KIFhZZlnX0GrhaZRFxLveXWd1t7h729e09BrJvN5N9u1leFubtzIJQT+aFebIg1JPYALdpU1Lo4uLCypUrWbRoETk5OWRnZ8vissFg4OLFi+Tm5pKQkEB6ejq+vr6P2KJgUmGdcSPO60/HJCuVEowtQrgRCOwIUSo1MUiSxNq1a/nkk08AqK+v5/z58yxbtuzxtyWO4SMZaBO+a9cuDAYDer2eL7/8kp07dxIeHj5+A7EOJzZOTuEGwMfHh1//+td8/fXXVFVVAVBZWcmHH37Ijh07nljwGrgc72ztRaGQcPNSY+gzYjSaaaqyiDJ+4RZRx6ZMSpLo7TbQVt+NSqVA6ydyLSY7s2fPJjIyklOnTnHx4kXZ9VJSUkJpaSmLFi1iyZIlY9claApO/lzVKtIivUmLHLS1NXf2UVzdxtUqHVer2yiuaqOiqWvY199p6uJOUxc/XrK8Z10clSSFapkf6sn8ME/mh3ji4Ty122o7OTmxbNky0tLSyM3NJSsri85Oy7nDZDJRWFhIYWEhs2bNIiMjg+Dg4AkesWAkmI2Dwo2kVE7gSASCqYUQbgQCO8KmlbTBIEoPxpGQkBAWLlxIXl4eYMlfmTNnzmPfKZwMLaanAiEhIbz00kt88803snize/duXnnllXErm5KswomZhKVS1ri6uvLGG2/w008/cfnyZQA6Ojr4/PPPWbt2LWlpaQ88V7TUduLk5ojGxXJ+ub8dc31lOyaTGQ8/Z/nmYGudZTLqF+Zu89wBAae+XIfRaCIoWotSpRDnqimAWq1m3bp1JCYm8ssvv8gOQ6PRyLlz57h8+TJr1qwhPj5eHMsH4OXiyJKZviyZOfi5oOvRc71ax5V7bRRUtpB/p2XYtuSdfUbOlzZxvnQwLyfaz5X5oVoWhHkyP9STKF/XKdnFSq1Wk5GRQUpKCgUFBWRlZdHW1iavv3HjBjdu3CA8PJyMjAyioqLE/9gkxuZGhhBuBIIRI4QbgcCeUN13902vB6vyKcHYsnr1akpKSmhvb7eEwR44wJtvvoniMcL5RMbNyImOjubll1/m66+/HiLeREZGjvn+re8kTtZSKWscHBzYunUrISEh/PLLL5hMJsxmM0eOHOHevXts3rx5iGPCaDBRfK6ang49i7ZG4aJV27Tu7tL1UZxZDUDwLE9UDgpMkpmWWstdc5+Q/pDR/peY+7+9e8NSEjIjRmtZLSZhU4bAwEDeeustioqKOHbsmFw+1d7ezo8//khubi7r168nKChobAYwwRk3o427xoHUSG9S+505ZrOZqtZu8u+0cKmylfw7LVyr0WE0Df29S+s7KK3vYE/evf5tqZgX6ikLOYkhHrhppo4rx9HRkbS0NJKTk7l69Srnzp2joWEwC6iiooKKigoCAgLIyMhg9uzZKIUwMPkQjptRY7J1lRKMLUK4EQjsCOtJP1gm/pIQbsYNjUbDxo0b+frrrwG4e/cuubm5pKamjngbolTq8YiKiuKVV17hq6++wmAwYDAY+Oqrr3j55ZeJiooa252rpkaplDWSJLFw4UICAgLYs2cPOp0OgOLiYurq6njxxRdtXGImkxmT3kTJxVqqSlqISPTFe4YLLlo1bfXdXD1bRXd7H2Fx3nIIcXdHH90dejQuDri4q+X9ArIboOKKJVw6bO4EtJYWPDWSJJGQkEBsbCznzp3jwoULGPtdZ3fv3uWjjz5i/vz5rFy5UnQIekwkSSLY05lgT2e5k1VXn0F25BTcaaWgsoXmzqEZaLoeA2duNnCmP/hYIUGMvxuJwVrigz2In+HBrEA31KrJPZlWKpUkJiYSHx/PrVu3yMzM5N69e/L62tpavv/+ezw9PUlPTycxMXF8u5wJHoqt40aEEwsEI0UINwKBHSE5DBVuBONLbGwscXFxFBcXA3DixAliY2PRarUjer0olXp8IiMj2blzJ1999RV6vd5GvBnLrjc2dxIneanU/QQHB/Pee+/x/fffy+3VGxsb+ctf/sLWrVuZM2cOAA6OSpLWhOLm48St3DqKztwbsq3ZiwJJWh0q/2wymvAOckHfa6StoRuvIBc5yBig+lYrLXVdaP2c5WDjh9HToaemrJXAaK1criWYHKjValatWsW8efM4evQoN27ckNcVFBRQXFzM8uXLSUlJeTpnhJ07spwdbfNyzGYzd5q6yL/TIpdX3axr535TjskMN2rbuVHbzrd5ltI2B6VEjL8bCcEezJ3hQcIMLTEBrpNSzFEoFMTGxhITE0NlZSXnzp3j1q1b8vqWlhZ++uknTp06RWpqKgsWLMDFxWUCRywA7nPciKmoQDBSxLtFILAjhHAzOVi/fj23b9+mu7ubvr4+fvrpJ3bu3DmichDhuHkyIiIi2LlzJ7t370av12M0Gvn666956aWXmDlz5pjs01Zkm1rCDVg6u/zqV7/i5MmTnDt3DrC05N2zZw+LFy9m1apVKJVK3H2cmLcmlHlrQtE1dnOvpIW2hm6cXB0ImqnFO8gVpYPlrqrZZMbdxwnPQBdK8+tprunEK8hFFm3aGrq4fNIygZy9OFB+jfSQXI67N5o5+rFFCPUKciFoptbyFa3FRTv9WiZPRby8vHjppZcoKyvj8OHDcnlLb28vR44cIT8/n3Xr1o1f+/BpjiRJhPu4EO7jwvYFlsDe9h49l+8O5uRcqmxB1zNU/NcbzRRX6yiu1gGDYs6sAHfmzrC4chKCPYjxd8NRNTncEpIkERYWRlhYGLW1tZw/f56rV6/KIdmdnZ2cPHmSM2fOEB8fT2pqKoGBgRM8avvFbH0jQzhuno5pVhoqeDhCuBEI7AjpvvbTwrExMbi6uvLMM8+wb98+AEpLSykqKiIhIeGRrxXCzZMTHh7Oq6++yu7du+nr68NoNPLNN9/w4osvEhMTM/o7tLpDPVVKpe5HoVCwevVqgoOD2bt3L729llDUCxcuUF1dzfPPP29T6uLu48QcH6cHbm9AgIlI9KH8ciM5P5WjclDgF+6OQiGR+1MFtwsbiE0JIHqhX/+LHj7Gmlut8vfN1Z00V3dy9Yyl0467rxNBM7UERnrgH+GOZ6DLlAxnnS5ERUXx/vvvk5uby6lTp+T/p8bGxtFrHy4mMsPipnEgY6YPGTMt5Ycmk5myhg4u3W3tb0vexvUaHb2Goe3U9UYzRVVtFFW18XX/MkelglmBbv2uHIs7JzbADYcJnogHBASwfft2VqxYQVZWFpcuXcLQf61jNBrlTlShoaGkpqYya9YskYMz3lgJN8JxIxCMHPFuEQjsCEmpBIUCTJYLMzHxnzgSExMpKiqirKwMgEOHDhEVFfVoG7e1i0Mcv8cmLCyMV199lS+//HKIeBMbGzuq+7K5IJ2CjhtrZs2axbvvvsu3335LfX09YAkC/fDDD3nhhRcICQl5rO3FJAfQ0dxL9v7bHP2kGFdPNZ2tvfT1GgmK1rJ4ezTO7pb8rUc50VSOSpzcHOhuH/p+0DV0o2vo5saFGstz1Ur8Qt3wC3fHP9wdv3A33Lw0Ivx4HFEqlaSlpREfH8/JkyfJz8+X1z1x+3Bx/B4bhUJipr8bM/3deGGh5f2rN5q4VddhEXKqWimq0nG9RkffMGJOn9HElXsWweer/mWOKgWzA9zkvJz4GVpm+rtOiJjj5eXFhg0bWLZsGXl5eeTm5sqtxAEqKyuprKzE3d2d5ORk5s+fL8qoxgmzjXAjHDcCwUgRwo1AYGdIDg6Y++9yion/xCFJEhs3buRPf/oTer2e7u5uDh8+zPbt2x/+OmvHjXBMPRGhoaH86le/4ssvv6S3txeTycS3337LCy+8wKxZs0ZtP5KN42ZqCzcA3t7evP322xw8eJCioiLA0inos88+45lnniElJeWxBJDE1SH4hblxK6+exnsdhMx2ISzem4hE38fKqlm8PZpFz0XRWtdF9a1Wqktbqb7VSkfz0JbJhl6j5TlWLh0nN4d+EcddfhRZOWOPi4sLmzZtYsGCBRw6dEi0D58EOCgVzAlyZ06QOy8kD4o5N+vaKbrXJrtubtS002ccRswxmLh8r43L9wZbdTuqFMwJdLcIOf2Czkw/V1TjNGF3dXVl+fLlZGRkcO3aNS5evEhVVZW8XqfTceLECZsyqoCAgHEZm91isi6VElPRJ8Y8CbtKTbbxTDPEu0UgsDOEcDN58PT0ZNWqVRw+fBiAoqIi4uPjH1q2I0qlRoeQkBB+9atf8de//lUWb/bs2cPzzz8vB+8+NTbhxNNDZHN0dOS5554jODiYI0eOYDKZMJlMHDp0iHv37rFp0yYcR9ipTqlUEDzLi+BZlrIYo8GE8gkzMyRJwjPABc8AF+KWWDrt6Jq6qSlto7q0lfoKHU1VnZiHaZnc3a6noqiJiqImeZmHrxP+EYNijk+IKyoHUU4xFgQFBfHWW29x9epVjh49+tTtw82iVGpUcVAqiAvyIC7Ig5f6l/UZ+sWc/hKrq1Vt3KjVoTcO/dv3GUwU3m2l8G6rvMxRpSDa15VZgW7MCnAjNsCdWQFu+Lmpx0ykU6lUJCQkkJCQwL1797h48SLFxcWY+h3IBoOBS5cucenSJcLCwkhNTSU2NlaUUY0B1plvwnEjEIwcIdwIBHaGmPhPLlJSUigqKpLvAP7000/8zd/8zQNLBGwCpvV6zGazuBv9hAQHB/Paa6/x17/+lZ6eHkwmE9999x3PP/88cXFxT71961Ips356CDdgEUkGwj2/++47eaJdVFQktwz39vZ+7O0+qWjzINy9nXD3diI21XL3XN9npLGynboKHfUVOuoqdOgae4Z9bVtDN20N3dzMqQMsZSXewa42zhzPAOeHhiYLRo4kScTHxxMbG0tmZubjtw8Xh2FccVQpmNufa/NyimVZr8HIzdoOrlRZMnMGnDmGYcTSPoOJazU6rtXobJZrnR2I9XdjdqA7sQFuli9/N1zUoztdCQ4OJjg4mDVr1pCfn09eXp5NGdWdO3e4c+cOHh4echmVs7PzqI7BnrFtBy6EsadC6NR2hRBuBAI7QxIZKZMKhULBli1b+OCDDzCZTOh0Oo4fP86GDRuGff79ncEwGOD+ZYIRM2PGDF577TW++OILenp6MJvNfP/995jNZubOnftU255upVL3Exoayrvvvsv333/PnTt3AKivr+ejjz5i27Zto1p2Nho4OCoJjNYSGK2Vl3V39FFfYSvm9HQMPS+aTGYaKttpqGyHsxaR1UGjxC/MzUbMcfXUjNevMy1xdHR8ZPvw9PR00tLSRuzsEowPapXSUgoV7CEv6zUYKaltl105V+61cbNueDEHoLVLz8XyZi6WN9ssD/FyYla/Kyc2wOLSCfd2eepyK3d3d1asWMGSJUsoLi4mOzubmpoaeX1bWxvHjx/n9OnTJCQkkJqair+//1PtU8B97cCFcCMQjBQh3AgEdoat42b6uACmMn5+fixZsoQzZ84AkJubS3x8PKGhoUOeO1xL9yFijuCxCAoK4vXXX+eLL76gu7sbs9nMDz/8gNlsJj4+/sk3bO24mSalUvfj5ubGa6+9xokTJ7hw4QJgafH8zTffkJGRwcqVK1EoJq8V3snVkbC53oTNtTiEzGYz7U091PWLOPUVOhrutGPQD9Npp8dIVUkrVSWt8jIXD0f8+oUc3xA3fEJccXZ3FK64x+Rh7cNPnjxJTk4Oy5cvZ968eUNLWcQd6EmDWqUkIVhLQrBWXtajN1Ja30FJbTslde1cr9FRUttOffvQTKoB7jZ3c7e5m2PX6uRlo1lupVKpSExMtCmjunbtmk0ZVUFBAQUFBYSHh8tlVJP53DaZsW0HLoQbgWCkCOFGILAzRKnU5GTJkiVcu3ZNnqAcOHCA9957D4f7RJkhLd3FMRwVAgMDef3119m1a5cs3vz444+YzeYRtWkfDptjNcW7Sj0MpVLJ2rVrmTFjBvv376evrw+Ac+fOUVVVxfPPPz9lurVIkoS7jxPuPk7MXGi5s24ymmiu6aSufMCV005zdcewXac72/oov9xI+eVGeZmTmwM+wa74BFuEHJ9gN7T+TihEtsMjsW4ffvr0aXp6LKVtHR0d/PTTT2RlZbFq1SocRK3UlEHjoJTLrKxp6ezjRm07N2otQs6N2nZu1rXT1Tf8ufNh5VazAtyYFfD45VaSJBESEkJISAg6nY68vDzy8vLo6uqSn1NRUUFFRQVarVYuo3JycnqCv4QdI9qBjxrS0HsKgmmMeLcIBHaG5Ggt3PRN4EgE1qhUKjZv3swnn3wCQGNjI5mZmaxcudLmeUMcN6Kz1KgREBAgO2+6urpk8cZoNDJv3rzH3t50L5W6n7i4OPz8/Pj2229pbLQIF+Xl5XLL8ODg4Ake4ZOhUCosokuwmxx8rO810nBfXk570/B5Od3teu5eb+Hu9RZ5mdJBgXeQi0XQCXHDJ9gV72BXHDXisux+BtqHJyYmcu7cObKzs+X8m6amJvbs2YNPUiIJ+j58GxofsTXBZMXTxZFFUd4sihrMxzKZzNxr6eZGrY4bte39go6O8sZOHlBtRWuXnuzbzWTfti23mqF1IsrPlWhfV6L9Br+8XIYvuXN3d2flypU2ZVS1tbWD+2lt5dixYzZlVH5+fk//h7ADRDtwgeDJEFcIAoG9oRKOm8lKSEgIqampXLx4EbA4FubMmWPTmnS4UinB6DEg3uzatUu+y7p//34MBgPJycmPt7Fp2FXqUfj6+vLOO++wf/9+rl27Blja7X722WesW7eOhQsXTouyIQe1kqCZWoJmauVlXbo+6u/oqCvX0XC3nca7HXS2Dl/+YdSbqL/TTv2ddmAwU8PD16nflTPo0HHRjl2nnamEk5MTa9asISUlhdOnT1NYWCh3kGp0d+fkqlUEVVWxVqdjavi7BI9CoZAI9XYm1NuZtXGDn4MD5VYWMWdQ1HlYuVVVazdVrd2cvdlgs9zLxZFoX1eLqOPnSpSvC9F+rgR5OKFQSDg4OJCUlERiYiJ3796Vy6gG/vf0ej35+fnk5+cTGRlJamoqM2fOFGVUD8Mo2oELBE+CeLcIBHaGKJWa3KxcuZIbN27Q1taGyWTiwIEDvP3224MXgffVg4tjOPr4+/vz5ptvsmvXLjo6OgD4+eefMRgMLFq0aMTbsekqNY1Lpe5HrVazY8cOsrKyOHbsGGazGaPRyM8//8y9e/fYsGHDtAyWdXZ3JDzeh/B4H3lZd3sfjfc6aLzbQeO9dhrvddBS2zVsW3IY7GZVVjA4udS4OAyKOf3uHG2AM0o7vVPt4eHBli1bSEtL48SJE9y8eVNeVz1jBrvOnyOxs4MVK1bg4eHxkC0JpioPKrdq7uyTS61GUm418JqczmZyKmwdOk4OSqL8XO5z6Hiy9bntrF27Vi6j6u7ull9z+/Ztbt++jaenJ8nJycybN0+UUQ2DcNyMIiLTy64Qwo1AYGfYODZEmc2kQ61Ws2nTJr788ksAqquryc7OZvHixYClBl9ycJAFGyHcjA2+vr6yeKPTWTIUjhw5Ql9fH0uXLh2RA8LeSqWskSSJxYsXExQUxHfffSe32r18+TK1tbXs2LEDHx+fR2xl6uPk5kjIbC9CZnvJywx6I83VnUMEHX3P8P8jPZ167t1o4d6NwVIrhUrCO8gVnxBXfEPc8A11w3uGKw5q+wn69Pf355VXXuHOnTsc/Nd/pdHdHbDMYwoLCykqKiIlJYWMjIwpk7EkeDq8XBxZHOXD4qjBc8tAuVVpQzul9R2U1XdS2tBBaX0Hbd0P/vzs1hu5WqXjapVtho5KIRHm7cysAE9mL9hCqL6OxtvFNDXUy89paWnh6NGjnDx5krlz57JgwQKCg4OFc64fs0mEEwsET4IQbgQCO8M6MNXUJzJuJiPR0dEkJCRw5coVAE6cOEFERASBgYGWJzg4gBBuxhxvb29ZvGltbQXg1KlTtLa2snHjxqHdbO7HxnFjn8cpPDyc9957j++++467d+8CUFdXxwcffMCqVatITU21u5IClYMSvzB3/MLc5WVmkxldU3e/kNP/dbedjpbhSz9MhsH25NcHSq0k8PBxwjvYFe8gF8vjDFc8fJyQFNN3whgWFsYzl69QAVxJTKC9X8AxGo1kZWWRl5dHWloaixYtwtnZeULHKhh/rMutVs4abOVtNptp7OijtL6D0oYOyuotYk5pfQe1uuHzqgAMJjNlDZ2UNXTyc9HA0lBiXPxJdGzApbuOARuEwWCgsLCQwsJC/Pz8WLhwIfHx8cKFY7B23AjhRiAYKUK4EQjsDOG4mRqsW7eOsrIyOjs7MRqN7Nmzh/feew+NRmNx3PQ/T7R0H1s8PT158803+eKLL2hqagLg0qVLtLa28sILLzz0AtzGAm6039YP7u7uvPHGGxw9elTObzIYDBw5coTr16+zdetWvLy8HrGV6Y2kkPDwdcbD15mo+YMBpz0detmRM+DOaanpwjRcqZV5sNTq9qXBUiuVowKvIFd8ZvSLOUEWQUfj6jB0G1MUyWwmuLqaoOpq2v6f/4cLdyrkMke9Xk9mZiY5OTksWrSItLQ0NBrNBI9YMNFIkoSvmxpfN7VNIDJAe4+esoZOWcgpre+grKGDO00PCkWWuNmp4WZnCC74EauqZ6ayESdp8PO5vr6eX375haNHj9q9C8e6qcL9nTIFj4ckSqXsCvFuEQjsDOsPSTHpn7w4Ozuzfft2vvjiC8BivT5w4AA7duy4r820fTo5xhMPDw/eeustvvnmG9k1Ul5ezieffMLOnTvx9PQc/oVK61Ip+36vKZVK1q9fT0REBAcPHpRLpyorK/nzn//MmjVrWLhwod25bx6FxtWB4FleBM8aFLaMekt78oEA5IbKdhrvtWPoG14cNPSZqO/vfmWNi1aN9wxXvGe44D3DkqGj9XdGqZp6x8DcL2UrzGYSQ0NZuGUzubm5nDt3Ts4g6e3t5fTp01y8eJHFixeTkpKCWq2eyGELJiluGgeSQrQkhWhtlvcajFQ0dnGrvp3rNTqKqy1fDVahyJ2oKTCEUGiYQZiihRhlA4HKdnm9tQtHctYSPDOOtAXziJ3hhcpO8l5shBuH6SMgCwRjjRBuBAI7Q3KwLt+w78nkZCcyMpLly5dz+vRpAK5du0ZOTg5eKnEMxxsXFxdee+019u/fz9WrVwFLy/a//OUvvPzyy4SEhAx5jY0F3I4dN9bMmjWLkJAQfvnlF4qLiwGLI+KXX37h+vXrbNmyBa1WO7GDnOQoHRT4hlpybQYwm8y0NXbTVNVB070Omqo6aarqoK2x+4HhlZ2tvXS29lJZ3CQvUyglPAOc+wWdwS8XrePkdgZY/44SODo6kp6ezsKFC8nOziYrK4ueHkv5S3d3NydOnCArK4uMjAySk5NxEJNHwQhQq5TEBrgRG+DGxoQgeXl9ew/XqnVcq9FZHqt1lDd1Um7yptzkjbuhmxhlA9HKJjRWLhxzVyt3L5/ndmEWlWZverVhhMwIZnaQO7MC3JkV6IaP6/QTF21KvIXjRiAYMeLdIhDYG2LSP6VYunQplZWV3L59G7AE5K7VavGoqwPEMRxPHBwc2L59O97e3pw5cwaArq4uPv/8c7Zt28bcuXNtX2DlHrEJY7RzXFxc2LFjB7Nnz+bnn3+WHRHl5eX86U9/Yt26dcybN29yCwWTDEkhofVzRuvnTNS8wVKrvh4DzTWdFjGnuv+xqoPeruHPGyajuV/06QTq5OVqFxU+M1zxmuGKT7+Y4xXkMnnCkM2Dyo31/41arWbZsmWkpKSQlZVFdnY2ff3Zbl1dXRw9epQLFy6wdOlS5s+fj0pMIgVPgJ+bBr9YDctjB997XX0GbtZ1cKPG0q78es0MjtS0oe2rJ1bVQIBi0IXjIJmIkhpA10BzazHfXfHjttELPSp8XNXMDnRjVoCbLOZE+7miVk2S994TYC3cCMfNU2DG5tw3KZhkw5luiE8ogcDOkFRW7cBFmc2kR6FQ8Nxzz/HBBx/Q0dGByWQic/Zs1pSXo+7rE+Vu44wkSaxYsQJPT08OHDiAyWTCaDTy/fff09zczJIlS+SJo3U7cOG4GcrcuXMJDw/n4MGDlJSUANDX18eBAwe4fv06mzZtwt3d/RFbETwMR42KgAgPAiIG2yabzWY6W/ss7pwqSxByc3XHg7NzgN5OA1U3W6m62Wqz3M1Lg2egM54BLngG9D8GOuPkOs7t3q0nL8OU2zk5ObFy5UpSU1O5cOECOTk56Psnjx0dHfzyyy+cO3eOZcuWkZSU9OjgcYHgETg7qoaUW5nNZmp1Pdyoaafo9l2qbl1D1XoHB/Pg57iXoptFijssVN2l3OjFzU5fMm/1kHmrUX6OUiER5esiCzmz+x8D3DVTQ/C2EW7G+VwhEExhhHAjENgZIpx46uHq6srzzz/Prl27LJMujZqc1BQyMs8J8W2CSEpKQqvV8s0338glGCdPnqS5uZmNGzda7txb5RXYWzvwkeLq6spLL73ElStXOHTokPy3vHXrFn/605949tlniY+PnxqTkSmCJEm4eqpx9VQTNncwlNVoMNFS2yULOgNlV51tD+4+2N7cQ3tzD5XFzTbLNa4Og0KO1aObl2ZsOlyZrITRh/yvuLi4sGbNGhYtWsS5c+fIzc3F2P/e1Ol0HDx4UBZw4uPjhYAjGFUkSSLQw4lADydWzPIDFqDX6ykqLubCxVwaa6rk5zpIJmJUjcSoGmkyOXPT6Mttozd6lBhNZm7WdXCzroMDlwe376ZWEennSrSvK9F+g18hnk6TKj/H1nEjpqICwUgR7xaBwM6wDScWk/6pQnh4OKtWreL48eMAVM+YQUlsLMHiGE4Y4eHhvP3223z11Vc0N1smroWFhXLHKduMGyHcPAhJkkhMTCQiIoIDBw5QWloKQE9PDz/++CPXrl1j48aNuLq6TvBIpzdKlQKfYEtIsTU9HXqLM0cWdDppru54YBjywGtqStuoKW2zWa5yUKAdRtDR+jmjdHjyiaX5/pCbR+Dq6sq6detYvHgxmZmZ5OfnY+oXf1paWti3bx+ZmZksX76cuLg4EZotGDMcHByYn5TE/KQkGhoayM/P5/Lly3IJKYC3ootFijukONyl3OTNdb0PTWYX7v9fb+81cPluK5fvttosd1QqCPdxtgg5vq5E9Qs6Ub6uaBzGX5wU4cSjh+gqZV8I4UYgsDNEV6mpy+LFi7lz5w63bt0C4EpiArNaWhDFJBOHj48Pb7/9Nt988w2VlZUAVFRU8Mknn7A5aDC80mwSpVKPwt3dnZ07d3Lp0iUOHz4sZ5HcuHGDyspKNmzYQFxc3ASP0v7QuDowI9aTGbGD3dNMJjPtTd201HbRUtNFS21n/1fXA/NzAAx6k6Wt+d0Om+WSQsLdRzNE0PEMdEHtNIJL1cfTbWTc3d3ZsGED6enpnD17lkuXLmHuL7tqamrihx9+4PTp06Snp5OQkCAycARjiq+vL+vWrWPVqlVcv36dvLw8+XMFQImJaEUD0eoGnDy8MXhFUGbw5Hp9DzVtPQ/cbp/RJDt0rJEkmKF1kgUda5eO1nnsSphsHDfiPSUQjBjxbhEI7AzRVWrqolAo2LZtG3/8r/+VTgcHzAoFP5eWEtrZiYuLy0QPz25xdnbmtdde48CBA1y5cgWwTPq+bmtjsY8Pvo2NoixxhEiSxPz584mMjGT//v2Ul5cDliDZ7777jmvXrrFhwwacnZ0neKT2jUIh4eHrjIevM+Hxg8vNZjPd7XpaajppqeuyPPYLOh0tvQ/cntlkpq2+m7b6biqu2K5z9nCUxRytv8Wd4+HrhJuPBuVA+ccDwolHilarZfPmzaSnp3PmzBmKiopsBJwDBw5w6tQp0tLSWLBgARqN5rH3IRCMFAcHBxISEkhISJBdOIWFhXIpKUB3WxO0NRHl4MDW+Hhi4xJpV7pxu6GT0oYOSustX3dbuh6YX2s2w72Wbu61dHO6pMFmnY+rI1ED7hwrUSfQ4+lydMxGo+37VThuBIIRI4QbgcDesOkqJcpsphrOzs4sr6vnl6BAzAoFHXo9P/74Izt37hR2/glEpVKxbds2vLy85PbtPQYDp1csJyUnhxjhuHkstFotv/rVr8jLy+PYsWNykGxxcTEVFRVs2rSJWbNmTfAoBfcjSRLO7o44uzvaOHTA0uGqVRZzuvq/Ommr735gKDJAV1sfXW19VJW02u5LIeHmrUHr64Q58Fk0mrs4dTfg2WbC0WgaFHUeA29vb5577jmWLFnC6dOn5Zb1AO3t7Rw7doyzZ8+SnJxMamoqbm5uD9maQPD0WLtwrl27Rn5+vo0LR6/XU1BQQEFBAf7+/sTHx/NMejweHpZA8h69kdsNnZQNiDkNHZTVd3C7sZM+w4M/lxo7+mjsaOZiuW1+lYujUhZzovxcCfd2IczbmXAfF1zVj55W3l+iL4Sbp0SUStkVktk82fqI2S8DFnDrCwWBYLSp/5//i6YPPwTA4/ntBP2X/zLBIxI8LpVvvUVBYxOF8+fJy1auXMnSpUsncFSCAa5cucL+/fvl0FOAxOpqtn74oQjZfQKamprYv3+/zWQFIDExkXXr1uHk5DRBIxOMBkajCV1DNy01XTTXdtJa2yW7dPS9T5YNJSkk3LzUePg5o/V1wsPPGQ8/Jzx8nXD3cUKpGpmo09TUxIULFygsLLR5PwMolUqSkpJYvHgx3t7eD9iCQDD61NfXy1k41i4ca8LDw0lISGD27NnDniONJjN3m7sore+wEXVK6zto73kyh6iPq5rwfhFn8NEi7LhpLAKNsaODmwuT5dfEZGeh1GqfaH8jZTrOr+Li4ii/28T81X8/0UOxoeD474kI8Z5Wf+vJxLQVbvLz8zl27Bg5OTnk5ORQVWVJan/SX7elpYXf/e537Nu3j9raWgICAti2bRu/+93v0I7SCWc6nlgEk4+GP/yRxj/8AQCPLVsI+u//bYJHJHhcKt99l46zmZzPSKcqOBiw3Ol+7bXXiIiImODRCQAqKyv56osv6LEqkUpISGDz5s0iJ+MJMJlMZGdnc+LECZsJtJubG1u2bCE6OnoCRycYCyxty3tlQaeltou2+i7a6rtpb+l54jvNkgRu3ho8BgQdXydL+ZWfE+7eTsOGJLe3t3Px4kVyc3Pp7R1a8jVnzhwyMjIIssq1EgjGGr1eP6wLxxqlUklMTAwJCQnMnDnzkZ8/ZrOZhvZeG3fOgKBTp3twueOj8HF1JMzbhTA3Fa57viCos5GgjkaW/vIDWm+PJ97uSJiO8ysh3Ngn01a42bp1K/v37x+y/El+3cbGRhYtWkRpaSmRkZEsXLiQ4uJiiouLiYmJISsrCy8vr6ce83Q8sQgmH40ffEjD//pfALhv2MCMf/79xA5I8Njc/e3f0HHyJH0ODpx48QV0/eKAi4sL77//vrDvTxLuHjnKniOHaXcfjI8ODQ3lpZdeEhktT0hDQwP79u2Tb8YMMH/+fJ555hnUavUEjUwwnhj1Jtoau2lr6Katvos7f/6STqUH3U6+9Dr7PDDT41FIErh6aYaIOW4+Gtx9nDBLBvLz88nKyqKjo2PI6yMiIsjIyCAyMlK46wTjSmNjI0VFRVy5coWWlpZhn6PRaJgzZw4JCQmEhoY+dnm1rkdvEXL6xZzyhk7uNHVR0dRJ70PKrh6Ft4ujXG4V7u0iO3bCvF3wcHr6UqrpOL+Ki4uj4m4T81dNMuHmxO8JF8LNmDFtb/stWrSIhIQEkpOTSU5OJjw8fNi7JCPh7/7u7ygtLeW5557j22+/ldXqf//v/z3/+3//b/7Df/gPfP7556M4eoFg7BDhxFOfgS4Mjno96729+b6xEaPRSGdnJ99//z2vvfYaSuX4t/gU2OLl5sqq4ye4kL6Yen9/wOLE+fjjj9m5c6cor3gCfH19eeutt7hw4QKnTp2SWzgXFBRQVlbG1q1bhevMDlA6KPAKdMEr0BLK7vQf92PS6QAI2fMder8IS9hxQzet9V2ywNPe1PNQUcdshvamHtqberh3Y+jkV+2sws1bwxyvtfQ46ahquEN7TxNGVQ9GZQ/l5eWUl5cTGBhIeno6c+bMEdljgnHBx8eHFStWsHz5cu7du0dRURFXr16lq6tLfk5PT4+ch+Pu7k58fDwJCQn4938+PQp3jQPzQj2ZF2qbX2Uymalr76Gi0SLiVDR1UtE4KOr06B8u6jR19tHU2UdBZeuQdV79ok6Etwtzgtx5e0nkiMYqEExHpq3j5n40Gg29vb2P7bipqakhODgYlUpFZWWlzcmtt7eXkJAQmpubqa6uxs/P76nGOB0VYcHko3nXLur+0VIe5bpyJSF/+uMEj0jwuFT9h/8D3S+/AOD7d39L+YIF/Pzzz/L6JUuWsGrVqokanqCfzuyLVL7xBkaFgoKlS7gdECCvc3Jy4sUXXyQ8PHziBjjFqaurY+/evdTW1tosT0lJYfXq1Tg6jl07W8HkoiQ5BVN7OwARP/6AZs6cYZ9nNJjQyU4di5gzIO48StQZCSZFH0alRcQxKXtQuymYkzSTpJQ4PP1cR5ytIxCMBkajkbKyMq5cucKNGzcwPOBmnb+/PwkJCcydO1cONR4tzGYzdbpeWcwpu13DtV9OUu3iQ7WLD72qkZ+nE0O07P+b9Mcew3ScXwnHjX0ybR03o8Xhw4cxmUwsWbJkiCKtVqvZtGkTn376Kb/88gtvvPHGxAxSIHgcRFepKY91Fwaz3sDChQu5c+cOV69eBSAzM5OQkBBiYmImaogCQFJZXE9Kk4m0GyWEv/IKJ0+eBKC7u5svvviCLVu2kJiYOJHDnLL4+/vzzjvvcPbsWTIzM2X3TU5ODqWlpWzdupXQ0NAJHqVgXLBWXB5SoqRUKfAMcMEzwGXIOqPBRHtTj5VDxyLwtDd1o2vqwfgI1wCAwuSIwuSIg76/PLITSg53U3I4DyRw8XDE3ccSkOzubSm/cut/dNGqUShEeZVg9BjIt4mJiaG3t5cbN25w5coVbt++bXMju66ujmPHjnHs2LFHhho/LpIkEeChIcBDQ1qkN71efdz+3ReWlRoNXmezqGjsd+k0dXGnqZPyRstjV59tIHi4tygxHoJ9+C8E/Qjh5hFcvnwZsNTPD8f8+fP59NNPuXLlyngOSyB4YmxaL4pSqanJfeVukiSxadMmampqaGpqAmDv3r289957oxaeLngCFFblakYDS5cuxcvLi71792I0GjGZTOzdu5fm5maWL18uMjGeAKVSyYoVK4iNjWXv3r00NDQA0NzczKeffsrixYtZsWIFDqLl7PTGevLyhKVJSpUCrb8zWv+hk0Oz2UyXro/2ph50jRYhp73/UdfYTUdz70Nbmls2Ap2tfXS29lFT2jZktUIp4eqlwd1bg6uXBjdPteXRW4ObpwZXLzUqB1ECK3gy1Go1iYmJJCYm0t7eTnFxMVeuXKG6utrmeRUVFVRUVPDzzz8/VqjxSLFuB65wcMDfXYO/u4bUSNvS4YGQ5IqmLlnYmRPkfv/mBAK7Qgg3j2AgpT24v3PL/Qwsv3PnzriNSSB4GiSVrVtDMPWQhnFNqdVqXnjhBf7yl79gMBjo7u7mu+++48033xRdjCYISWk1gTRa7tYPWNG//vprOXvgzJkzNDU1sXnzZlHe84QEBQXx3nvvcfr0ac6fPy/fTb5w4QI3b95k06ZNhIWFTfAoBWOFbRn86AugkiTh4qHGxUNNQOTQUhKTydIBS9fYja6xh/ambhqrdVTfaaC7zYBkdER6xLhMRjO6hm50Dd0PfI6TuyNu/eKOm/fAo8W14+atwcFRCDuCR+Pm5kZaWhppaWkPDDU2Go1cv36d69evy6HG8fHxhIWFPVVuk3W2ovSQaxNJkvBz1+DnriEl4ukbwAgE0wFxNf8IBroGPKgDiIuLxW7b3l9bPRIGai3vp6ysjKioqMccoUDweIhw4qmPtfhm7Zry9/dn48aN7Nu3D4Cqqir27dvHc889JwIyJwIbx82g5TskJIR33nmH3bt309jYCMDVq1epr6/nxRdfFKHFT4hKpWL16tXExsayb98+2X3W2NjIZ599xty5c1mzZs2oZzgIJgE2pVLjv3uFQsLNS4Obl4YZ91WodnZ2kn3hInnZlzF0SSiNGpRGDYr+R0dcMOtHJrh06/ro1vVRX6Ebdr2TmwNu3k5C2BGMmPtDja9cuUJxcfFDQ43nzp1LfHw8AQEBj+0UtXbcPEy4EYwMSVRK2RXiHSMQ2Bm2bg0h3ExFbI+hbQ14UlISlZWVFBQUABZBQKvVsnr16nEdo8DWcXN/ML6npye//vWv+e6777h9+zYA9fX1fPTRR2zevPmBAr/g0YSEhPDee+9x8uRJsrOz5eVXr16lpKSEjIwMFi9eLMqnphOmwfwZaZKJ1C4uLqxas5KMpekUFBSQlZWFTmcbqI1Zga9HELMiE/DxCKCrtY/25l46mntob+6hs7V3RFEW3e16utv1jy3suHqpcfPU4OgkpgX2iiRJhISEEBISwrp16x4YaqzT6bhw4QIXLlzA19eXuLg44uLi8PX1HdF+zH19g/vUaEb99xAIpjPiDP0IXF1dAWyUZ2s6OzsBi+1wpDwoaVtcqAvGBas20WajEG6mIgOhtzC8+Pbss8/S0tJCeXk5AOfOnUOr1bJw4cJxG6MA26wNo3HIaicnJ3bu3MmJEye4cOECYOlW+N1331FWVsa6detE6dQT4ujoyLp164iLi+OXX36hpqYGAL1ez6lTpygoKGDt2rXMmTNHZAtNA8xWwo2N020SoVarWbRoEcnJyRQXF5OVlTXYEU0y0aC7R0PhPVxcXJg/fz6pKxfK7jCj0URna7+Q09RjydiRH0eYscOjhR1HjRJXLw2u/Zk6Azk7rp4aXD3VuHqKnB17YLhQ46KiIsrKymxuQjQ0NHD69GlOnz6Nn5+fLOL4+Pg8cNvm3l75e0ktPt8EgsdBCDePYKAjxb1794ZdP7Bc1M4Lpgo2ZTYi42ZqorRy3AwjvqlUKl588UU+/fRT6uvrAfj555/x8PBg5syZ4zZMu0fxYMfNAEqlkrVr1xIcHMy+ffvo678bWVBQQGVlJc8//zwBVm3EBY/HQFlaYWEhJ06ckG+2tLW18d133xEWFsa6desIDAyc4JEKngorYdQmW2oSolKpSExMJCEhgYqKCrKysrh586a8vrOzk8zMTM6dO0dsbCzJyclERkbi7u2Eu7cTDHMKH8jYae8Xcp5U2OnrMdJc3UlzdecDn+Pk5iALOW7WIo+XZZmzh+iONZ2wDjXu6OiguLiYoqKiIfOi+vp66uvrOXXqFP7+/syZM2dYEcfUMyjcKBzV4/I7TFvM/V+Tick2nmmGEG4ewUCb1oGyg/sZWJ6QkDBuYxIIngYbt8YwLgDB5MemLtww/DHUaDTs3LmTv/zlL3R0dGA2m9mzZw9vvvkmQUFB4zRS+8amZMP08FbCc+bMISAggB9++IGqqirAks3yl7/8hTVr1pCamiqcIU+IQqFg/vz5zJkzh7Nnz5KdnS23Dr9z5w4ffvghCxYsYOXKlXJunWDqYDabbd9fyqnhCJEkiYiICCIiImhoaCA7O5vLly/LZSlms5kbN25w48YNvL29SU5OJikpCc0w5SXWGTvM1A5Z/0hhp7UXk2FkM64B105D5fDZjpJCwsXDURZyBoQdV0+NvEzj6iDOZ1MQV1dXUlNTSU1Npbm5mWvXrlFcXCw7Ggeoq6ujrq5OFnEGnDje3t6Y+6wdN0K4EQgeByHcPIJ169ahUCjIzMykvr4ePz8/eV1vby8HDx5EqVTy7LPPTuAoBYKRIzJupj6PKpUawMPDg507d/LZZ5/R19eHXq/nq6++4u233xZtwseDxxBuALy8vHjrrbc4deoU586dAyydPQ4fPkxZWRlbt24VwsJToNFoWLt2LfPnz+fo0aM2Lof8/HyuXr3K8uXLSU5OFp3YphL3vbcmW8bNSPD19WXTpk2sWrWKS5cukZeXZ9Php6mpicOHD3PixAkSEhJITk5+LCfeo4Qds8lMV3sfHS29dLT00NHcS3v/o+XnHjp1fSO6m242mfu30/vA5yhVCly0jrho1ZYvj/5HrSOuVstUIkx50uLl5UVGRgYZGRk0NTXJIo5c/tfPgIhz8uRJAgICiDSb0bq64tbRIYQbgeAxEVcm/fzhD3/gD3/4A9u2beMf//Ef5eWBgYG8/PLL7N69m9/+9rd888038gXdP/zDP9DQ0MDrr79uI+gIBJMa5dBW0oIphurhpVLWBAYGsmPHDr766ivMZjMdHR3s3r2bt956Cycnp7EeqX1jdUfZPALhBiylU6tXryYiIoK9e/fKnQ1v3brFn//8Z5577jkiIyPHZLj2go+PD6+88gq3bt3iyJEjcmev3t5ejhw5Ql5eHuvWrRNlhVOF+52jU8RxMxzOzs6kp6ezaNEiSktLyc3N5datW/J6vV5Pfn4++fn5hIaGkpyczOzZs59aaLS4ZCxiiX+4+7DPkXN2WixZOwOP7VZiT0/nyK4pjAYTusYedI09D32e2lk1KO5o1bh4WAk7/V9Obo6iNGuC8fb2ZsmSJSxZsoSmpiaKi4spLi6mrq7O5nm1tbXUAmzcgGdzM5EqFW7NzXh5iXbfT4roKmVfTFvh5ueff+Y//+f/LP88kBuQlpYmL/u//q//iw0bNgAWS3pJSckQux/A//pf/4vs7Gx++OEHZs2axcKFCykuLubq1avMnDmTf/mXfxnj30YgGD2s24E/qMxGMLmRlNbH8NGuqZkzZ7Jx40YOHjwIWAIFv/32W1599VXhLBhDHqdU6n6ioqL4zW9+w759++SJW0dHB1988QXp6emsXLkS5RSeoE4GZs6cSWRkJLm5uZw6dYre/tDMpqYmdu/ezcyZM3nmmWceGrQpmHjuF0WnouPmfhQKhRwO29zcTF5eHpcuXaK7u1t+TmVlJZWVlbi4uLBgwQIWLFgwpq3ulUrFYM7OA9D3GQdFnRbLY/t9Io+hd+TXHb1dBnq7DA/N3JEUEs7ujjbCjrNWbePccfFU46hRivKsccDb25ulS5eydOlSGhsbZRFnIG9vgBYvL/KB/H/7NwIDA+VyKk9Pz4kZuEAwBZi2V+wNDQ1cvHhxyHLrZQ0NDSPalo+PDzk5Ofzud79j37597N27F39/f/79v//3/N//9/8tSg4EUwpRKjX1sS2VGtlF8IIFC2htbSUzMxOAiooKDhw4wLZt28TF7FhhLaw8pnADljbCr7zyChcvXuTYsWMY+50F58+fp6Kigu3bt4s7lU+JUqkkLS2N+Ph4Tp06RX5+vhwkfevWLcrKykhNTWXZsmXDZosIJgHTyHEzHF5eXqxdu5YVK1ZQXFxMTk4O1dXV8vrOzk7Onj1LZmYmsbGxpKSkEBERMSHndQdHJZ4BLngGDF/SaTab6e0y0Nnaa3HvtPbS1dZLR2ufvKyztZeu9pGVZYGlNGvgdQ9D5aDA2cMRZ3dHnD3Ulkd3R1wGvu9f5+TuiHKSB1xPFXx8fFi2bBnLli2joaGBa9eucTkzk+b7rj1ramqoqanh+PHjBAUFERcXx5w5c4SIIxDch2R+UKsLwbgz0A78Qe3CBYLRoLu4mIrtzwOg8PAg9mL2BI9I8Lg0f/UVdf+PxVHosnQJoR99NKLXmc1mfvzxR4qKiuRlS5cuZeXKlWMyTntHX1VF6arV8s+zrl974slUTU0N33//PU1NTfIyR0dHNm7cKMLxR5Ha2loOHTrEnTt3bJY7OzuzatUq5s2bh2IaODqmE8b2dm4mp8g/x2RnoZzmN9SqqqrIycnh6tWrsqBrzaPCjCc7JqOJLl2fRdhptTx2tvXaiDudrb309YyNa1jj6tAv6jji7G4l7Fj97OLhiKOTStz4eEzq//Vfub37K+6GhFA9N46Wh/z9ZsyYIXenepqb5NNxfhUXF0dFZSMLl/4fEz0UG/LO/jPhoT7T6m89mZi2jhuBQDA8tu3ARcbNVORxS6Xk10kSW7Zsob29nYqKCgDOnj2LVqtl/vz5ozxKAfdP8E2mJ3YDBAYG8t5773Ho0CEuXboEWEqAf/zxR8rKynj22WdRi6DHpyYgIIA33niDa9eucfToUdra2gDo6uri4MGD5Obmsn79esLCwiZ4pAKZae64GY4ZM2awbds2nnnmGS5dukRubi6tra3y+vvDjFNSUvD395+4AT8mCqWiv+X4w0Wnvh4DXW39wo71lyzy9NHZ1ovJ+Hj3qHs69PR06B9aogWWkGVrt86Ak8fFwxEnt34Hj5sjTm4OOKhFqRaAubcPD50Oj+JiliQmoHj/fbmcaiBvbICqqiqqqqo4duwYM2bMIC4ujoULF+Lo6DhBoxcIJhYh3AgEdsZIOxIJJi+25W6Pd8dRpVLx4osv8sknn8gXSQcPHsTd3Z3o6OhRHafdc79wYzQ+1aTS0dGRLVu2EBUVxcGDB+VMlsuXL3P37l2ef/550ep9FJAkibi4OGJiYrhw4QLnzp1D3y9y19bW8tlnnxEXF8eaNWtEqfQkYDpm3IyUiQozniw4alQ4alRo/Z0f+ByzyUx3h54uXR9dul7LY1v/V//PnW19dOn66Ot+vGsio8FEe3MP7c0PD1kGS6mWU7+Q4+zmYBF03B1x7hd2LAKPRezRuKhQTNNyLXOvVTtwRzV+fn74+fmxfPly6uvrZRHH2l0KFhGnqamJlJSU+zcpENgN0+PMLRAIRozNpH8Yi7Vg8vO04puTkxOvvvoqH3/8MR0dHZjNZvbs2cObb75JYGDgaA7Vrrl/Amk2mxmN+61z585lxowZ/PDDD9y7dw+A5uZmPv74Y1avXk1aWpoo5xkFHBwcWLZsGUlJSRw/ftymxLC4uJiSkhIyMjJYvHixuAM8kdih4+Z+JmOY8WRhILzY2d0RcH3ocw19xn6BxyLsdLb1Dv6s66OrbVD4MZkez8Vj0Jtob+qhvenRIg8SaFwc+oUcK1HnPoFnQPCZSm4ec5+VcGPlEpUkCX9/f/z9/VmxYsWwIs6sWbOmjeg4aojAE7tC/PcLBPaGdZmN0WiZTE6RD3xBP8qRtwN/EFqtlldeeYXPPvsMvV5PX18fX331FW+//bZdXMyPC8OVSo0Snp6evPnmm5w5c4azZ8/2b97E0aNHKSsrY+vWrbi5uY3a/uwZDw8Ptm/fTnJyMocPH5aDYQ0GA6dPn6agoIC1a9cSFxcnzqUTgD07bobDOsz46tWr5ObmPjDMeNasWSQnJ09YmPFkQ+WoxN3HCXefB3fOAouLp6dL3+/asQg6nVaCT1dbL13terrb+ywt0h93cm0eLNdqGdrsdui4HRRySZbG1fLl5OrY/9j/vdvg92pnFdIEtVA3WTtu1MML3veLOHV1dRQXFxMVFTVewxQIJiVCuBEI7AybduBgyUhxcBj+yYJJibVr6mlaugcFBbFjxw6+/vprzGYz7e3t7N69m7feemtKBlpOOsZQuAFLR6SVK1cSERHBjz/+SHt7OwBlZWV88MEHbN26lZkzZ47qPu2Z0NBQ3n77bS5fvszx48fp7LTkX+h0Or7//ntycnJYt26dKFcbb4TjZlgcHByYN28e8+bNGzbM2Gw2c/36da5fv46XlxdJSUkkJiYK4X4ESAoJJ1dHnFwd8Z7x8OeajCa6O/R09ws5li9L6dbAzwMiT7euD4P+8T8nDPqRl2wBSBKoXSxCjsbV4tqxEXlch65zcByd95W5Z1C4UYwgl02SJAICAggICBiV/QsEUxkh3AgEdoZ030Wt2WBAEsLNlGI0c4piYmLYsGEDP/30EwD19fXs2bOHnTt3ohQToKfi/jvYY9XEMSIigt/85jccOHCAGzduAJa76rt372bRokWsWrVK2MtHCYVCwbx585g9ezaZmZlkZ2fLE+HKyko++ugj5s+fz8qVK3F1fXhZhmB0uN9xM0QwFchhxmvXrqWwsHBImHFzczMnT57k5MmTREVFkZSUxKxZs3AQ1wZPjUKpwMVDjYvHo0UKs9mMvtdoI/JYBB6rn9utfu54AjcPYLZy9IwUlaNCdvIMiDoaVwc0Lv1frg5onC2PahcVGpfhA5nvz7gRPB2SKJWyK8SVnEBgZ0j3TeBEQPEUxEpQedJSKWsWLlxIS0sL58+fB+D27dscPHiQLVu2CPv80zBcOPEY4ezszIsvvkheXh5HjhzB0P++zsrKoqKigu3bt+Pj4zNm+7c3NBoNa9asYf78+Rw9epSSkhJ5XUFBAcXFxaSnp5OWlibyb8Ya6/eVQiHOWQ/BxcXFJsw4JyeH0tJSm+eUlZVRVlaGRqNh7ty5zJs3j6CgIPF3HQckSZIDlz18H16uBWAymenp0MuCTk+/s6eno//7/q+ejr7+R/1jd9gawNBnoqO5l47m3kc/uR+FSpLFnAGBR2+ahxSpxUHfSWeTG62FDWhcVKhdBp+jVAnxVSAYDiHcCAT2hhBupjw2Ld2folTKmlWrVtHW1sbVq1cBKCwsRKvVsnz58lHZvl2iuM/dNsqlUvcjSRLJycmEhoby/fff09DQAEBNTQ0ffvghzz77LElJSWICNop4e3vz8ssvU1paypEjR+S/eW9vLydPnuTixYssXbqUBQsWCNfTGGE2Wr2vhEtwRFiHGbe2tnL58mUKCwtpaWmRn9PT00NeXh55eXn4+voyb948EhIShJNsEqGwCl72HsHzzWYzfT1Gi5DTru8Xd/pFnXY93Z16WQgaEH4et9OWNSaDWQ52llHOhFBLCW/ZDeBG0ZDXOWiUVoKPxb2jdnHAO8iFucuCn3g8AsFUR1xFCAR2xv2OG4RwM+UYi5buCoWCrVu3otPpqKysBOD06dO4u7szf/78UdmHvTEk/HGMSqXux9/fn3feeYejR4+Sl5cHWNoC79+/n9LSUp599llcXFzGZSz2QnR0NBEREeTl5XHq1Cl6eixZE52dnRw6dIisrCyWLl1KYmKiKEEcbUyD4rW9BxM/CVqtlmXLlrF06VLu3LlDYWEhxcXF6PWDZTQNDQ0cPXqU48ePEx0dTVJSEjExMUKMnGJIkoTaSYXaSYWH78heYzSY6BkQdO4TdXo69PR06unttDwOPK+v5+luKOl7jOh7jEMye2bEaoVwY42ZcbuuGDGTbDjTDXHGFQjsDFEqNfWxaek+isdPpVLx0ksv8cknn8jtNw8cOIAkScybN2/U9mM3jGOp1P04OjqyceNGoqKi2L9/vywkFBcXU15ezvr165k7d65w34wiSqWS1NRU4uPjOX/+PBcvXpRL1lpbWzlw4ABnz55lyZIlJCYmiknvKCEcN6ODJEmEh4cTHh7O+vXruXbtGpcuXZKFfLB0rrt58yY3b97EycmJuXPnkpSUJEqppjFK1cgzegYwGk30dhpsxJzeLj09HQZqd31FT3sfegcXFHPmYXB06ReADBgND3elalxE5pK90dDQwH//7/+dgwcPUllZiZOTE+Hh4axatYp/+qd/mujhjTviqkEgsDfuDyc2jm35hmAMsD6GoywGODs78+qrr/LJJ5/Q0dEBwP79+zGbzcJ587iMUzjxw5g9ezZBQUH8+OOP3LlzB4Curi5++OEHrl69yoYNG3B3dx/3cU1nnJ2dWbNmDampqZw9e5aCggJM/WVyra2tHDx4UBZwkpKShIDzlJgNg86Q+8P3BU+GWq2WO1I1NTVRWFjI5cuX0el08nO6u7vJzc0lNzcXX19fkpKSSEhIwM3NbQJHLpgMKJUKuYTrfkr/+3H0VVUAhP79p7gsSgUsn4+GPtOg2DMg+Mg/G/CeIcr07In8/HyeeeYZmpqaiIuLY8uWLeh0Oq5du8b//J//Uwg3AoFg+iNJkmXiPzDhH4VwW8H4ItmEE4++i8PT05PXX3+dXbt2yeLNgQMHAIR48zjcfwd6gizEHh4evP766+Tk5HDixAm5BKKkpISKigrWrl3LvHnzUIgyk1HF3d2djRs3kp6eTmZmJoWFhbKA09bWxk8//URmZqYQcJ4WK9eh6JA4+nh7e7Nq1SpWrFjB7du3uXz5MtevX5fdZGC5K37s2DGOHz9OVFQUiYmJoiuVYFhM3d3y9wqnwQBmSZJwUCtxUCtx89JMxNCmJNO1q1RDQwPr1q2ju7ub/fv3s3nzZpv1OTk5EzSyiUVcJQgEdoikVMoT/rGY+AvGGKXVqXuMjp+vry9vvPEGn3/+uY14YzabWbBgwZjsc7oxmQoHFAoFaWlpxMTEcPDgQcrLywFLiO7BgwfJz8/n2WefJThY5AeMNp6enmzevJklS5Y8VMDJyMhg3rx5QsB5TKzLRYdkuAlGDYVCQXR0NNHR0fT09FBcXMzly5dtSqnMZjOlpaWUlpaiVqvlUqrg4GBRSiUAwNTVJX8vOTlP4EgEk5n/9J/+E42Njfzxj38cItoApKSkTMCoJh7xCScQ2CMqFfRZUv5Fxs3UQ1IOOiPGUnjz8fEZIt4cPHgQs9nMwoULx2y/05eJvzXm5eXFa6+9RkFBAUePHqW319Latbq6mo8//ph58+axatUq0TlmDLAWcM6dO8elS5dsBJyff/5ZduAIAWfkmPVCuBlvNBoNCxYsYMGCBTQ1NXH58mUuX75MW1ub/Jze3l7y8/PJz8/Hy8tLLqXSarUTN3DBhGI2mTD3DAYOK1yEcCMYSnd3N19++SUuLi68+eabEz2cSYX4hBMI7BBJoRicQgrHzdTDulRqjFtMD4g3u3btor29HYCffvoJQIg3j2JIqdTECzdgsaQvWLCAmTNncvToUbkFPMClS5e4du0aK1asIDk5WXRAGgM8PT3ZtGmT7MCxFnB0Op0s4GRkZDB//nwh4DwCm5sPDuJvNd54e3uzcuVKli9fLnelunbtmk1XqubmZk6ePMnJkyeJiIiQS6k0GlESY0+YrcqkwLZUSvCETI7LilElLy+P9vZ2MjIycHJy4tChQxw7doyenh5iYmJ44YUXCAoKmuhhTgjiE04gsENsMlIMQriZatgEcI6DY8raeWMt3phMJru1q46ISSrcDODu7s7zzz/PggULOHToEPX19YDlTvnhw4cpKCjg2WefJTw8fGIHOk3RarWygHPu3DmbEGOdTscvv/xi48AReSHDYxNOrBJ/o4lCoVAQERFBREQEzz77LNevX6ewsJCKigqb55WXl1NeXo5SqSQqKoq4uDhiY2OFiGMHmIRwIxgB165dA8DPz4+tW7eyf/9+m/X/8T/+Rz755BNefvnliRjehCKEG4HAHrG+gyvCiacc0jg6bgbw9vYeIt788ssv9PX1kZGRMS5jmHJMcuFmgIiICN577z1yc3M5deqUXD5VX1/P559/zty5c1mzZg0eHh4TPNLpiVarZePGjWRkZMglVMZ+J2R7e7ss4Aw4cISAY4vZytkhwoknB2q1mqSkJJKSkmhpaeHKlSsUFhbS0tIiP8doNMqtxYWIYx/cL9xI4jhPS8rKyoiLixt2XXFx8SNfP3CeOHDgAEqlkj/+8Y/s2LGDrq4u/vCHP/D73/+e119/ndmzZ5OUlDSaQ5/0COFGILBDJmLiLxhFrIU3gwGz2TwuwY8D4s2uXbvktrDHjx+np6eHVatWifDJ+5kiwg2AUqkkLS2NuXPncuLECS5duiSvu3r1KiUlJSxdupRFixaJ0p0xYkDAsXbgWAs4hw4d4ty5c6Snp7NgwQIh4AwgwoknNZ6enixbtoylS5dy9+5dCgsLuX79Ot1Wk3gh4tgHpq7BYy45OSGJToZPjTSJryuelAHnqcFg4L/+1//Kb3/7W3ndP/3TP3Hnzh2+++47/umf/ondu3dP1DAnBPEJJxDYIyrrUinhuJlqDLnYMZlscm/GEm9vb958802++OIL+a7IuXPn6O3tZf369aKltDVTUMhydXVly5YtLFiwgF9++YXq6moA9Hq9LOisX7+emTNnTvBIpy8eHh5s2LBBduDcL+AcPnyYc+fOkZGRIQQcRFepqYIkSYSGhhIaGsqGDRuoqKiguLhYiDh2hLl7sKOUKJOavkRFRY3IWfMgrJsjDBdO/Oabb/Ldd99x5syZJ97HVEV8wgkEdog0Du2kBWOI8r5Tt9E4bsINWO6gvvXWW/z1r3+Vc1Fyc3Pp7e1ly5YtItD2AUylG2PBwcG8/fbbFBYWcvz4cbr6W7g2Nzeze/duYmJiWLduHV5eXhM80unLgIAz4MDJz8+XBZyOjg5ZwElPT2fhwoV2K+CIrlJTjwFBJioqSog4doR1qZQQbgQPIiwsDABnZ2d8fX2HrB/I3Ru4/rQnxCecQGCHiHDiqY11O3CwtAQfb2+Hm5sbb7zxBrt376aqqgqAK1eu0Nvby/PPP2+3k0hrhpaOTSHlBkvY6Pz585k9ezanTp0iNzcXc7/6dPPmTcrKykhPTycjIwNHR8cJHu30xd3dnWeffZaMjAzOnz9PXl6ejYBz5MgRWcCZP3++3U1orcOJRVepqYcQcewHG+HGWbQCHxWmYdrBvHnzAEtb8N7eXtRqtc365uZmwNaZYy8IT7tAYI9Yl0qJcOKpx32OFrNxYj65nZ2dee2114iIiJCXlZSU8NVXX8kBtwIrppLlxgonJyeeffZZ3nvvPflOGFgmUmfPnuWPf/wj165dk0Udwdjg7u7O+vXr+du//VtSU1NtsoY6Ozs5evQo//Iv/8KhQ4fkC1t7wCacWHSVmtIMCDKbN2/m7//+7/nVr37F/PnzcbrPnTEg4uzdu5d/+qd/4quvvuLy5cv09PRM0MgFI8HUOVgqJTkLx41geEJDQ0lMTMRsNg9bDjWwbEDgsSeEcCMQ2CGiVGpqI91fijSB4ptareaVV14hNjZWXlZeXs4XX3whl9fYNdaumykubAQEBPDGG2+wfft23Nzc5OVtbW3s2bOHL774wi6ty+ONtYCTlpZmI+D09fVx8eJF/u3f/o2vv/6aioqK6S+oWWfcCKfftEGIONMPk03GjXDcCB7MP/zDPwDw93//99TU1MjLCwsL+ed//mcA3n///QkZ20QiPKUCgR0iSqWmNvcLN+YJFt8cHBx44YUX2LdvH0VFRQBUVVXx+eef86tf/cpmkm93SNKgYDMNJtCSJBEfH09MTAxnz54lKytL7gBRXl7OBx98QGpqKsuWLRPlC2OMm5sb69atIz09nezsbPLz820mqyUlJZSUlBAQECB3DJuOHcFEOPH0R5RTTQ/MIuNmVJHMk6+rlDRKw3nllVc4evQou3btYs6cOSxevJju7m4uXLhAb28v77zzDjt27BidnU0hxCecQGCPWF/cilKpqcf9k5NJ4JpSKpVs27YNtVpNXl4eYAmO+/TTT3nttdfw9PSc4BFOENPIcWONWq1mzZo1zJs3j8OHD1NaWgpY2nhmZWVRVFTE6tWrSUhIEJ3Gxhg3NzfWrFnDsmXLuHz5MtnZ2TQ1Ncnra2tr2bdvH8ePHyc5OZmFCxfi4uIygSMeXUQ4sX3xpCJOREQEs2bNIiYmBnd39wn8DewXEU4seBw+++wz0tPT+fDDDzl9+jSSJDF//nzee+89Xn/99Yke3oQgPuEEAjvEup30RLs1BI/P/e3AJ8sxVCgUbNiwAY1Gw7lz5wBoaWmRxZvhugMIpjY+Pj7s3LmTkpISDh8+TGtrK2AJzd23bx/5+fk8++yzBAYGTuxA7QBHR0eSk5NZsGABpaWlZGdnc/v2bXl9R0cHp06d4uzZsyQkJJCWloa/v/8Ejnh0sHHciHBiu+JxRJzS0lJZYA4KCmLWrFnExsbi5+c3TJC8YCwwdQ0eE5FxI3gUkiTxzjvv8M4770z0UCYN4hNOILBHVKJUakozJONm8hxDSZJYvXo1Go2G48ePA9De3s5nn33Gq6++SlBQ0ASPcJyxmhBM16wRSZKYNWsWUVFRXLhwgczMTAz9k+m7d+/y4YcfsnDhQlauXImz6CQy5igUCmJiYoiJiaGuro7s7GyuXLkid6IyGo1cunSJS5cuERkZSVpaGtHR0VPWGWUdTjzEjSiwG0Yq4gBUV1dTXV3NyZMn0Wq1sogTGhqK8v7PV8GoYeu4EZ8Fo8L0vKwQPADxCScQ2CG24cSiVGqqISkUNtkpk8VxY01GRgZqtZqff/4ZgK6uLnbt2sWOHTuIjo6e4NGNIzalUhM3jPHAwcGBZcuWkZiYyJEjR7h+/bq8Li8vj+LiYpYuXUpycvK0zFqZjPj7+7NlyxZWrVpFfn4+OTk5dHZ2yutv377N7du38fb2Jjk5maSkpCmXBWLdDlx0lRLAUBHnzp07cubTgCtwgNbWVrKzs8nOzkaj0RATE0NsbCzR0dFD2hALng7bcGLhuBEIHhdx5SQQ2CEinHgaoFJB/53myXoMk5OTUavV7N27F7PZTG9vL7t372b16tUsXrzYLuzpEtZ6zTRXbvrRarW8+OKLlJWVcejQIRobGwHo7u7myJEjXLx4keXLlxMfHy/ubo8Trq6uLFu2jPT0dK5evUp2dja1tbXy+qamJg4fPszJkydJTEwkJSVl6pQ2inBiwUNQKpVERkYSGRnJunXrqKurk0Wc6upqm+f29PRw5coVrly5YpOLExsba98h+6OE2apUSiFKpQSCx0Z8wgkE9oi1cGOanJN+wcORFIpBGcBsmsihPJSEhATUajXfffcdBoMBs9nMsWPHqKmpYfPmzTg6Ok70EMcUW6lm+gtV1kRFRfH++++Tk5PD6dOn6evrAyx3uPft28fZs2dZunSpEHDGEZVKRVJSEomJidy5c4esrCxKSkrk9X19feTm5pKbm0tERASpqanExMRM6jIqU2+v/L2kEQ4JwYORJImAgAACAgJYtmwZOp1OFnHKy8vlckKwzcX56aefmDFjBrGxscyaNQtfX1+7uPEw2hg72uXvFa5CCBsVpmkJtmB4hHAjENghNu2kjZN30i94CFMoYDo2NpZf//rXfPPNN7S1tQFw9epVGhsbefHFF6d3xynriyo7vM5XqVQsXryYhIQEzpw5Q35+vtw+vLm5WRZwli1bxty5c4WAM05IkkR4eDjh4eE0NzeTl5dHQUGBTTvx8vJyysvL8fDwIDk5mfnz50/KjCJzb5/8vUKUtggeA3d3d5KTk0lOTqa3t5fS0lJu3LjBrVu3bN4LAFVVVVRVVXHy5Ek8PT1lJ05ISIg4b40Qk25QuFG6uU7gSASCqYkQbgQCe8TacSMybqYkto6byX/HJTAwkHfffZfvv/+e8vJywNKm+KOPPmLHjh1ERkZO8AjHHnu+Q+vq6sqGDRtIS0vj7NmzXLlyRQ5rbm5uZu/evTYOnMns8JhueHl5sXbtWpYvX05RURE5OTnU1dXJ69va2jh+/DinT59m7ty5pKamTqouYWZrx42jEG4ET4ZarSYuLo64uDiMRqOci3Pjxg35hsMALS0tZGVlkZWVhZOTEzExMXJA+3R3kT4NNo4bUXomEDw2QrgRCOwQm3bSwnEzNbE5hpPbcTOAi4sLr776KseOHSM7Oxuw5J789a9/Ze3ataSlpU0/cWMKiGrjibe3N9u2bWPp0qVDBJympiZZwBlw4AgBZ/xwdHRkwYIFzJ8/n8rKSnJycrh27Zp8fAwGA4WFhRQWFhISEkJKSgqzZ8+e8KBpU5+VcCMcN4JRYLhcnBs3blBSUkJNTY3Nc7u7u7l8+TKXL19GpVIRGRlJbGwssbGxuLoKV4k1pvYO+XuF+NuMCpK4xLArhHAjENgjKpFxM9WxFt/Mpqnzya1UKlm3bh2BgYEcPHhQzr05cuQINTU1bNq0CQeHadQZxqZUapqJUk/BgICzZMkSzp49S1FRkY2A8+OPP3LmzBkh4EwAkiQRFhZGWFgYOp2OvLw88vPzbbpR3b17l7t37+Lk5ER8fDxJSUkEBgZOiPBqXSolqYXbQTC6WOfiLF++nLa2NtmJU1FRIZd+gkXcvHnzJjdv3uTgwYMEBAQQHR1NVFQUISEhEy5yTjSmdutSKeG4EQgeF/s+gwgEdoqksM64EcLNlMR6IjsFxbfExER8fX355ptv0Ol0AFy5coWGhgZefPFFtFrtxA5wtBDCzUPx8fHhueeekx04wwk4Aw6cuLg4IeCMM+7u7qxcuZKlS5dy7do1cnJyuHfvnry+u7ubnJwccnJy8PPzIykpifj4+HHtwGNdKiUybgRjjYeHBykpKaSkpNDT08OtW7coKSnh1q1b9Fr9L4KlHLi2tpZz587h4OBAREQEUVFRREdH4+XlNf0cpg/BbDRi6rJqBy6Em9FBuHrtCiHcCAT2iHLqBNsKHoCNcDM1y92CgoJ49913+e6777hz5w4ANTU1fPTRR7zwwguEh4dP7ABHAyHcjIgBAcfagTNAY2MjP/zwg+zAEQLO+KNSqUhISCAhIYGqqipycnIoLi7GYNWKu76+nqNHj3Ls2DFmzpxJUlISMTExY+4yEBk3golCo9EQHx9PfHw8BoPBJhdn4IbEAHq9XnbjAGi1WtmNExERgUajmYhfYdwwdXTY/KwUpVICwWMjhBuBwA6RlFZvfZFxMyWxLZWausfQ1dWV1157jSNHjpCTkwNAV1cXX3zxBc888wwpKSnT567kdPk9xhBfX1+2b99u48AZYEDAGXDgzJkzRwg4E8CMGTPYtm0b69ev59q1axQWFlJZWSmvN5vN8gR1PEqpTH2iVEow8ahUKqKiooiKimL9+vU0NDRQVlZGaWkpd+7csRE5AVpbW8nLyyMvLw9JkggJCZHdOIGBgdPu3GZstxVuRMaNQPD4COFG8P9v777D26zP/fG/H03LUx6SZzzjEdtxdkJC0ixI2KvQUnrKaClQ2n7h9LQ9paXjFCgtXdAD/Fo6gEMLtNBeUAKEhCwy7WwncRzvvfeSZY3n94fRk+exZcd2bEuy3q/r8oW2P0Kx/eit+3Pf5I9YceP75kDFjYtarcZ1112H2NhYbNu2DQ6HA06nEx9++CEaGxtx/fXXz5G+NwxuJkoe4Ozbtw9nz56VrmttbcXbb78Nk8nEAMeDAgICsHTpUixduhTt7e04ffo0Tp06pag0kG+lMplMWLx4MfLy8qZ1KxW3SpG3EQQBZrMZZrMZq1evhs1mQ3V1NcrLy1FeXo6WlhbF7UVRRE1NDWpqarBnzx4YDAakpqZKFTmhoaEeeibTxymbKCUEBkLw834/00IEBG87/OPOrRnFnxoiP6ToceOD/VEIyvDNx4MblyVLlsBkMuHvf/87ej9tYnjq1Cm0trbic5/7HMLCwjy8wskRuff8splMJtx+++1SBc5YAc6GDRuwYMECBjgeEhkZiU2bNmHDhg2oqqrCqVOnUFRUpKgyaG1txc6dO/Hxxx9j/vz5WLx4MTIzMy97K5ViqxSDG/JCWq0W8+fPx/z58wEAPT09UjVORUUFLBaL4vYWiwXnzp3DuXPnAABms1mqxklMTPTJDzIUjYlZbUM0JQxuiPyQIJ8qxa1SPkkQ5k7FjVxCQoLU98a1/aK+vl7qe5OUlOThFU7CiOCGO6Wmzmw2SwHOvn37pDc0wHAg8NZbb8FsNmP9+vUMcDxIpVJJY5Svu+66MbdSlZaWorS0VOoRsnjxYsTFxU1pK5WTwQ35mNDQUCxZsgRLliyB0+lEY2MjysrKUF5ejtra2lGhf0tLC1paWnD48GFoNBokJSVJ1Tgmk8knthPLt0qxMTHR1DC4IfJHiqlS9rFvR95LLa+amjvBDQCEhITg7rvvxvbt23Hs2DEAQH9/P1599VVcddVVuOKKK3zjjfnIihsfOLj2dmazGXfccYdUgSMPcFpaWqQAZ8OGDcjKyvKNfydz1ES2Ug0ODuLo0aM4evTolLdScasU+TKVSoX4+HjEx8dj/fr1GBwcRGVlpVSR09XVpbi93W6XtlwBwyGQq7dOSkoKgoKCPPAsLk2+VYqjwKeL6IVTpbxtPXMLgxsiPyQoetzMrTf9/kL+CdtcfA01Gg1uuOEGxMbG4oMPPpD63uzYsQMVFRW45ZZbEOzt5dYMbmZMdHS0FODs27cPRUVF0nUtLS34xz/+gejoaKxfv54BjheYya1U3CpFc0lAQAAWLFiABQsWQBRFdHR0SNU4lZWVsNlsitv39PTg5MmTOHnyJIDhcDspKQnJyclISkrymr+TDtlWKVbcEE0NgxsifySfKsUeN75JXnEjzr3gxmXZsmUwm834xz/+IfW9KSsrw+9//3vceuutSEtL8/AKx8HgZsZFR0fjc5/7HJqbm0cFOM3NzVKA85nPfIZbqLzAdG+lEkURomKqFIMbmjsEQUBkZCQiIyOxatUq2O121NbWStU4TU1No+7j2lZ19OhRAEBUVJQU4iQnJ09rY/DJcMq2SqlDvCNMIvI1DG6I/JCi4sbO4MYnqeQVN3P7NZw3bx4eeughvPvuuygpKQEA9PX14bXXXsPatWuxceNGqOVBlrdgcDNrXAFOU1MT9u3bh/Pnz0vXNTc346233oLRaMSqVauwZMkSBAQEeHC1BExtK9WiRYuQm5sLo9EIAIrQBgAEHceB09yl0WiQkpKClJQUXHXVVejr60NFRYXU5Livr2/Ufdra2tDW1iZtO46IiFAEObPV9F++VUoVzIqbacOdSX6FwQ2RP5L1uBFZceOTFJPBvG6P8/QLCgrCF77wBRQUFGDHjh1wfBpWHThwAJWVlbj99tsRHh7u4VVeCoObmRYTE4PPf/7zaGpqwt69e1FcXCxd19XVhY8++gh79uzB0qVLsWrVKh/4N+MfJrqV6uOPP8bHH3+MhIQE5ObmIisxUfE47HFD/iQ4OBh5eXnIy8uDKIpob29HdXU1qqqqUFVVJVWpynV0dKCjowMnTpwAAISHhyu2Vs3U70Rlc2JW3BBNBYMbIj8kyKsT5mB/FL+gkvcp8o/wTRAErFq1CklJSXjrrbfQ3t4OYHjq1O9//3vceOONyM3N9fAqL5r7cZr3iomJwZ133onGxkYcOHAARUVF0qSWoaEhHDlyBPn5+cjKysLq1asxb948n5jMMtdNZCsVANTV1aGurg7bAZg2bURiTQ0Sauu4VYr8liAIiIqKQlRUFJYtWwZRFNHZ2YmqqiopzOnu7h51v87OTnR2duLUqVMAgLCwMCnISU5ORnh4+LT8blSMA2ePG6IpYXBD5I8UzYk5VcoXCfJeHU7/ighiYmLw4IMP4sMPP5QaMlqtVrz99tsoKSnBNddcg8DAQA+vEm62SnlmGf4sNjYWd9xxB7q6ulBQUIDjx4/D+mkzW1EUcf78eZw/fx5xcXFYuXIlcnJyoNVqPbxqAkZvpSosLMTZs2elwNal1WxGq9mME0uX4szf/46c3FwsWLDAO34HEHmIIAiIiIhAREQEli5dCmA4pHGFONXV1ejs7Bx1v+7ubhQWFqKwsBDA8NSq5ORkpKSkSEHOVDi4VWpGCH5QcU0XMbgh8kOsuJkDFMGNf1TcyOl0Otx8881ITU3Fe++9h6FPe10UFhaivLwc1113HbKzsz1bRTHigIoVHZ5jNBqxZcsWrF+/HqdOnUJ+fj46Ojqk6xsaGvDOO+9gx44dWLZsGZYvXz5rvR/o0iIjI7Fx40Zs2LABTU1NOHfuHM6ePasYlSyqVKiorERFZSXef/99pKamIicnB1lZWTAYDJ5bPJGXCA8PR3h4OBYvXgxgOKSRb62S/0506enpUQQ5RqNREeRM9Peks0deccOtUkRTweCGyB+xx43vk4cAfvyJy8KFCxEfH49//vOfqK+vBwD09/fjrbfeQlZWFq6//nqPTdHAyC1s3thA2c/o9XqsWrUKK1asQElJCY4cOYKqqirp+oGBAezfvx8HDhxAVlaWtDWPoZt3EAQBsbGxiI2NxebNm1HxyX7k/3//H2oT58Eiq7BxOp0oKytDWVkZ3nvvPcyfPx85OTnIzMxkY2qiT4WFhUk9coDhkKa6uloKc9ra2kbdp6urC6dOnZK2VhmNRiQmJiIpKQmJiYmIiopy+/vSIQtZ1ewtRjQlDG6I/JB8qpS/bbOZM2QHRqIfBzfA8JSMr3zlKzhy5Ah2794tNTQtLi5GZWUltm7diiVLlsz6m2/RqaxmEziK2muoVCpkZWUhKysLTU1NKCgoQGFhofRvR76Nymw2Y+XKlcjLy4OOU4u8hiAIiAkIwJJTp7D41Cl0ZmWi+4EHUFRUpJiu43Q6UVJSgpKSEqjVaqSnpyMnJwcZGRnQsycOkSQ0NBQLFy7EwoULAQxPb6yqqkJlZSWqqqpGbVMEhoOcrq4uqSInMDBQCnGSkpIQHR0NtVoNu2xbFoObaeTnx3/+hsENkT8S/HubzZwgzyD4dxsqlQpr1qxBZmYm3nvvPamKwmq14t///jfOnj2LG2+8cXanCLHixifExMTgpptuwlVXXYWTJ0/i6NGjii04LS0t2LZtGz7++GMsWbIEK1asQEREhOcWTBLnQD+A4V+HMXY7rrzuOlxzzTWoqanB2bNnUVRUhIGBAen2DocDxcXFKC4uhkajQUZGBnJycpCens5QjmiE4OBg5ObmSk3/e3p6FEGOux45AwMDUugNDG9rnpeQAEN8PEw6HSI6OhjcEE0RgxsiPyQomhOzx40vEsCtUu5ERkbi7rvvxsmTJ7Fjxw6pEW1FRQVefPFFbN68GStXroRqFqpfWHHjWwIDA3HllVdi9erVKC0tRX5+PioqKqTrBwcHcfjwYRw+fBgZGRlYuXIlUlNTZ+XfErnnlIUyqsCg4f+qVNJEnGuvvRZVVVU4d+4czp8/D4vFIt3ebrejqKgIRUVF0Gq1yMzMRE5ODubPn88G1URuhIaGKrZWdXd3o6amBtXV1aipqUFLS8uo+wwNDaG8ogLIG67iUTkciPvgAySlpCApKQnz5s1jDyqiCWJwQ+SPZD1u4GRw45MEltyMRaVSYdmyZUhPT8e2bdtQUlICALDZbNi+fTvOnj2Lm266CWazeWYXwoobn6RSqZCZmYnMzEy0traioKAAp0+flhpgA5C23kRGRmLFihVYvHgxe6d4gCK4cfPmT61WIy0tDWlpabj++utRUVEhhTiuUBcY/t1w9uxZnD17Fnq9Xgpx0tLSoNHwUJnInbCwMMXWqoGBAdTW1kpBTkNDA5wjjjGdajXqGhpQ19CAgwcPAgCio6MV26s81pfO14gAvO0QnoejM4p/jYj8kUrWH4VbpXwTmxNfUmhoKL7whS/g7Nmz+PDDD6UtE3V1dfjDH/6Az3zmM7jyyitn7I0ZK258n8lkwvXXX4/Nmzfj9OnTKCgoUPR5aG9vx/bt27F7924sWrQIK1euhMlk8uCK/Ysoq6BRXWL8t6u/TXp6Om644QaUl5fj3LlzKC4uVoRyVqtVmqITEBCA+fPnIyMjA/Pnz+eIcaJxBAYGSqE3MFxtU19fj7LDh1H2ySdoi4qCw83f2+bmZjQ3N6OgoADA8PQreZATERHBBvFEYHBD5Jc4DnwOYHAzIYIgYOHChUhNTcX27dtx5swZAMO9Lvbs2YOioiLcdNNNiI+Pn/5v/mmjWwk/ufdZAQEB0jSqiooKFBQUSJVcwPAblKNHj+Lo0aNITU3FypUrkZ6eDjWrrGaUcqvUxEMVjUYjvcG02WwoKyvDuXPncOHCBdhsNul2g4ODUiWOIAhISEhAeno6MjIyEB0dzTeTROPQ6XRISUlBZGkpEvbug1MQ0L9kMezf+IZUlSPfvujS2dmJzs5OaXJVcHCwFOKsWLGC21PJb/Eoksgfyf7oseLGR6k4VWoygoKC8NnPfha5ubnYtm0bent7AQx/0venP/0Jq1evxsaNG6e1twUrbuYelUqF+fPnY/78+ejo6MDRo0dx8uRJDA4OSrepqKhARUUFAgMDkZubi4ULFyIhIYFv8meAs39qwY2cVqvFggULsGDBAgwNDaG0tBTnzp1DSUmJNGUMGP49W1tbi9raWuzevRshISFSiJOSksIJVURjcHQMNzFWiSKi9XokrVmDNWvWwOl0oq2tTdEnp7u7e9T9+/r6UFRUhPr6eqxatWq2l+/VBB7/+RUGN0R+SPEGkuPAfZKiOTFfwwnLzMxEUlISdu7ciePHjwMYfkN26NAhFBcX46abbkJycvL0fDN5jxtWXsw5ERER2Lp1KzZu3IjCwkIUFBQomnMODAygoKAABQUFMBqNWLhwIfLy8riVahpNteJmLDqdDjk5OcjJyYHVakV5eTlKS0tRWlqqGDEOAL29vThx4gROnDgBtVqN5ORkKcjh1DGiixxdF6dPacIv/myoVCqYzWaYzWYsX74cwPB4cVeIU11djba2Nun2SUlJs7doIi/E4IbIH8mbE49soEq+gVulpiwgIAA33ngjcnNz8e9//1saadrR0YFXXnkFy5cvx1VXXXXZzWblFTestpm7dDodli9fjmXLlqG6uhoFBQW4cOECHLLfrV1dXdi/fz/279+PmJgYLFy4ELm5uQgLC/Pgyn2fIrgJmt7+M3q9HtnZ2cjOzobT6URTUxNKS0tRUlKC+vp6xW0dDgfKy8tRXl6O7du3IzIyUgpxEhMT2eCY/JpDNjb8UqPAjUYjjEYjFi1aBADo7+9HTU0NampqGNyQ3+NfEiI/pBgHzqlSvolTpS5bSkoKvva1r2Hv3r04fPiwtOXs2LFjKCkpwQ033ICMjIypfwNW3PgVQRCkMdQWiwVFRUU4c+YMqqqqFLdrampCU1MTdu7ciaSkJOTl5WHBggVsfDsFzkk0J74cKpUKcXFxiIuLw/r169HX14eysjKUlpairKxMMaEKGG5a3d7ejiNHjkCn0yEtLU1qjMyJOeRv7JMIbkYKCgqStjKSG/zgzq8wuCHyRxwH7vtYcTMtdDodtmzZgpycHLz77rvSVpeenh68/vrryMnJwdVXXw2j0Tjpx2bFjf8yGAxYtmwZli1bhu7ubpw9exZnzpxBU1OT4nbV1dWorq7G+++/j/T0dCxcuBCZmZnT2mtpLnMO9EunhVkMvoKDg7F48WIsXrwYDocDtbW1UjVOa2ur4rZDQ0M4f/48zp8/DwCIjY2VqnHi4uLYaJXmPEdnl3RaHW702DqIfB2DGyJ/pBgHzuDGJwlsTjyd4uPj8cADD+DAgQP45JNP4Pz058I1Lnj16tVYt27d5BqQsuKGAISFheHKK6/ElVdeidbWVpw5cwZnzpyRtugBgNPpxIULF3DhwgXodDosWLAACxcuREpKCidTjUOxVcrgmYolV3+b5ORkXH311ejs7JT64lRWVioaHANAY2MjGhsb8cknnyAwMFCqxElLS4PBYPDIcyCaSY6ODum0ZpIVN0R0EYMbIj+kHAfOHjc+SbFTisHNdNBoNNiwYQOys7Px7rvvSn0sHA4HDhw4gJMnT2LTpk1YsmTJhD4lFx2suCElk8mETZs2YePGjaivr0dhYSHOnTuH/v6LlSNDQ0M4ffo0Tp8+jaCgIGkyVXx8PCdTjTDdzYmnQ3h4OFauXImVK1fCZrOhsrJSqsYZOTFnYGBAeq0FQUBiYiLS09ORkpKC2NhYVuPQnKDoccPG3dOLx39+hcENkT+SjwMXWXHjixRv4Ph3e1qZzWZ85StfwenTp7Fr1y5pmkx/fz/ee+895OfnY+vWrUhLSxv/gZysuCH3BEFAQkICEhISsHXrVlRWVuLMmTM4f/48hoaGpNv19/cjPz8f+fn5CA8Px8KFC7Fw4UJOpvqUOA3jwGeSVqtFRkYGMjIycN1116G1tRUlJSUoLS1FTU2NolpSFEVp6xww3EQ9OTkZqampSElJQVRUFIM78kn2ri7p9GR73BDRRQxuiPyQ4tN/B4Mb38QeNzNJpVJhyZIlyM7OxqFDh3Dw4EFpy0NLSwtee+01pKenY8uWLWO+iZZX3EDNT87JPbVajfnz52P+/Pm4/vrrUVJSgjNnzqC0tFTasgcAnZ2d+OSTT/DJJ58gNjZWmkwVGhrqwdV7lqI58TRPlZpugiBIo4/Xrl0Li8WiGDc+IKseAoDBwUEUFxejuLgYABASEoKUlBQpyOFEMvIFzsFBiLJ/22ojgxuiqWJwQ+SPFM2JuVXKJ3Gq1KzQ6/XYuHEjli5dil27dqGwsFC6zjVRZsWKFVi/fj2CgoKUd5b9bAkqVtzQpel0OuTm5iI3NxcDAwM4f/48CgsLpSoMF1eflB07diA5OVmaTOVvPVK8cavURBkMBum1djqdaGhoQGlpKSoqKlBXVzeqd1lvby8KCwul30GRkZFSkJOcnMypZOSVHLJqG4DNiacdP3v1KwxuiPyQchw43/T7JE6VmlVhYWG47bbbsGrVKnz00UeoqakBMLy9oaCgAKdPn8aaNWtwxRVXSA2MWXFDlyMwMHBCk6mqqqpQVVWFbdu2IS0tDdnZ2cjMzJzzb+RFUfTp4EZOpVJJW+c2btwIq9WK6upqVFRUoLKyEs3NzaPu4xo5fuzYMQBAXFwcUlNTkZaWhnnz5kGj4SE+eZ68v40qKAgqnc6DqyHybfytTuSPFFulWHHjkzhVyiPi4+Nx33334fz589i5c6c0GchqtWLPnj3Iz8/HunXrsHz5csBxcZoMK27ocsgnU7W0tEiTqbpkn2Y7nU5p241KpUJKSgqys7ORlZU1uhpsDhAHBwHZVjJfDm5G0uv1Um8cAOjr60NVVRUqKipQUVGheN1dGhoa0NDQgAMHDkCr1SIpKQmpqalITU1FdHQ0++OQR9jb2qXTbExMdHkY3BD5IzYn9n2ysIYH5LNLEARkZ2cjIyMDBQUF+OSTTzA4OAhgeErMRx99hMOHD+OK2FiECQJUogiBnzLSNDGbzdi8eTM2bdqEuro6nDlzBmfPnlX0SHE6nSgvL0d5eTm2bdumCHGCg4M9uPrp4+jpUZxXzeFeP8HBwdK2KmC435GrGqeyslIxlQwAbDYbysrKUFZWBgAICgqSqnFSU1P9ui8SzS57y8VqMY3Z7MGVzEGiCMHbPrjztvXMMQxuiPyQojkxt0r5JvkfRwY3HqHRaLBmzRosWbIEhw4dwpEjR2Cz2QAAPT092NHTg+Brr8XCs2cwX6v18GpprhEEAfPmzcO8efOwdetW1NTU4Ny5czh//rzijbwoilKlxvvvv4+kpCRkZ2djwYIFCAkJ8eAzuDwO2WhtISDAr7ZghIeHS9vonE4nWlpaUF5ejoqKClRXV0uN1F36+/ulKi1geCy9K8hJSkqStncSTTebbJufNprBDdHlYHBD5I8EeXDDihufpPhUg8GNJxkMBmzevBmrVq3C/v37cezYMTg+3YLYFxqCw2vWoHhwENdcuICMjAxWSNG0U6vVSElJQUpKCq677jrU1NSgqKgIRUVF0jh7YDjEcfXE+eCDDxQhjq9VYThlwY3ax9Y+nVQqFWJiYhATE4Mrr7wSNpsNtbW1qKioQHl5ORobG0fdp7W1Fa2trcjPz4dKpUJcXBySkpKQlJSExMREBAQEeOCZ0Fxkb26RTmuiYzy4EiLfx+CGyB+p5P1RGNz4JlbceJvg4GBce+21WL16Nfbt24dTJ09Kr1JnQADeeOMNJCQkYPPmzUhJSfHoWmnuUqlUSE5ORnJyMq655hrU1dXh3LlzKCoqQm9vr+K21dXVqK6uxocffoh58+YhJycHCxYs8IlR0/KtUuow/w1uRtJqtVJvm6uuugoDAwOorKyUKnJG9sdxOp2oq6tDXV0dDh48CACIiYmRQpykpKQ5s72OZp9d1kxdw4qb6cetSX6FwQ2RH+JWKd+naEjM3MarGI1G3HzzzVjY14c9u3ahNjFRuq6urg6vvvoqUlNTsXnzZsTHx3twpTTXqVQqJCYmIjExEVu3bkV9fb1UidMtq1gBgNraWtTW1mL79u1ISEhAdnY2srOzYTQaPbP4S3B0XwxuVKHeHzR5SmBgIHJycpCTkwNRFNHR0SFV41RWVsJqtY66T1NTE5qampCfnw9gePS4qyInKSnJa/9NkPextVysuNFGR3twJUS+j8ENkT9ScauUz1PslGJy443CVSqsOXQYnUXnUbR+PeoMF7cfuHqOZGVlYdOmTTCzaSPNMJVKJfXE2bJliyLEGVmF4arA2LFjB+Li4pCTk4Ps7GyEh4d7ZvFuOHq4VWqyBEFAZGQkIiMjsWLFCjgcDjQ1NaG6uho1NTWorq6GxWIZdT/X6PETJ04AGJ5yJq/IiYqK4hZQcssu63GjYXBDdFkY3BD5I4FbpXwep0p5PfHTRsXhXV3Y2tMD58Nfw65du1BTUyPdpri4GMXFxcjLy8OGDRsQwXGpNAsEQUBCQgISEhJw9dVXo7GxEUVFRTh37pw04t7FNWZ6586diI2NlSpxIiMjPbT6YU7FVilW3EyFWq1GfHw84uPjsWbNGjidTrS1tUlb6Kqrq0dtrwOA7u5uFBYWorCwEMBwVY+8Iic6Ohoq+QdE5JecQ0NwdHRI51lxMwO4VcqvMLgh8kPcKjUHcKqU13MFNwAg6HRISkrCfffdh/LycuzatUvRNLSwsBBnz57F0qVLsXr1ao+/KSb/IQgC4uLiEBcXh82bN6OpqUmqxGlvb1fctrGxEY2Njdi1axeio6ORnp6O1NRUJCYmQqOZ3UNK+VYp9riZHiqVCmazGWazGStWrIAoiujs7JSqcaqrq9EheyPuMjAwgPPnz+P8+fMAAL1eL23RS0pKQlxc3Kz/+yDPs8u2SQGAxmTy0EqI5gb+FiXyR9wq5fs4VcrriUND0mnh03HggiBg/vz5SEtLw/nz57F79260tbUBGG4SeuzYMRw7dgzp6elYtWoV0tLSWFFFs0YQBMTGxiI2NhabNm1CS0uLVInj+nfq0tzcjObmZhw4cAAajQZJSUlSU9zZqLiQNydWcavUjBAEAREREYiIiMDixYsBAL29vVKIU1NTg2bZVhgXq9WK0tJSlJaWAgA0Gg0SEhKkipyEhATo/Gh8u7+Sb5NSR0ZC4GtOdFkY3BD5I44D932suPF6ioqbT4Mb6bwgIDs7G1lZWSgsLMSePXsUzWJdb3qioqKwcuVKLFq0CHq9ftbWTiQIAqKjoxEdHY2NGzdKIU5RURFaRnySbrfbUV5ejvLycgDDW2dcIU5aWtqMTKlS9rjhVqnZEhISgtzcXOTm5gIYrrapra2VwpzGxkY4RxxX2O12aQw9MPxvy2QyIS4uDvHx8YiLi0N0dDSrcuYYZX8b9nGbEdwq5Vfm/G9Ii8WCp59+Gm+++SZqamoQERGBa665Bk888cSkpnkkJyejurp6zOvPnz+PrKys6Vgy0YwTFOPA+UvfF4kcB+71xgtuXFQqFRYvXozc3FycOnUKR44cUVQ2tLW14YMPPsCuXbuwdOlSrFixgn1wyCNcW2g2bNiA1tZWlJaWoqKiAtXV1bDJ/q0Dw2/mz549i7NnzwIYnkrkCnJSUlIQEBDg7ltMipNbpbxCYGAgMjMzkZmZCQAYGhpCXV2dFOTU1dXBbrcr7iOKIlpaWtDS0oJTp04BGP5dGB0dLQU5cXFxMJlMUKvVs/2UaJrYmi4GN9roGA+uhGhumNPBzeDgIDZt2oQjR44gNjYWN998M6qqqvDyyy9j27ZtOHLkCFJTUyf1mPfcc4/by2fi0ySiGcOtUnMLcxuvJA4pe9yMR6PRYPny5Vi2bBkqKiqQn5+PkpIS6Xqr1YrDhw/j8OHDyMzMxKpVq5CSksJtVOQRJpMJJpMJa9asgd1uR21trTQpraGhYdQHAq6pREePHoUgCIiPj5eqceLj46dUacGtUt5Jp9NJIR0wXG3T0NAgba2qqalxO4Lc6XRKPZRcNBoNYmNjpSAnLi4OkZGRbHzsI1hxQzS95nRw8+STT+LIkSNYvXo1duzYgeDgYADAb37zG/zXf/0XvvzlL2Pv3r2TesxXXnll+hdKNNu4Vcr3sVDK64m20T1uLkUQBKSlpSEtLQ3t7e0oKCjAyZMnMSTrl3PhwgVcuHABJpMJq1atQl5eHvtFkMdoNBqkpKQgJSUFmzdvhsViQWVlpRTkjGxmK4qiNG78k08+gVarRXJyshTkmEymCQWSjm5ulfIFGo1GalQMDAc07e3tqK+vlyaWNTY2wuFwjLqvKxSsra2VLtPr9VKY46rOMRqNDLG9kK1FXnHDiVIzgofwfmXOBjdDQ0N4/vnnAQAvvPCCFNoAwLe+9S28+uqr2LdvH44fP45ly5Z5aplEHsGtUnMAx4F7vYlslRpPZGQkrr32WmzatAmnTp1CQUGBYspPa2srtm3bho8//ljaRhUeHj4tayeaKoPBII0MB4DOzk4pxKmoqIDFYlHc3mazKRrZBgcHSyFOSkoKQt1U04iiqKi44VYp36FSqaSKLVfDY4fDgZaWFinIqa+vR0tLy6heOcBw9aG8Xw4w/G9OHuTExcW5/XdDs8su2yqlMTO4Ibpccza4OXjwILq7u5GWloYlS5aMuv72229HYWEh3nvvPQY35H+4Vcr3sTmx11NslZpCcOOi1+uxatUqrFixAuXl5cjPz0dZWZl0/eDgIA4dOqTYRpWcnMxAj7xCeHg4li1bhmXLlsHpdKKpqUkKcaqrq0dVWvT19aGwsBCFhYUAhrdlpaWlITU1FUlJSdDr9RAtFkAWjKr5Jt2nqdVqaZqZ65jcZrOhublZUZnT2trq9v4Wi0XRHBsYDgDlQU5sbKziQ1yaeYqtUjEMbogu15wNbk6fPg0AWLp0qdvrXZe7Dgwm6pe//CXKy8uh1+uRk5ODW2+9FSaT6fIWSzTbuFXK9zG48XqXW3EzkkqlQnp6OtLT09HW1oaCggKcOnVK2kYliiKKi4tRXFwMs9mMVatWYeHChdxGRV5DpVJJb6TXrl0Lm82GmpoaVFRUoLy8HE1NTaPu09raitbWVhw5ckQaVz7PZII2Lg5RbW3QDw1BxT6Dc45Wq0VCQgISEhKky6xWKxobGxWVOZ2dnW7v39fXJ20rdQkODkZMTAxiYmIQGxuLmJgYhIeHs2fODBCdTthkQRu3Sk0/QQQEL6uaF7xrOXPOnA1uampqAEDxC1/Odfl4k6Lc+e53v6s4/5//+Z/43//9X3z5y1+ewiqJPINbpeYAxevG4MYbKXrcTHN4EhUVheuuu07aRpWfn694A9PS0oL33ntPsY3KaDRO6xqILpdWq5V6Ol199dXo7+9HZWUlysvLUVFRgW5ZHxtg+O+V6007PrMOABDW3Y3Kjz9GUlISkpKSWFUxh+n1eiQnJyM5OVm6bGBgQApzXNU5PbJtdHJ9fX0oKytTVCzqdDpER0dLgU5MTAxHk08DR0eHoipOw+CG6LLN2d9KfX19AIbHFLoTFBQEAOjt7Z3Q4910003YuHEjli1bBpPJhIqKCvzlL3/Bc889h/vvvx+RkZG4+eabJ/RYOTk5bi8vLy9HWlrahB6D6LJwq5TP4zhw7zddW6XGExAQgCuuuAIrV65EWVkZ8vPzFdsFLBYLDh48iEOHDiEzMxMrVqxAamoqt1GRVwoKCkJubi5yc3MhiiI6OjqkapzKykq304i6w8JQUFCAgoICAMOhZkpKivQG33W8R3NTYGCgFP659Pb2orGxUbHNqr+/3+39h4aGRjVAdo0ml0+zMpvNHE0+CTbZNikhMBAqBqpEl23OBjfT7Xe/+53ifE5ODn79618jKysLDzzwAP77v/97wsENkcfJ37QxuPFNTnlw47ll0NimMlVqqlQqFTIyMpCRkYHW1lZpG5Xt00885duoIiMjsWLFCixevBgBAQEzui6iqRIEAZGRkdK/V6fTiebmZlRXV6P86FHU1NfD6ubfb1tbG9ra2nD06FEAgNlsVgQ5BoNhtp8KzbKQkBCEhIQgIyNDuqy3txdNTU2KL3mzdzn5aPLjx48DGO7D49pi5QpzTCYTw5wx2BoapNPa6Gh+WDBTWDXvV+ZscOMqlR0YGHB7vSt5DwkJuazv85WvfAWPP/44Lly4gKqqKkX55ljOnTvn9vKxKnGIph3/gPo+WUNPQTOzoQBNjXPg4vQcVeDsvVk0mUy4/vrrFdOo5Nuo2tvbsX37duzatQt5eXlYvnw5YmJieGBNXk2lUkkNbDMqKtD0wovoDQlB9xWr0LthA6qqqtxWUbe0tKClpQX5+fkAgJiYGCQnJyMlJQVJSUkML/2EK8xJT0+XLrNarWhpaUFjY6MU5jQ3N7sdTe5wOFBfX4/6+nrpMo1Gg5iYGEUDZJPJxJ45AGyyVhS6pCQProRo7pizwU1iYiIAoK6uzu31rsuTLvOXiUqlQlpamvSLfyLBDZGnjXyDJooi37T5GFER3PATP2/klI09FjzwKb/BYMDq1auxatUqlJWV4ejRo9LIZWB4asvx48dx/PhxmEwmLFq0CAsXLkQYG72Sl7O3tkIAENrbi3mBgYj77GelrVVVVVWorKxEVVWVtG1ezvUGXd7s2BXkJCYmQq/Xz/4TIo/Q6/WYN28e5s2bJ102cjR5Q0MDmpub3Y4mt9vtqKurU7zX0Gq1iubH0dHRMJvN0M5w1aW3scrGtev43ohoWszZ4GbRokUAgBMnTri93nV5Xl7eZX8v1yeZ3EdNPmNkSON0Aiz39Smiw37xDF87ryQPblQG9/3WZoN8G1VHRweOHTuGEydOYHBwULpNa2srPv74Y3z88cdITk7GokWLsGDBAlYjkFdytLVJpzWfTvaUb61atmwZRFFEe3u7FOJUVVWN6nMib3Z86NAhCIKA+Ph4KciZN28ep7L5GXejye12+6gwp6WlxW2YY7PZRvXMcf3bjI6OlhohR0dHIzQ0dM5+aDbE4GYWiMpt817B29Yzt8zZ4ObKK69EWFgYysvLcerUKSxevFhx/dtvvw0AuPHGGy/r+5w7dw4XLlxAYGAgsrKyLuuxiGbNyAMF7pH1PXZZxQ2DG6/ktFzcqjubW6XGExERgS1btmDjxo04e/Ysjh8/Pqoy1fUm9/3330dWVhby8vKQlpbGXg7kNewtF8cMq6Oi3N5GEARERUUhKioKK1asgCiKaG1tVQQ5Flm4CgwHOa4KigMHDkClUiEmJkYaS52QkIDw8PA5+2ab3NNoNNJ2KBebzYbm5mYpyGlsbERLS4vbSZ2iKEq9l+TtEgICAhRBzlyqzhmSb5VK5lYpoukwZ4MbnU6Hb3zjG3jqqafw9a9/HTt27JAqYn7zm9+gsLAQ69evl9J0AHj++efx/PPP49Zbb8XTTz8tXf7BBx8gICAAmzZtUnyPwsJC3HnnnRBFEffffz8/lSHfweDG5ym2SvENtVcS5T1uvKwhqlarxZIlS7BkyRK0t7ejsLAQhYWFil44drsdZ8+exdmzZxEYGIiFCxciLy8PcXFxfONKHmVvvRjcuCpuLkUQBJjNZpjNZqxatQpOpxMtLS3S1qrq6mpFFRow3KTW9cbcNbUqMDBQEeTEx8dze5Uf0mq10r8Bl6GhISnMcfXLaWlpgd1ud/sYg4ODqK6uRrUs5JgL1TmOvj44Wi9WxbHihmh6zNngBgAef/xxfPzxxzh06BDS09Oxbt06VFdXIz8/HyaTCX/5y18Ut29ra8OFCxfQ2NiouLygoAD/8z//g6SkJCxatAiBgYGoqKjAiRMnYLfbsWHDBvz85z+fzadGdHkY3Pg+efNE9Zz+Ve6TRFEcsVXKu4IbucjISGzcuBEbNmxAbW0tCgsLce7cOUU1wsDAAPLz85Gfn4+oqCjk5eUhLy8PRqPRcwsnvzWV4GYkVzVNTEwMrrjiCjidTjQ1NUnVONXV1W7Hjw8MDKCkpAQlJSXSZWazWRHmREVFsUGtH9LpdG575nR0dKC5uVkKc5qbm9HT0+P2McarzpFX5nhzdc5QlSyIMhigMZs9uJo5jsfvfmVOH+0HBARgz549ePrpp/H666/jnXfeQUREBO6991488cQTipR8PFu3bkVtbS2OHj2KgwcPoru7G6GhoVi7di2++MUv4r777mMJOfmYEc2JR11C3o7Nib2bODQ03DvqU4IHe9xMlCAISExMRGJiIq655hqUlpaisLAQJSUliikrbW1t2L17N3bv3o2kpCTk5eUhOzubY5ZpVogOB+wdHdL5qQY3I6lUKmk7zJo1a6Qmta6tU3V1dWOOj3ZNrnL1T9Tr9YiPj1eEOYGB3v87gKafWq2GyWSCyWRCbm6udPnAwIAU4ri+LlWd4woVXUZW55jNZkRFRSE8PNyj70uGqi+uUZeYCIEhJtG0EER3mzHJI1zjwMcaF040XeytrShd9xnpfObpU1Cx1NunlKxdJzXoTH7zDRhG9PEiz7J3dqJ09RrpfMbRAqhDQjy4oqmzWCw4d+4cCgsLUVNT4/Y2arUamZmZyMvLw/z586HRzOnPhciD7G1tKF27Tjqfcewo1MHBs/K9BwYGUF9fLwU59fX1o7ZXjSUiIkIR5ERHR/NDP1KYbHXOWFQqFSIiImAymaQ+T66v2djW1/rCC2j73+cBACFbtyLhuWdn/HuOZy6+v8rJyUFNWTPWJn3F00tROFD9ZyTOj55T/6+9CY+siPyRu6lS5Fvkn8pxq5TXEUc0PfXmrVKXYjAYsHz5cixfvhwdHR04c+YMTp8+jQ5Z1YPD4UBRURGKiopgMBiQm5uLRYsWIT4+3mf6MpBvkG+TEgwGqGZxomdgYCDS09ORnp4OYLgHTnt7u6IqZ6wGtR0dHejo6EBhYSGAiw1v5WFOaGjorD0X8j7TVZ3jdDql7VYjhYaGjgpzTCYTgoODp+13tXyrFPvbzDDWX/gVHu0T+SP2uPF53Crl3eT9bQStFsIcqUCJiIjA+vXr8ZnPfAb19fUoLCzE2bNnMTBwcYKWxWLB0aNHcfToUUREREj9cCIiIjy4cpor7CNGgXsyGFSpVNIb7SVLlgAArFYrGhoaFGHOyDHkwHDz75qaGkUVW2hoKOLi4qReJjExMTAajQw//VxgYCBSUlKQkpIiXTayOqelpQWtra3o6upyGxy69PT0oKenBxUVFYrL9Xq920BnKtuuFBOlkjhRimi6zI0jSSKaHAY3Pk8e3EDF4MbbOC0Xt08IPlxtMxZBEKQqga1bt6KsrAynT5/GhQsXFP1wOjo6sHfvXuzduxfz5s3DokWLkJOTw344NGXyUeDT1d9mOun1esWbbFEU0dXVpQhyGhsb4XRT6ep6U11cXCxdptPpFNOFYmJiYDabOcnUz41VnWOz2dDR0SFV3LS1taG1tRXt7e2w2WxjPp7VakV9fT3q6+sVl7u2XcnDnKioKERGRiIgIGDU44iiiCFZHx5W3BBNHwY3RP5oRHDD3MYHyUqkWXHjfUTLxQoUX94mNRGu/jaZmZmwWCwoKipCYWGhYsQtANTW1qK2thYffPABEhMTpS0nJg9XTZBvUUyUiory4EomRhAEhIeHIzw8HAsXLgQw/Oa6qalJ0Sunq6vL7f2Hhoaknx25iIgIRZgTHR2NsLAw/iz5Oa1WKzUrlnM6nejp6RkV6LS1tbmtCJPfb6xtVyEhIQgPD0dERAQiIiIQHh6OMI0GlsFBuDrp6FKSp/HZkYII7zuA97LlzDUMbogI/E3rexRbpdjg0uv4yijw6WYwGLBs2TIsW7YMXV1dKCwsRGFhoeKg3+l0StNRdu7cibCwMCnESUlJYSUBjWs6RoF7mlarHTU2ure3F/X19WhsbJT6mHR2do75GK6eOUVFRdJlAQEB0pt2V5jjrSOjaXapVCoYjUYYjUbMnz9fcZ3FYhkV5rS1taGzs3PcbVe9vb3o7e0d3bT+tluhHRpCyMAAzn78sRTquAKe4OBgqDhpimjSGNwQ+aFRoxm9LbGncYmiCMi3Ss2R/ilziXNA1uMm0H+CGzmj0YjPfOYzWLduHRoaGqR+OCM/3e3u7saxY8dw7NgxqNVqJCUlSUFOZGQkKwhIYWSPm7kiJCQEWVlZyMrKki4bHBxES0uLNGHI1ctkrC0vg4ODqK6uVlS7yUdGu8Kc6OhohIaG8meLAAwH7iODRGC4D1NHR4cizHF9jbftCgBsOh06dDp0uJkupNFopCo0ebVOREQEwsLCOJWQaAz8ySDyR5wq5dtGvF6suPE+yoqbQA+uxPMEQUB8fDzi4+OxZcsW1NfXo7S0FGVlZWhsbFTc1uFwoKKiAhUVFfjoo49gNBqlECc5OZnVODQnKm4mKiAgAImJiUhMTJQuczqd6OzsVIQ5zc3N6O7udvsYoihKb7blI3oNBoMU5rh6pZhMJvafIolGo4HZbIbZbFZc7tp25ar66uzslE53NDdj/EhnOBBqbW1Fq+xn2UUQBISFhSnCHPl/Z2OcuU9x8oNXf8LghsgfsTmxT1M0JgYABjdex+lHPW4mQ61WS29EN2/ejN7eXpSVlaG0tBTl5eWwWq2K23d1dUkTqtRqNVJSUjB//nypGof8jzK48f4eN9NNpVIhMjISkZGRyMnJkS63WCzSFitXmDPeyGiLxSJtWZQLDg5WBDmur6BZHLtO3k2+7So1NVVxXe3/ewRt+/ahLzgYwm23wrZ0qRTsdHZ2jttPB7jYzNtdz6fIyEh885vfnM6nQuRTGNwQ+aNRzYkZ3PiUEQfic2XU9Fwi+mmPm8kKCQnBkiVLsGTJEjgcDtTV1aG0tBSlpaVobm5W3NbhcKCsrAxlZWXYvn07IiIipGqcpKQk9vHwA6IoztmtUpfLYDAgOTkZybIpPk6nE+3t7Yowp7m5GT09PWM+Tl9fH/r6+lBZWam4PDAwUBHkmM1mREdHIzDQvysKSclWXY0AqxUBVivisrIQtnGj4nqr1aqo0pFX6/T09Ix7PBoeHj7Ty/cxIiB6W8U830/MJB7tE/kl7mv3ZSMrbkb1LCKPk/e4Uflpj5vJcvW3SUpKwlVXXYWenh5FNc7Q0JDi9h0dHcjPz0d+fj60Wi3S0tKQkZGBjIwMBAcHe+hZ0Exy9vcrQlEGN+NTqVRuR0YPDAwowhxXU9qRFW9yAwMDo/rnAMPh68j+OZGRkVCzEtTviE4nhmT/PtyNAtfr9YiNjUVsbOyo6+x2O7q6uhRhjjzgiYiImMnlE3k9BjdEfmhUP0JW3PgUcWRTQA0rDbyNU1YOLvAT6SkJDQ3F0qVLsXTpUtjtdtTW1kpBTktLi+K2NpsNxcXFKC4uBgDEx8cjMzMTGRkZiI6OZhPWOcLW0HDxjFYLNT+Bn5LAwECkpKQgJSVFukwURfT29kq9R+RfFllYNpJrslBZWZl0mUajgclkUoQ5rM6Z+2w1NRAHB6XzuqTkSd1fo9EgKioKUVGjt0A6nc4xt/0R+QsGN0T+iG9ifJo44lNRVQCb9Xkbh2x/vtpo9Ng65gqNRiO90bz66qvR3d0tbamqqKgYNeGkvr4e9fX12L17N8LCwjB//nykpqYiOTmZvTp8mOLT/HnzWG04jQRBQGhoKEJDQ5GWliZdLooi+vv7R4U5zc3NYwY6drsdjY2No5qPh4aGSiGOqxIoKiqKTcfnCEthoXRal5oKdfD0/a5VqVT8d+KOn3zw2t7ejgULFqC1tRVpaWmKoNifMLghIvIxTtknWtBo2OPGCzlkE17UYWEeXMncFBYWhuXLl2P58uWw2WyoqqpCSUkJLly4MKp/R3d3N44fP47jx48DAGJiYpCSkoLU1FQkJiZySokPGZI10tUlJXluIX5EEAQEBwcjODjYbYXOyP45bW1tY/Yp6enpQU9PD0pLSxWXG41Gtw2R+bPpWyyFZ6TThrw8D66E5pr/+q//Qpusv5m/4tE+EZGPkVfcqHhg65VYcTN7tFqt1KT4uuuuQ3NzMy5cuICSkhLU19ePun1TUxOamppw+PBhqFQqJCQkSEFOfHw8NAxCvZai4obBjUfJK3TS09Oly202m1SRIx9ZPij/wGEE1xShkYFOaGio20CHI8u9k+XMxYqbgLyFHlwJzSW7du3Cq6++igceeAAvvfSSp5fjUTw6ISLyMfI95AKDG6+kqLj2rDZxAAA35klEQVRhcDNrBEFATEwMYmJisH79eqn3RmVlJSoqKtDX16e4vdPpRE1NDWpqarBv3z5otVokJSVJQU50dDRU3I7jNWxV8sanDG68kVarRVxcHOLi4qTLRFFET0+PFOK4tlu1tbWN27fEVaFTXl6uuJwjy72Pc2gI1qLz0nnDQlbczDgRgNPLtkpN83IsFgsefPBBZGdn49vf/jaDG08vgIiIJsc5eLHiRmB/G6+kqLjhVimPkY8bF0URra2tUohTVVU1aoqOzWaTRo4DwyOWXSFOSkoKIiIi2OjYg1hx45sEQUBYWBjCwsKQkZEhXe50OtHV1eW2IfLIvlVyExlZbjabFYEOf25nlvXCBWlwgqDTISAz4xL3ILq0//mf/0FFRYX0wYq/Y3BDRH7T3GyuEK0XK25U+gAProTcEUWRFTdeSBAEmM1mmM1mrFq1Cg6HA42NjVKQU1NTA4fDobiPxWJBUVERioqKAAz31pEHOSEhIZ54Kn7J2d8Pe2urdJ7Bje9TqVSIiIhAREQEMjMzpcudTid6enrcBjpTGVkeEBCAyMhI6XvJvwIDAxnqTAN5Y+KABQsgsJEwXabCwkL8+te/xn333Yd169ahStbjzF8xuCHyRzxI8WlOq7zihsGNt3H29QGyAIDBjXdSq9VISEhAQkIC1q1bB5vNhtraWinIaWhoGNVktbu7G6dOncKpU6cAACaTSQpykpOTEcCfxxkzVFMjnRb0emhiYjy4GppJKpUKRqMRRqNR0T9nrJHlLS0t4/bQGRwclCbNjaTX690GOhEREQgODmaoM0GD8uCGjYlnzxz94NXpdOL++++H0WjEM8884+nleA0GN0REPobNib2bfJsUBAHq0FCPrYUmTqvVIjU1Fampqdi8eTMsFguqq6tRUVGByspKtMqqPVxcbxwLCgogCALi4uKkseXx8fEMcqaRYqJUYiJHgfuhyY4sb21tRX9//7iPabVa3Y4uB4Z/J4wV6oSEhLD/lQwnSpFLeXk5cnJy3F537ty5CT3G//7v/+Lo0aN4+eWXERkZOZ3L82kMboiIfIx8HDgrbryPo+viNilVaCgEtdqDq6GpMhgMyMrKQlZWFgCgt7dXqsaprKxEt2w7HDD85tH1qf6BAwcAAJGRkVKj1vj4eMTExEDHLQRTouhvw8bEJDPWyHIA6O/vR1tbGzo6OkZ9jbftChjueeUacz6SRqNBeHi421AnLCzMr0IdR08PhmT9hgycKEWXoaamBo8//jjWr1+Pe++919PL8SoMboiIfIw4yIobb8bGxHNTSEgI8vLykJeXB1EU0dHRoQhyLBbLqPu0t7ejvb0dZ84MfxotCAJMJpMU5sTFxSE6OppNFydgqIqNiWnygoKCEBQUhKQR/2ZEUcTAwIDbQKejo8Ptz7Oc3W6XqnpGkm/1cjVldp02Go0IDQ2Feg4F+pYzF6tt1GFh0CYmenA1fsYLt0qlpaVNuLLGna9//esYGhrC73//+2lc1dzA4IaIyMfImxNzHLj3YWPiuU8QBERGRiIyMhLLly+H0+lEc3OzFOTU1ta6/TRfFEW0tLSgpaVF6pOjUqkQHR2tCHPMZvOcemM3HeQVN1oGN3SZBEGQQp158+aNut5isYwZ6lxq+5XT6ZRuO9b3DgkJGRXoyP/rS5V5g7LgJiAvj32B6LJs27YNRqMRDz30kOJyVx+r+vp6bNiwAQDw5ptvIsaP+p0xuCEir0zsaWwcB+7dWHHjf1QqFWJjYxEbG4s1a9bA6XSis7MTDQ0NaGhoQH19PRobG92OOHY6nVKPjePHjwMYbpwcExMjbbGKi4tDVFSUX22/GImjwGk2GQwGxMfHIz4+ftR1Vqt1zFCnt7f3ko8tiiJ6enrQ09OD2tpat7cJDAwcN9gxGAxeE5Ao+tss5DYpunxdXV3Yt2+f2+sGBwel68ZrSj4XMbgh8kde8seepkbZnJg9bryNo7tLOs2KG/+kUqmkipyFn76RcTqdaGtrk8KchoYGNDU1wW63j7q/w+GQ+uUcPXoUwHCj1NjYWEXPnPDwcL8Icxw9PXDIqhd0ScmeWwz5Pb1eLwW1Iw0NDaGzsxNdXV3o6upCd3e34r+XqtZxGRgYwMDAgNumyQCg0+ncbsEKCQlBSEgIQkNDZ6VqRxRF5Shw9reZXXPwg9eR0xxdqqqqkJKSgrS0NJSVlc3yqrwDgxsiIh/jtLI5sTeTNydmxQ25qFQqmM1mmM1mLF68GMBwQNPS0qIIc5qbm+F0Okfd32azoaamBjWysdh6vV4KcmJiYmA2mxEZGQmNZm4d3smrbYTAQGjMJg+uhmhsOp0O0dHRiI6Odnu9zWZDd3f3qEDHdVl3d/eYb1zlhoaGxuyx46LX60eFOfL/hoSEIDg4+LLCX3tjIxxtbdJ5TpQimjlz6y87EZEfUDQn5lYpr6PYKsWKGxqHWq2WPrlftmwZgOE3dq4wp76+Hg0NDWhtbXX7Zs5qtaKyshKVsokurmofs9kMk8kkhUXh4eE+2zdH0Zg4MdFrtogQTZZWq0VUVBSioqLcXu90OtHb2+u2Wsf1X3dVeu5YrdZLhjuuiVyXCngCxviQSL5NSpuQAE1ExITWRkSTx+CGiMjHKJsTs+LG23CrFF0OrVYr9dZYsWIFgOFP15uamhQ9c9rb293e3+l0un2zplarYTKZFGGO2Wz2idHFylHgyZ5bCNEMU6lU0iQqd1zTsNxV6/T09KC3txd9fX0TqtpxPV5vb+8le/PodLpRYU5ISAicJ07AHhUFw6AFJlbbzDIRcFOd6Vlzb+uWN2FwQ0TkY5ysuPFq3CpF002n0yExMRGJsjG7g4ODaGxslMKclpYWtLe3u91mBQxvy2pqakJTU5Picq1Wq6jOiYmJQWxsLAwGw4w+p8lgY2KiYfJpWO4aJwPDP+v9/f3o7e2VwhzXf+Wn3U2+G8vQ0BDa29vdB8ZXbZZO6n72M2kLVnBwsHRaPkUrJCTEZ6v/yHOSk5MnHEjOVQxuiIh8jCjroi/oGNx4G1bc0GwICAhASkoKUlJSpMvsdjs6OjqkkeOur87OzjEPeG02m9QIWc5oNCIuLk7ayhUbG4ugoKAZfU5jsckm7+gSR49uJqKL1Go1QkNDERoaOma4AwxvpRoZ5owMePr6+sYMg90ZN+D5lHwcuuvL1WTZ9TXW1iwif8bghojmZFf6ucw5MCCdVgV6z6fiNFx2bm+92KhRHRHuwdWQv9FoNNIWKDmbzYa2tjZFmNPa2oouWT+mkVxTcYqKiqTLwsLCFEFOdHQ0QkNDZ7TnjOh0wiqbIMKKG6Lpodfrodfrx+y3AwxvvRwYGHAb7HTV1KCzrAwWgwFWvX7CE0snMg5dr9ePCnSioqKQlZU1pec6J4nwvuN3L1vOXMPghsgfjfz0hCWrPoXNb72Xo6MDoixY0yUkeHA1RMNco8RHji92NS91BTnNzc1obGyExWJx+ziuXhrFxcXSZQEBAVJYFB0dLZ2erq1WQ1XVcPb1DZ8RBOizFkzL4xLRpalUKmnb00iNP/oxuj7aAQAI3LgR4b/4Ofr6+qQ+O/LTPT096O7unvA4dKvVKoXMLnFxcQxuyK8xuCHyQ6JzRCTOCR0+xdEt66HC4MaryLd0qEJD2eOGvJper0dCQgISZAGjKIro7u5GQ0MDGhsbpT46A7JAUm5wcHDUmHIACA0NHRXoREVFQavVTmqNg+fOSqd1qalQB3tmuxYRXSTa7ejduVM6b7xmq7Q9azw2mw09PT2jRqC7Gi339PTA4XC4va+Rxzvk5xjcEPkjUVlxI3j5RBG6SBRFZcUNgwGvMlR3sU+INmHs3gJE3koQBBiNRhiNRmRnZwO4uLXBFeI0Njaiqalp3Ek0rq0QZbJtToIgSKPK5YFOeHj4mJOtLGcujhs25OZO07MkossxcPQoHJ2dw2e0WgRv3Dih+2m1WkRGRiIyMtLt9U6nE/39/aMCne7ubsybx/5Wo3jbVimaUQxuiPzRyK1SDG58hmixQBwaks6z4sa72OrqpNO6eG6TorlBEASpz4R8q8LAwICib05zczNaWlrGnFYjiiLa2trQ1tam6J0j780jD3SCg4MxePacdLsABjdEXqHno4+k08Fr1kB9iUqbiVKpVNKo8QRuNSZSYHBD5IfEkcGNwODGV8i3SQGsuPE2Q3UXt0ppedBJc1xgYCCSk5ORnJwsXeaqznGFOK5Ap62tbcwtEHa7XRprLmcwGBASbkTo0qUwdndBHRsDbW8vgoODZ7QhMhGNTXQ40LvzY+l8yNatHlwNkf9gcEPkj0aUVvL413fIt0mpAgMh6HSeWwyNYpNvlZrH4Ib8j7w6JyMjQ7rc4XCgo6NjVKDT6dpu4YbFYoHFZEKLyQQAOHbgAHDgALRaLSIiIhAZGYmIiAjFV3Bw8Jjbrojo8g0cOw6Ha9y3VouQzZs8uyB/NrJnJc1pDG6I/BG3SvksNib2boqtUqy4IZKo1WqYTCaYPg1hXIaGhqTJVvJQp881ScoNm82G5uZmNDc3j7pOo9GMCnNcIU9ISAhDHaLL1LvrYrVN0BVXsPKXaJYwuCHyRyObmfFA1mcoKm6MPFjyJqLdDltjo3SeW6WILk2n0yE+Ph7x8cpm3v39/Tj/y1+i/vgJdBvD0J+aip7AwDFHlbvY7fZRY4Rd1Gq121AnIiICYWFhDHWILkEURfTt3iOdZ7UN0exhcEPkh0aOA2evAN/h6LpYcaNhxY1XsTU1AbIeHtp4TpUimqqgoCBEnitCUGkpACDm+hsQfufnYbFY0NHR4farv79/3Md0OBxobW1Fa2vrqOtUKhXCw8MVW7DCw8NhNBoRGhoKvV4/I8+TyJcMlZUpKkuDN2zw3GL8nAgR4ogpsZ4mglu3ZhKDGyJ/NPIXPT9l9BmKihuWJ3sV+cGsxmyGim/0iKZMHBqCtbhYOh+wcHiilMFgcFuhAwCDg4Po7OxER0cH2tvbFaHOeFuvgOExxO3t7Whvb0fpp2GRXEBAgNS7x/UVGhoqnQ4JCYFarb7MZ03k3Xr37JVOB2RnQxsT47nFEPkZBjdE/og9bnwWe9x4L3lww21SRJdnsKQUos0GABC0WgSkp1/yPgEBAYiNjUVsbOyo66xWqxTqjPzq6em59HoGBzE4OOi2rw4wXLkaEhKiCHNGBjyBgYGscCWf1rfn4jap4E3cJkU0mxjcEPmhkVulOFbKd8grbhjceJehWlljYk6UIrosg2fPSKf1CxZc9gQ9vV6PmJgYxLipELDZbG4Dnc7OTvT09MA58sMON1xj0Ht6elAnC3HlNBrNmBU7rvM6TgokL2Vvb4fl1CnpfPDGDZ5aCgGACO+bKuVly5lrGNwQ+SP5VilB4CeAPkQR3HCrlFdRVNzEM7ghuhyWs2el04bcnBn9XlqtFtHR0YiOjh51ndPpRF9fH7q7u9HT04Pu7m7FV09PzyV767jY7XZpO9ZYAgICEBISguDgYMXXyMsMBgP/dtOs6tv3iTTcQhMdjYDsbA+viMi/MLgh8kfyTw+5TcqncKuU9+JWKaLpM3jmYnATkLvQY+tQqVQIDQ1FaGjomLex2WyjQp2R522fbvu6FNeWLHcNlOXUavW4wY7rfFBQEDQaHu7T5VNsk9q4gcEh0Szjb3IiPyQyuPFZrLjxXkN13CpFNB2cFgusZWXS+YAZrri5XFqtFpGRkYiMjHR7vSiKsFgsbit2XCFPT08PRHHi+wwcDod0/0sxGAxjBjuucCcwMBCBgYEciU5uOa1W9B08KJ0PYX8b7zCJ3xnk+xjcEPkj2S96fl7iW1hx452cAwNwyLY/sOKGaOoGi4sBhwMAIBgM0KeleXhFl0cQBCkYcddjBxgOYvr6+tDb24u+vr5Rp+XnJ9JzR85iscBisaClpeWStzUYDAgMDJTCnEv9l9U8/mGgoADiwAAAQAgMROCqVR5eEZH/4W9bIn/EihufJIqiMrgJM3puMaRgq6+/eEarhcZs9txiiHycYptUdjYEPxizrVarpSbF43FV74wX7Li+BgcHJ70OV8gzXh8eOb1e7zbQCQ4OhtFolL4MBsOk10Leo3f3bul08JVroNLrPbgaIv/E4IbIH8lLKxnc+AxnXx9gt0vn1eFGzy2GFBQTpeLi/OKNJtFMsZw+LZ025OZ6cCXeR169Y75EQGyz2RRBjrtwp6+vD/39/XB8WuE0WVarVRq1Pp6AgABFkOManR4aGoqQkBCEhIRAq9VOaQ00s5xWK/p2yYKbDRs9uBpSmGT1Hfk2BjdEfkiUNUnkG0zfYautlU4LWi3U4zTLpNk1cPyYdFqXmurBlRD5Nkdvr+LTfcOSxZ5bjI/TarUIDw9HeHj4uLcTRRFDQ0Po7+/HwMDAhP470WbLLoODg2hqakJTU9OYtwkMDBwV6Iw8HRAQwKa4s6zj1f+D3bXNTqNB8Ib1nl0QkZ9icEPkh5yDVum0YAjw4EpoMgYvlEindenzGbp5kf79B6TTQWvWeHAlRL6t+91/Q7RYAAw3YA/eyE/3Z5ogCNDr9dDr9YiIiJjQfWw227jBTm9vL7q6utDV1QW7rFJ0PAMDAxgYGEBzc/OYt9FqtW4DHfllwcHBbLI8TWzNLWj7/e+l8+F3fQGaMZpwE9HMYnBD5IfEQYt0WhXAfee+wlpyMbgJSM/w4EpIztbUpHhtgtet9eBqiHyXKIro+vub0vmw225jLw0vpdVqpW1P4xFFEf39/ejs7JSCnO7ubvT29krTtPr7+yf8fW02Gzo6OtDR0THmbQRBQHBwsCLQkU/PCgoKkr70ej0reMbR+tvfSk2J1UYjTF//uodXRAqcKuVXGNwQ+SF5xY0qgAfFvsJ64YJ0Wp+Z6cGVkFz/gYvVNtrEROiSkz23GCIfZjlxAtbSi2PAjZ+7w4OroengClGCg4Mxb948t7ex2+3o6+tDT0+PItCRn+/t7Z1wHx5RFNHb24ve3t5L3latViuCHHfhjvzLn/rwWAoL0f3OO9J506OPQH2J5tlENHMY3BD5IXnFjcCKG58xWHqxqkOfwYobb9H3yX7pdPBaVtsQTVXnGxerbQJXXwF9SooHV0OzRaPRXLJ6RxRFDAwMjAp0Rp62Wq1jPoY7DodDuu9E6HS6S4Y7rut9eVy66HSi6amnpPP6zEwY72CQSuRJvvnbhIgui9NycUQoy9B9g72jA47WNul8QCaDG28g2mzoP3RIOh/0mXUeXA2R77J3dKD3o4+k8+F3fsGDqyFvIwiCFIrExsaOebuhoSG31Tr9/f2Kr4FPt/9M1tDQEIaGhi45RctFp9PBYDBIQU5gYOAlz3tDVU/Ptm0YPF0onY9+7DH21fM2ogjR26ZKcevWjGJwQ+SHnNaLwY1gYMWNL5D3UFGHh0MdFeXB1ZCLpbBweEw7hid9Ba1c6eEVEfmm7n/9S5p4qDGZELKJTYlp8nQ6HaKiohB1ib+RTqcTFotlVKAzMtxxnR4cHBz38cbiCnq6u7snfB+NRjOpoMdgMECn001brx5nfz9afvVr6XzIli0IumLVtDw2EU0dgxsiPyTKK27Y48YnjOxvw2aK3kG+TSpwxXKoAgM9uBoi3yQ6nej8+z+k88Y7bofgBVUHNHepVCqpgmci7Ha7IsiRn3b3Ndlx6SO/12S2bwHDvXoMBgMCAgIQEBBwydPyy0Y2aG774x+l8d+CTgfzd78z5edCRNOHwQ2RH1JU3LDHjU+QjwLnNinv0b//YnATtO4zHlwJke/qP3QYttra4TMqFXtpkNfRaDTSuPGJsNlsGBgYgMVikcacX+r80NDQlNfncDjQ19eHvk8rQCdDEAQpxAlQq+G8UALdmtXQDtkQlp2N1spKGJqa3AZBer3eZ/v4zAncmuRX+JNG5IdYceN75Ful2JjYO9hbWzFYVCSd5xhwoqnpfPMN6XTwhg3QjtPDhMgXaLVahIWFIWwSU5jsdvukgp6BgYFJN2N2RxRFWCwWWCyfDq6INl+8csgK7No17v01Gg30er3iyxXqTPQynU4HNXvoEI2LwQ2RH2LFjW8RHQ5YS0ul8/oMjgL3Bn0HD0qnNXGx0KWleXA1RL7J1tSEvj17pfPhd37ec4sh8iCNRoOQkBCEhIRM+D4Oh0MKcwYHB2GxWDA4ODih05dT4SNnt9tht9vR399/WY+j1WrHDXhMJhOWLVs2LWsm8kUMboj8ECtufMtQTQ1E16dqggD9fAYE3qBfMQZ8HfsOEU1B19v/BBwOAIA2Ph5BV17p4RUR+Q61Wo3g4GAEBwdP+r4Oh+NimDMwgKrHvo/+5mYM6XQQkxIRcMstsFqtYwZA4jRv07HZbLDZbGNu90pJSWFwM5KTW6X8CYMbIj+krLgJ8OBKaCKssv42uqQkqDgJzONEhwP9soqbIG6TIpo00W5H11tvSeeNn/88Rw4TzRK1Wi01aO7c+TEijx1D5KfXJf/sKRgWLRrzvqIowmq1YmhoCIODg7BarYqviV42maqfAB6vkp9jcEPkh5QVN/xD6O2sJbKJUuxv4xUGz56FwzXeVaNB0OrVnl0QkQ/q27sX9ubm4TNaLYyfvc2zCyLyQ47ubrQ++6x0Puzmm8cNbQBlQ+OJNmx2x+l0Tjj0iY6OnvL3IZoLGNwQ+SFW3PiWQXljYk6U8gqKMeBLlkA9hTJ1In/X+cab0unQq6+GJjJynFsT0Uxoe/FFOLq6AABCYCBM3/rWrH1vlUoFg8EAAyuJp0Z0enoFNItUnl4AEc0+Vtz4FvlWKVbceIe+A7Ix4J9Z58GVEPmmoZoaxXZDI5sSE806a3k5Ov72unQ+6oEHoJVPlSIir8HghsgPOWXjI1lx492c/f2w1dZK5wMyOVHK0+ydnRgsPCOdD17H4IZosrr+8Q/ptC4tDYErVnhwNUT+qfnnvwDsdgDDzcEj7rvXswsiojFxqxSRHxItFuk0K268m3wMuBAYCG1CggdXQwDQf/AQ8Ok0DY3JBD3DNKJJcQ4Noeuf/5LOh3/+85zKRjTL+vbtQ//+i9Wj5v/+LlR6Thr1GaII0dumSk3zpDFSYsUNkR8SP/10BWDFjbezd3ZCHREBANCnz4eg4q9tT3P29UEdHg4ACFrHMeBEk2VvaYUuJQXA8N+gsFtu9vCKiPyP6HBCYx7eFhW4ahVCrr7awysiovGw4obID6V9+AFEux3OQStUep2nl0PjCNm4ESGHDsLe1nZxihF5VPidn4fxc3dg8FwRVAH8dJJosnQJ8Uh+/W8YvFAC64ViqC9jKg0RTU3Ipo0IWrUSbS/9EaHXXcsPIYi8HIMbIj8laDRQB/NXgK/QREVBExXl6WXQpwSVCoaFuZ5eBpFPC8jMQAAn5RF5jCooCOb/fNTTy6Cp4lQpv8KaeyIiIiIiIiIiL8XghoiIiIiIiIjIS3GfBBEREREREZEP8bqpUjSjWHFDREREREREROSlGNwQEREREREREXkpbpUiIiIiIiIi8iWcKuVXGNx4kZqaGthsNuTk5Hh6KURERERERD6tvLwcWq3W08uYdgPow2Fxh6eXoTCAPk8vYU5jcONFgoKC0N/f7+lleJXy8nIAQFpamodXQpPF18438XXzTXzdfBdfO9/E18038XXzXVN97bRaLYKCgmZiSR7jzf9+vXltvk4QRZHtqMlruaqPzp075+GV0GTxtfNNfN18E18338XXzjfxdfNNfN18F1878ndsTkxERERERERE5KUY3BAREREREREReSkGN0REREREREREXorBDRERERERERGRl2JwQ0RERERERETkpThVioiIiIiIiIjIS7HihoiIiIiIiIjISzG4ISIiIiIiIiLyUgxuiIiIiIiIiIi8FIMbIiIiIiIiIiIvxeCGiIiIiIiIiMhLMbghIiIiIiIiIvJSDG6IiIiIiIiIiLwUgxvyWq2trfj2t7+NzMxMGAwGREREYOnSpfjOd77j6aXRGI4ePYrPfe5ziIuLg1arhdFoxLp16/Dyyy9DFEVPL8+vHT9+HD//+c9x2223ISEhAYIgQBCES97vlVdewcqVKxEcHIyIiAhcd911OHTo0CysmIDJvW5OpxP79+/Hd7/7XSxbtgwhISHQ6/VIS0vDQw89hMrKyllevX+b6s+c3FVXXSXdr66uboZWSnJTfd1sNhueffZZrFy5EqGhoQgODkZGRga+/OUvo76+fhZW7t+m8ro1NDTgG9/4BubPnw+9Xo/AwEDk5eXhxz/+MXp7e2dp5f5tYGAA77zzDr7yla8gMzMTAQEBCAoKwqJFi/DTn/4UfX19Y96XxyfkbwSR76bICx0/fhxbt25Fe3s7cnJykJubi56eHhQVFaGurg52u93TS6QR/vnPf+Lzn/88HA4Hli5divnz56O1tRX79++H3W7HXXfdhb/97W+eXqbfuuWWW/Duu++Ouny8PwGPPvoonnvuORgMBmzZsgWDg4PYtWsXRFHE22+/jVtuuWUGV0zA5F63srIypKenAwBiYmKwcuVKqNVqFBQUoL6+HiEhIfjggw+wdu3aGV83Te1nTu6VV17BfffdB0EQIIoiamtrkZCQMN3LpBGm8rp1dHRgy5YtOH78OGJjY3HFFVcAGP6ZPHPmDPbv38+fuxk22dettLQUV155JVpbW5GcnIylS5dicHAQhw4dQldXF7Kzs3Ho0CGEhYXN9NL92p/+9Cd89atfBQAsWLBAOt4/dOgQent7kZWVhX379sFsNivux+MT8ksikZdpaWkRo6KixMDAQPHdd98ddX1+fr4HVkXjsdlsotlsFgGIf/vb3xTXFRUViRERESIAcffu3R5aIf385z8Xf/jDH4r//ve/xcbGRlGv14vj/QnYuXOnCECMjIwUS0pKpMsPHTok6nQ60Wg0ip2dnbOwcv82mdetrKxMvPrqq8Vdu3aJTqdTunxwcFC89957RQBiYmKiODQ0NFvL92uT/ZmTa2lpESMiIsQtW7aISUlJIgCxtrZ2hldMojj5183pdIobN24UAYg//vGPRZvNpri+vLxcbG1tnell+73Jvm633nqrCEB8+OGHRbvdLl3e1dUlXnHFFSIA8Uc/+tFsLN2vvfLKK+IDDzwgFhUVKS5vaGgQlyxZIgIQv/CFLyiu4/EJ+SsGN+R1vva1r4kAxBdeeMHTS6EJOnPmjAhAzMzMdHv9//t//08EIP7iF7+Y5ZXRWC51UHvttdeKAMTf/va3o65zvZ6/+tWvZnCF5M5k3vzLDQwMiGFhYSIAce/evTOwMrqUybx2d911lxgQECCWlZUxuPGwS71uf//730UA4h133DGLq6JLudTrFhkZKQIQGxsbR133r3/9SwQgXnvttTO5RLqEQ4cOiQBEvV4vWq1W6XIen5C/Yo8b8ioWiwV//etfERQUhPvuu8/Ty6EJ0uv1E7pdZGTkDK+EpoPFYsHu3bsBALfffvuo612Xvffee7O6Lpo6g8GAjIwMAMN9Hch7bd++Ha+//jp+8IMfIC0tzdPLoUv44x//CAD45je/6eGV0GRM5LiFxyyetWjRIgCA1WpFe3s7AB6fkH9jcENe5dixY+jt7cWSJUtgMBjw4Ycf4lvf+hYefvhhPPvss3zD4aVSU1ORlpaGCxcu4PXXX1dcd/78efz1r39FeHg4br31Vg+tkCbjwoULsFqtMJlMbntqLF26FABQWFg420ujKXI6naiurgYw3P+GvFN/fz++9rWvISsrC9/97nc9vRy6BJvNhgMHDkCj0WDlypUoLCzED3/4Qzz44IP46U9/itOnT3t6iTSGLVu2AACeeOIJOBwO6fLu7m4888wzAIAvf/nLHlkbDauoqAAAaLVaREREAODxCfk3jacXQCRXVFQEADCbzW4bzX3/+9/Hn//8Z3zhC1/wxPJoDGq1Gq+++ipuuOEGfPGLX8Svf/1rpKeno6WlBfv370d2djZeeeUV6Q8vebeamhoAGLMRalBQEIxGIzo7O9Hb24uQkJDZXB5NwRtvvIGWlhaYTCasWbPG08uhMfzoRz9CVVUV9u7dC51O5+nl0CVUVFRgcHAQ0dHR+O1vf4sf/OAHcDqd0vU/+clP8Mgjj+C3v/2tB1dJ7jz99NM4fvw4XnzxRXzwwQdYtmwZBgcHcfDgQQQEBOCvf/0rNm7c6Oll+rXnnnsOAHDNNddIFVI8PiF/xoob8iqdnZ0AgH//+9/Yvn07XnjhBbS0tKCqqgrf/va3YbFYcM899+DUqVOeXSiNcuWVV2Lfvn1ITU3FiRMn8Pe//x179uyBSqXC1VdfjdTUVE8vkSbINX4zMDBwzNsEBQUBAEem+oDa2lo8+uijAICf/vSnE97aSLPrxIkTeO6553DPPfdg/fr1nl4OTYDrmKW9vR2PPfYYHnroIZSXl6OtrQ1//vOfYTAY8Oyzz+KFF17w8EpppJiYGOzduxdbtmxBVVUV/vnPf+L9999HV1cX1qxZg2XLlnl6iX7tgw8+wJ///GdotVo88cQT0uU8PiF/xuCGvIrrkyq73Y6f/vSnePjhh2EymZCUlIRf/vKXuOOOO2Cz2fDLX/7Swyulkd544w2sXLkS8+bNQ35+Pvr6+lBSUoJ7770Xv/71r7Fp0yZYrVZPL5PIr/T39+O2225DW1sbbrnlFjz00EOeXhK54XA4cP/998NoNOJXv/qVp5dDEyQ/Zrn22mvxwgsvIDU1FZGRkfjyl78sHas8/fTTnlwmuVFYWIhFixbhwoULePfdd9HZ2Ym6ujo8++yz+PDDD3HllVfiwoULnl6mXyouLsZ//Md/QBRF/PKXv5R63RD5OwY35FWCg4Ol0+6aE7su27dv36ytiS6ttLQU99xzD6KiorBt2zasXLkSQUFBSE9Pxx/+8AfccMMNOHHiBP7yl794eqk0Aa6fw4GBgTFv09/fDwAsQ/ZiNpsNd9xxB44dO4a1a9eO6j9F3uPZZ5/FyZMn8cwzzyAqKsrTy6EJutQxy7333gsAqK+vR1lZ2Wwtiy7BZrPh9ttvR0NDA/71r3/hpptugtFoRHx8PB555BE8+eST6OjowI9+9CNPL9Xv1NfX45prrkFnZye+9a1v4ZFHHlFcz+MT8mcMbsirJCUlARgugTSZTKOuT05OBgC0tLTM5rLoEt58803YbDZcc801igNZl8997nMAgE8++WS2l0ZTkJiYCACoq6tze31/fz+6uroQHh7OAyMv5XQ6cc899+DDDz/E4sWL8d5778FgMHh6WTSG9957D4Ig4NVXX8WGDRsUX01NTQCAO+64Axs2bMD27ds9vFpycR2zABePT+QCAwNhNpsB8LjFmxw5cgSlpaVISUmRmtnK3XHHHQB4zDLbOjo6sGXLFlRXV+O+++5zW33I4xPyZ2xOTF5lyZIlAIbH/Vmt1lG9GDo6OgDAbThAnuP6AxoWFub2etflrn4A5N0yMzOh1+vR2tqK+vp6xMfHK64/ceIEACAvL88Ty6MJ+OY3v4k33ngDGRkZ+Oijj2A0Gj29JLoEURTHfaN45MgRABerOMjzwsLCkJKSgsrKSrd/35xOJ7q6ugDwuMWb8JjF+/T19eHaa69FUVERbrvtNvzxj3+EIAijbsfjE/JnrLghr5KYmIhFixZBFEW326Fcl7kCHvIOrvHCx44dc3v90aNHAbj/RJK8j8FgwKZNmwAAb7311qjr3377bQDAjTfeOKvrool5/PHH8eKLLyIxMRE7d+6UPvEn77V3716Iouj2y1XVUVtbC1EUGdx4mZtuugnA8Gs40pEjRzA0NASDwYDMzMxZXhmNxXXMcuHCBbcNbHnMMrusVituvvlmFBQUYOvWrXjjjTegVqvd3pbHJ+TXRCIv87e//U0EIC5cuFBsaGiQLj958qQYEREhAhD/8Y9/eHCFNNLx48dFACIA8cUXX1Rcd/jwYTEoKEgEIO7cudNDK6SR9Hq9ON6fgJ07d4oAxMjISLGkpES6/NChQ6JerxeNRqPY2dk5CysluUu9br/5zW9EAGJMTIzidSPPu9RrN5akpCQRgFhbWzsDq6JLudTrVllZKep0OjEkJEQ8fPiwdHlra6u4YsUKEYD48MMPz8ZSSWa8181isYhms1kEIN59993i4OCgdF19fb24cOFCEYD4gx/8YLaW67fsdrt46623igDEdevWif39/Ze8D49PyF8JoiiKsx0WEV3Kvffei1dffRVGoxFr1qyBxWLBoUOHYLVa8dWvfhUvvfSSp5dII3znO9+R9iPn5OQgOzsbDQ0NOHz4MJxOJx544AH84Q9/8PAq/df777+vGKlZUFAAURSxatUq6bIf/vCHuP7666Xzjz76KJ577jkEBgbi6quvxtDQEHbu3AlRFPH222/jlltumc2n4Jcm87qdOnUKS5cuhSiKWL16NTIyMtw+5v3334+1a9fO+Nr93VR+5txJTk5GdXU1amtrkZCQMGPrpWFTed3+8pe/4P7774dGo8Hq1asRFhaGQ4cOob29HUuXLsW+ffu4VWqGTfZ1e+edd3DHHXfAbrcjPj4ey5cvh8ViweHDh9Hb28vXbZY899xzePTRRwEAt956K0JDQ93e7le/+pWicTuPT8gveSoxIhqP0+kUX3rpJXHZsmViYGCgGBQUJK5evVp85ZVXPL00Gse//vUvccuWLWJkZKSo0WjE8PBwcePGjeLrr7/u6aX5vZdfflmqihrr6+WXX3Z7P9fPodFoFK+55hrx4MGDs/8E/NRkXrc9e/Zc8rZjvc40/ab6MzcSK25m11Rftz179ohbt24VjUajqNfrxQULFog/+clPxL6+vtl/En5oKq/biRMnxLvuuktMSEgQtVqtGBQUJC5evFj82c9+Jg4MDHjmifiZH//4xxP6u1VZWTnqvjw+IX/DihsiIiIiIiIiIi/F5sRERERERERERF6KwQ0RERERERERkZdicENERERERERE5KUY3BAREREREREReSkGN0REREREREREXorBDRERERERERGRl2JwQ0RERERERETkpRjcEBERERERERF5KQY3REREREREREReisENEREREREREZGXYnBDREREREREROSlGNwQEREREREREXkpBjdERERERERERF6KwQ0REZGXSUlJgSAIE/7S6XSwWq2eXvaE7N27d9T629raRt1u586dEAQBDzzwwLSv4f3334cgCLjqqqsuedv29naEhYVBEAQcOnQIRqNRsfZXXnll2tdHREREJKfx9AKIiIjoIqvVig0bNkAURcXl27dvR3NzMzZt2oR58+YprouNjYVer5/NZV62tLQ0rF27FgAQEBAw6vqTJ08CAJYtWzbt3zsnJwcAUFxcfMnbPvXUU+jp6cFnP/tZrFmzBnfddRcGBgZw6tQpnD59etrXRkRERDQSgxsiIiIvotfr8fLLL4+6PCkpCQDwm9/8BosWLZrtZU27tWvXjlutcuLECQAzE9wkJSUhKCgI9fX16OnpQWhoqNvbVVdX48UXX4RWq8XTTz8NAHjxxRcBAD/5yU8Y3BAREdGs4FYpIiKiWVZeXo6ampoJ376rqws1NTXQarVYsGDBtK/n8OHDGBwcnPbHvRwnT56EVqvFwoULp/2xBUFAdnY2gPGrbn70ox/BarXiwQcfRHp6+rSvg4iIiGgiGNwQERHNgp6eHvzpT3/CunXrMH/+fKmiZCIKCwsBAFlZWdDpdNO+tsceewwxMTF48MEHcejQoWl//Mnq6+tDaWkpcnNzR20B+/vf/47g4GDExMTgwIEDiuuKiorwwAMPICUlBXq9HmazGXfffTfq6upGfQ9XcHP+/Hm3azhz5gz++te/IjQ0FD/60Y+m6ZkRERERTR6DGyIiohnidDqxY8cOfPGLX0RMTAy++tWv4uDBg1i/fj2ysrIm/Diu4GamtkjdfPPNCAwMxEsvvYQrr7wSGRkZeOqppyZVFTSdTp06BVEUFduk7HY7vvWtb+HOO+9ETk4Ojh8/LvXIAYA//OEPWLx4Mf785z8jNjYWN910E4xGI1577TVcccUVaG5uVnwPV5+bsYKbxx57DE6nE9/73vdgMplm4FkSERERTQyDGyIiomlWXFyMxx57DImJidi6dStef/11JCYm4sknn0RlZSX27t07qeDG1UslLy9vRtb7n//5n6itrcX27dtx1113ob6+Ho8//jiSk5OxefNmvPbaa+jv75+R7+2Oqxpp6dKlAIDm5mZs3rwZv/3tb3Hffffhk08+QXx8vHT7d999F1/72teQkpKCkydP4tChQ3jrrbdw/vx5PPzww6ivr5d61LiMF9x88skneP/995GQkIBHH310hp4lERER0cQwuCEiIpoGnZ2dePHFF7Fq1SosWLAAP//5z2G1WvH1r38d+fn5KC4uxg9+8AOpyfBkzHTFDQCo1Wps3boVf/vb39DU1ISXX34ZGzZswJ49e3D33XcjJiYG9913H/bu3Ttq4tV0k0+UOnz4MJYuXYrDhw/j+eefx1/+8hfF9qm+vj488MADCA4Oxvbt2xXhllqtxjPPPAOVSoWPP/5Y8T3GC26+973vAQCeeOIJGAyGaX9+RERERJPB4IaIiOgy/fd//zdiY2Px9a9/HadPn8Ztt92Gd955Bw0NDXj++eexcuXKKT+20+nE2bNnAcxcxc1IISEhuPfee7F7925UV1fjqaeeQkJCAl555RVs3LgRqampk+rRM1knTpyARqPB/v37sX79etjtduzatQtf//rXR932pZdeQktLi1RxM1JQUBAiIyPR3t6uuDwxMRHBwcGoqKjA0NCQdPk777yDw4cPIy8vD3fffff0PzkiIiKiSWJwQ0REdJny8/NhtVqhVqvxne98By+88AJuvvlmaLXay37ssrIyDAwMwGw2IyYmZhpWOznz5s3DY489ht///vdYvnw5AKCqqmrG+t9YrVYUFRXBbrfj29/+NpKSknD8+HGsW7fO7e3feecdAMAzzzwDQRDcfrW2tiI8PFxxP0EQsGDBAjgcDpSUlAAAHA4Hvv/97wMAfvnLX0Kl4mESEREReZ7G0wsgIiLydU8//TReeuklvP3223jyySfx9NNP46qrrsKXvvQl3HLLLQgKCpryY0+mv01fXx9+8pOf4B//+Ac6OjqwatUqvPTSS0hLS5vS9y4uLsZrr72Gv/71r1JQk5OTg3vuuQfr16+f0mNeypkzZ2C327F161acPn0aNTU1qKioQEJCgtvbnz59Gnq9Hnfeeee4j+turHhOTg6OHj2K8+fPIzc3F6+88grOnz+PLVu2YMuWLdPyfIiIiIguF4MbIiKiy7R69WqsXr0azz//PP75z3/i1VdfxY4dO/DRRx8hODgYt956K770pS9h8+bNk67imGh/G6vVis2bN6OtrQ1PPvkkTCYTnnrqKdx88804ffo01Gr1hL5fS0sL3nzzTbz22ms4duwYACAyMhLf+MY3cM8990hVNzPF1d/m2muvxU9/+lOsX78et912G/Lz80cFUENDQ+jp6UFKSgpeeeWVSX8veZ+bwcFB/OQnP4FKpcIzzzxz2c+DiIiIaLowuCEiIpomQUFBuPvuu3H33XejpqYG//d//4f/+7//w2uvvYbXXnsNcXFxuOuuu/ClL31pwv1qJlpx87Of/Qzl5eU4ffq0NHEpLy8PCQkJOHny5LiBi8Viwb///W+89tpr+Oijj2C326HVanHTTTfhnnvuwQ033ACdTjfB/wuXx9U7Z9GiRVi5ciX+/Oc/44tf/CJuvPFGHD58GGFhYdJtdTodDAYDamtr0dfXh+Dg4El9r+zsbADDwc3vfvc71NXV4Z577pnRJtBEREREk8XN20RERDMgMTERjz/+OEpKSnDw4EE88MADGBgYwK9+9SssWrQI77///oQeZyIVN3a7Hb/73e/w0EMPITo6Gna7HXa7HdHR0QgJCUFtbe243+Omm27CnXfeiffffx8LFy7Es88+i/r6erz77ru47bbbZi20AS5W3Lie71133YUf/OAHOH/+PD73uc/B4XAobn/11VfDbrfjwQcfxMDAgOI6URSxe/du7N+/3+33clXcHD16FD//+c9hMBjw5JNPTvdTIiIiIrosDG6IiIhm2Jo1a/CHP/wBjY2NeOONN3DNNddMaKR2d3c3qqurodVqsWDBgjFvd/LkSXR1deGpp56CVqtVfPX29iI0NHTc7xMZGYlvfetbKCwsxIkTJ/DII4/AZDJN+nleLofDgcLCQsybN0/RTPiJJ57Arbfeih07duCRRx5R3OcXv/gFIiIi8PrrryM5ORnXXXcd/uM//gPXXnst4uPjsXnzZvT09Lj9fq7JUuXl5ejs7MSjjz46Zi8dIiIiIk/hVikiIqJZEhAQgDvvvPOSjXRdXNU2mZmZ41a9NDU1AQCOHDnitpeNq7JkLG+++eaE1jPTiouLYbFYRlUXCYKA1157DWvXrsULL7yArKwsfOMb3wAAZGVl4eTJk/jZz36GHTt2YNeuXdDpdDCbzVi5ciWuv/56bNy40e33EwQB2dnZKCgoQFRUFL73ve/N+HMkIiIimiwGN0RERF5q3bp1E6rMiY2NBQCEh4cjIyNjppc1Y3JycsZ8vkFBQdI2qpESExPx+9//fkrfMz8/f0r3IyIiIpotDG6IiIh83KJFi5CdnY3bb78d3//+9xEbG4umpibs2bMHX/ziF7Fu3TpPL3GUAwcO4N577wUAPP/885NuLOwpDz/8MAYGBnDq1ClPL4WIiIj8BIMbIiIiH6fVarFt2zZ85zvfwSOPPILe3l7MmzcPGzduRG5urqeX51Z5eTnKy8sBAL/61a98Jrh5/fXX0d3d7ellEBERkR8RxInUYBMRERERERER0azjVCkiIiIiIiIiIi/F4IaIiIiIiIiIyEsxuCEiIiIiIiIi8lIMboiIiIiIiIiIvBSDGyIiIiIiIiIiL8XghoiIiIiIiIjISzG4ISIiIiIiIiLyUgxuiIiIiIiIiIi8FIMbIiIiIiIiIiIvxeCGiIiIiIiIiMhLMbghIiIiIiIiIvJSDG6IiIiIiIiIiLwUgxsiIiIiIiIiIi/F4IaIiIiIiIiIyEsxuCEiIiIiIiIi8lIMboiIiIiIiIiIvBSDGyIiIiIiIiIiL/X/A8pUndNczvsuAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "cfspopcon.plotting.make_plot(\n", + " dataset,\n", + " plot_style,\n", + " points=points,\n", + " title=\"POPCON example\",\n", + " output_dir=None\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There's lots of functionality which you can explore (and extend!). For example, if you'd prefer to look at the results in terms of the auxillary heating power instead of the average electron temperature, you can use `cfspopcon.transform` to map the results onto new axes.\n", + "\n", + "Some of these features are a bit experimental. For instance, you can see here that by remapping we've shrunk the range of $Q$ in the accessible parameter space, since we apply a transformation on the masked array. Increasing the resolution of the analysis grid should reduce the difference when remapping." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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b775JgDJycn897//PeNY+vTpw9ChQwHYsWOHzbqHHnoIk8lEeHg4//vf/wgICGixrZiYGFasWGGz7IMPPiA5ORmAN998kxEjRjS7f9euXfn000+B2p5K//znP5vd1sfHx9qDYNGiRWRmZrYYmz1+/PFHZsyYQefOnfHw8CAoKIgLLriAd955B4PBYLNtQUEBXbp0QaVSMW3atCbbM5lMjB49GpVKxYABA6iurrauMxqNrFixgrvuuothw4bRqVMn9Ho94eHhXHrppXzxxRfN1kBpWNMHYN++fVx//fVERUXh5eVF7969+de//oXJZLLus2nTJqZNm0anTp3w9PSkX79+LFq0qNljNCwuXFZWxhNPPGGt0xIaGsq0adPYtm3bmTy8jWzatImbbrqJ2NhYPD09CQgIYMSIEbzyyiuUl5fb1faZ2Lp1K2+++SY9evRosmfc2fjkk08AuO666+jatWuj9f/4xz/w9fW11rc6ExUVFdYaNvfccw+BgYGNtnniiScAKC0tZfny5WcW/F+Kiop45JFHiI+Px9PTk06dOnH11Veza9euVu1vsVj47LPPuPzyy4mIiECv1xMWFsbEiRObfH3v2bPH+rret29fi23fcsstqFQqLrroIuuy1NRUNm7cCMDDDz+MTqdrtF/d45Kens6GDRtadR5CCCGE0zg5cSSEEG7hdD1uFEVRFi1aZN1m06ZNiqIoisFgUPz9/RVAGT9+fKuOZbFYlPj4eAVQevfu3Wj96XrcKIqiXH311dY6OHW2b99uje/5559vVSxNqavT061bt1bX1ZgwYYK1V0DD3kiKUt/jZty4cYrBYLD2XJo9e3ajduztcVNZWanMnDnTpqaOv7+/TV2MUaNGNeq5sG7dOmtNkbfeeqtRu08++aS110VycnKzMdcd79Q6QFdffbViNptbPN+ffvrJWlPp1Foe1113naIotTU/NBqNolKplICAAJtjPPbYY00+JnU9ZhYuXKj07NlTARS9Xm993QKKWq1W/vvf/7a4f1M9bsxms3Lfffc1quvUsB5Tz549lfT09CbbbsmZ9riprq5WevfurahUKmXdunWKoih297g5ePCg9Ty++uqrZrebNGmS9bV1JlatWmVtf/v27c1u17t3b5vXwZlIS0uzPoenPvd6vV75/vvvW+xxU1BQoFxwwQU2z/Gpr72pU6c2qvFT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tp+HH36YCy64oNl2Dh06xEUXXURWVpZ1mbe3t03Pp7o6RhUVFc224+fn1+RyrVbb4vqG2zSVLKrTuXPnVq3Lzc1tdruG6h7vioqKFs+rTnOPtz3279/P888/j6+vL2+//bbD22/4mFdWVuLv79/kdg3PraXnqbn2T/fY1K0/k7ah/rls6bnv0qVLk8sLCwupqakBWk4INnTqeUyfPp05c+ZQXl7Ot99+a9Ozpq4Xzo033tjovaqtHxchhBCivUniRgghHKyl4Synaliodvfu3YwePbpV++3Zs8f6c9++fZvc5vzzz2fdunWtjqWunZqaGg4cONBsuy059XxuvPHGVu3XmvM51dChQ7n66qv56quv+L//+z/rkKKzZTabAXjnnXf429/+dtbtpKens2bNGuv9TZs2YTab0Wg0TW4/e/ZssrKyiIuL49VXX+XCCy+0KRptNputiRWlmSm7z0V1j/djjz1mHfrW3u69914MBgPz588nKCio0dTjddOoK4piXefh4dHk9NJNiYqKsv58/PjxZhM3x48fB8Df3x9fX99Wx1/XflFREVVVVXh5ebXYfsN42lrd8wvw888/c9lll51xGz4+PkyfPp1PPvmETz75xJq4SUxMZO/evUDjYVJQf551590cZzwuQgghxNmQGjdCCOFEw4cPt37bW9dD43QURWH58uUA9O7du8VhJmeiYQ2L77777qzaiIqKss7U8t1337U60fDtt98CtReuw4YNa/XxXnzxRbRaLUlJSU3WwTgTdY+jPUNyTCYT119/PSUlJfTo0QMPDw82btzI888/3+T2mZmZ1ho9X3zxBTNnzrRJ2sCZJQLbUksXwQ3XNTeLz6kc8XjbKy0tDait/ePn59fo9tlnnwGQkZFhXbZo0aJWt99wpqeGM0Cdqm7dqTOOObr9M03G1j2XrX3uGwoJCbEmHO15jusSM7///rv1WHW/64MGDaJ///6N9ql7XHJzc8nLy2uyXbPZbJ0B72yS1EIIIUR7ksSNEEI4kU6n44477gBqa9K0pofM0qVLSU1NBWDOnDkOi2X48OHWOilvvfWWzfCllpw6Ve8999wD1F4Uf/LJJ6fdf8OGDdbzvvPOO60Xe63RvXt37rzzTgCeeeYZ69CMs1HX2+mHH3446zaeffZZtm7dire3N8uXL+eVV14B4IUXXmDjxo2Nts/MzLT+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PlyLFi3SunXrdNFFF8WpQiSyjz/+WDfccIMMw9BvfvOb8FoigBmc7Pzk+olEx4gbE2sZzldXVxe1vba2VpIYjgrTmTx5ss4//3xVVlZq/fr18S4HkHTya6rEdRXmVFBQoFmzZkmSlixZEudqkIhKS0s1depUVVRU6Nvf/ra++c1vRrRz/UQ8nez8PBGun0gUBDcm1rK46759+6K2txzv27dvzGoCTtXAgQMlSQcOHIhzJUDIya6ptbW1qqysVGZmJl88YDpcU9FZjh49qsmTJ2vv3r2aNWuW5s6d26YP10/Ey6mcnyfD9ROJgODGxFqGAL7//vtR21uOFxcXx6wm4FRVVFRIOjbnHYi3wYMHKzk5WWVlZSotLW3TzjUVZsY1FZ3B6/Vq2rRp2rJli6655ho99thjslgsbfpx/UQ8nOr5eTJcP5EICG5MbNSoUcrIyNDOnTu1YcOGNu0vvPCCJOnKK6+McWXAiZWVlWnNmjWS2t/OHoi11NRUTZgwQZL097//vU0711SYlWEY+sc//iGJayo6TmNjo2bMmKF33nlHU6ZM0XPPPSebzRa1L9dPxNrpnJ8nwvUTiYLgxsSSkpJ07733SpLuueee8NxhSfrd736njRs3auzYsfr85z8frxLRja1du1aLFi1SIBCIOL5nzx5dffXVqq2t1fTp09vdOhSIh29/+9uSQlvYb9++PXz87bff1iOPPCKPx6Nbb701XuWhGysrK9PDDz/cZkcer9eru+66S+vXr1d+fr6uueaaOFWIRBIIBPSVr3xFq1at0pgxY/TSSy8pKSnphK/h+olYOd3zk+snugOLYRhGvItA+xoaGjRu3DitX79eBQUFGjNmjPbu3av169crJydH69atU//+/eNdJrqh+fPna9asWcrPz9d5550nj8ejvXv36r333lNDQ4OGDRumVatWKTc3N96lIoH985//jNgS9J133pFhGLrwwgvDx+bMmaPLL788/Hz27NmaN2+e0tLSdOmll6qpqUnLly+XYRh64YUXdNVVV8XyIyCBnc75uWfPHhUWFsrlcmnkyJEqKChQWVmZ3n//fR05ckQej0eLFy/WqFGj4vFRkGDmzZun2bNnS5KuvvpqpaenR+03d+5cZWdnh59z/UQsnO75yfUT3QHbgZtcSkqKXnvtNf3P//yPnn32WS1atEg9evTQzJkzdf/9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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "cfspopcon.plotting.make_plot(dataset,\n", + " cfspopcon.read_plot_style(\"../../example_cases/SPARC_PRD/plot_remapped.yaml\"),\n", + " points=points,\n", + " title=\"POPCON example\",\n", + " output_dir=None,\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We often want to study individual points in detail.\n", + "\n", + "The simplest way to do this is to use `file_io.write_point_to_file` which writes the values at the points specified in the `points` dictionary to a JSON file." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "for point, point_params in points.items():\n", + " cfspopcon.file_io.write_point_to_file(dataset, point, point_params, output_dir=Path(\"../../example_cases/SPARC_PRD/output\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can dig into the output file `SPARC_PRD/outputs/max_Q.json`, or alternatively we can peek under the hood to understand what is going on. Let's pick the `max_Q` point which we defined in `input.yaml`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'maximize': 'Q',\n", + " 'where': {'P_auxillary': {'min': 0.0, 'max': 25.0, 'units': 'MW'},\n", + " 'greenwald_fraction': {'max': 0.9},\n", + " 'ratio_of_P_SOL_to_P_LH': {'min': 1.0},\n", + " 'P_fusion': {'max': 140.0, 'units': 'MW'}}}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "point_params = points[\"PRD\"]\n", + "\n", + "point_params" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first build a *mask* from the `where` key. This lets us hide parts of operational space which aren't physical (for example, if they have $P_{SOL}$ below the LH transition).\n", + "\n", + "This can be used with the `where` method of an `xarray.DataArray`." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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yly/pETl/fffh6WlJaZOnYrHjx9j8ODBcHFxwdKlS5WLwamjS5cuEKL0X+kDBw5ICY+IiIgqyK5du7Bq1apiSQoAODk5Yf78+XjzzTcxffp0Seu1SEpUACA4OBjBwcF4/PgxsrOz4eDgILUqIiKiKsdQun5u374NHx+fUs83btwYRkZGklexlTSYdvbs2crVaa2srJikEBERlVUFT08uLzVr1sT169dLPZ+SkqJRniApUdm6dSvc3d3Rrl07fPPNN7h//77kAIiIiKqiohYVTQ59EBAQgClTpiA/P7/Yuby8PEybNg1vvPGG5Poldf2cO3cOf//9NzZs2IAvv/wS4eHheP311xEcHIzevXvDyspKckBERERUecyaNQutWrVCo0aNEBYWBk9PTwghcOnSJXzzzTfIy8vDDz/8ILl+yUvo+/j4IDIyEteuXcORI0dQr149hIeHcwNBIiIidRhI10+dOnVw8uRJeHt7IyIiAr1790afPn0wZcoUeHt74/jx43Bzc5Ncv+TBtP9lbW0NS0tLmJmZ4dGjR9qokoiIyLAZyPRk4Nn6ar/++isePnyIq1evAgDc3d1hb2+vcd2SE5WUlBRs3LgRGzduxJUrV9C5c2fMnDkTb7/9tsZBEZFh4eJtRFVD9erV8eqrr2q1TkmJStu2bXHmzBn4+voiJCQEgwYNQu3atbUaGBERkSEzlOnJ5U1SotKtWzd8//338Pb21nY8REREVYMBdf2UJ0mJypw5c7QdBxEREVExkseo3Lx5E3v27EFqamqxudOLFlXcZmdERESVkUwIyF6wjYw691cFkhKVw4cPo1evXmjQoAEuX76Mxo0b4/r16xBCoEWLFtqOkYiIyPCw60ctktZRiYiIwPjx45GQkAALCwts374daWlp6Ny5M955p+zbuRMRERGVRFKicunSJQwZMgQAYGJigidPnsDGxgazZs3CvHnztBogERGRITKUJfTLm6RExdraWjkuxdnZGcnJycpz3PeHiIhIDQayMm15k7yOyrFjx+Dl5YU333wT48aNQ0JCAnbs2IG2bdtqO0YiIiKDw3VU1CMpUVm0aBGys7MBADNnzkR2dja2bNmCRo0accYPERERaY2kRKVBgwbKn62trbFy5coSr9u0aRN69eoFa2tradEREREZKs76UYvk3ZPV8eGHH+Lu3bvl+QgiIqJKiYNp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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mask = cfspopcon.point_selection.build_mask_from_dict(dataset, point_params)\n", + "\n", + "dataset.Q.where(mask).plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's find the point here with the highest value of Q. This gives us the indices of the corresponding point." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'dim_average_electron_density': \n", + " array(24),\n", + " 'dim_average_electron_temp': \n", + " array(8)}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "point_indices = cfspopcon.point_selection.find_coords_of_maximum(dataset.Q, mask=mask)\n", + "\n", + "point_indices" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use those indices to select a point of the array, see the coordinates and value at that point." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.DataArray 'Q' ()>\n",
+       "<Quantity(11.40076545330472, 'dimensionless')>\n",
+       "Coordinates:\n",
+       "    dim_average_electron_density  float64 25.0\n",
+       "    dim_average_electron_temp     float64 9.138
" + ], + "text/plain": [ + "\n", + "\n", + "Coordinates:\n", + " dim_average_electron_density float64 25.0\n", + " dim_average_electron_temp float64 9.138" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset.Q.isel(point_indices)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also select this point for all of the variables defined in our dataset, which lets us look at the values of *all* of the different fields at that point (you might need to click the arrow next to \"data variables\" to see these)." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:                               (dim_species: 3, dim_rho: 50)\n",
+       "Coordinates:\n",
+       "  * dim_species                           (dim_species) object Impurity.Tungs...\n",
+       "    dim_average_electron_density          float64 25.0\n",
+       "    dim_average_electron_temp             float64 9.138\n",
+       "Dimensions without coordinates: dim_rho\n",
+       "Data variables: (12/115)\n",
+       "    major_radius                          float64 [m] 1.85\n",
+       "    magnetic_field_on_axis                float64 [T] 12.2\n",
+       "    inverse_aspect_ratio                  float64 [] 0.3081\n",
+       "    areal_elongation                      float64 [] 1.75\n",
+       "    elongation_ratio_sep_to_areal         float64 [] 1.125\n",
+       "    triangularity_psi95                   float64 [] 0.3\n",
+       "    ...                                    ...\n",
+       "    core_radiated_power_fraction          float64 [] 0.1866\n",
+       "    nu_star                               float64 [] 0.02375\n",
+       "    rho_star                              float64 [] 0.002213\n",
+       "    fusion_triple_product                 float64 [1e10 m^-3·keV·s] 45.28\n",
+       "    peak_pressure                         float64 [Pa] 2.469e+06\n",
+       "    current_relaxation_time               float64 [s] 16.36
" + ], + "text/plain": [ + "\n", + "Dimensions: (dim_species: 3, dim_rho: 50)\n", + "Coordinates:\n", + " * dim_species (dim_species) object Impurity.Tungs...\n", + " dim_average_electron_density float64 25.0\n", + " dim_average_electron_temp float64 9.138\n", + "Dimensions without coordinates: dim_rho\n", + "Data variables: (12/115)\n", + " major_radius float64 [m] 1.85\n", + " magnetic_field_on_axis float64 [T] 12.2\n", + " inverse_aspect_ratio float64 [] 0.3081\n", + " areal_elongation float64 [] 1.75\n", + " elongation_ratio_sep_to_areal float64 [] 1.125\n", + " triangularity_psi95 float64 [] 0.3\n", + " ... ...\n", + " core_radiated_power_fraction float64 [] 0.1866\n", + " nu_star float64 [] 0.02375\n", + " rho_star float64 [] 0.002213\n", + " fusion_triple_product float64 [1e10 m^-3·keV·s] 45.28\n", + " peak_pressure float64 [Pa] 2.469e+06\n", + " current_relaxation_time float64 [s] 16.36" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "point = dataset.isel(point_indices)\n", + "\n", + "point" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to look at a particular value, we can pull the single-element `DataArray` out of the `Dataset`.\n", + "\n", + "For instance, we can return how much power is crossing the separatrix. By default, this is stored in megawatts, but we can easily convert it to other compatible units such as watts." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.DataArray 'P_sol' ()>\n",
+       "<Quantity(25591250.26660787, 'watt')>\n",
+       "Coordinates:\n",
+       "    dim_average_electron_density  float64 25.0\n",
+       "    dim_average_electron_temp     float64 9.138
" + ], + "text/plain": [ + "\n", + "\n", + "Coordinates:\n", + " dim_average_electron_density float64 25.0\n", + " dim_average_electron_temp float64 9.138" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "point.P_sol.pint.to(ureg.watt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we selected the point, we selected a single average electron density and temperature, but left the rest of the structure of the data unchanged. If we'd defined more than 2 variables in our `grid` section of our `input.yaml`, we could look at how the point (in this case maximum Q) varies as a function of the third parameter (which could be something like the confinement time scalar $H$). Even for our simple 2D POPCON, there's still some 1D data at our point: namely, the assumed temperature and density profiles." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "point.electron_temp_profile.pint.to(ureg.keV).plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's the basics for using the POPCON library.\n", + "\n", + "You can perform the analysis in this notebook using the command line tool. If you wanted to run this exact case from a terminal at the top-level of this repository, the command would be:\n", + "```\n", + "poetry run popcon example_cases/SPARC_PRD -p example_cases/SPARC_PRD/plot_popcon.yaml -p example_cases/SPARC_PRD/plot_remapped.yaml --debug --show\n", + "```\n", + "where `example_cases/SPARC_PRD` is the path to the `input.yaml` file and `example_cases/SPARC_PRD/plot_popcon.yaml` & `example_cases/SPARC_PRD/plot_remapped.yaml` are the two plotting styles that we used.\n", + "\n", + "Feel free to try things out and change the `input.yaml` file. At some point, you'll probably want to dig into the formulas and algorithms and start implementing your own. For this, see the other notebooks in this folder." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/doc_sources/physics_glossary.rst b/docs/doc_sources/physics_glossary.rst new file mode 100644 index 00000000..4ba0db31 --- /dev/null +++ b/docs/doc_sources/physics_glossary.rst @@ -0,0 +1,373 @@ +.. _physics_glossary: + +Physics Glossary +================== + +.. glossary:: + :sorted: + + Q + Fusion power thermal gain factor. + + P_fusion + Total power generated by fusion integrated over the plasma volume. For DT fusion, this is the sum of the power going to the alpha particles and to the neutrons. + + P_neutron + Fusion power released as neutrons integrated over the plasma volume. + + P_alpha + Fusion power released as alpha particles integrated over the plasma volume. + + P_external + External heating absorbed by the plasma (ohmic plus auxillary) integrated over the plasma volume. + + P_launched + External heating supplied to the plasma (entering the volume, but not necessarily absorbed — ohmic plus auxillary) integrated over the plasma volume. + + fraction_of_external_power_coupled + Fraction of supplied external heating absorbed by the plasma: :math:`f_{coupled}=P_{external} / P_{launched}`. + + P_radiation + Power radiated from the confined region due to Bremmsstrahlung, synchrotron and impurity excitation-relaxation processes. + + P_radiated_by_core_radiator + Power radiated from the confined region due to the injection of an :term:`extrinsic` core radiator. + + extrinsic impurity + An impurity which has intentionally been injected into the plasma to enhance radiative power dissipation. + + intrinsic impurity + An impurity which is assumed to be already in the plasma (without being injected by us). + + P_SOL + power_crossing_separatrix + Power crossing the separatrix and entering the scrape-off-layer. + + SOL_power_loss_fraction + Fraction of power entering a scrape-off-layer flux tube which is lost (radiated or cross-field transported) before reaching the divertor target. + + SOL_momentum_loss_function + Fraction of momentum entering a scrape-off-layer flux tube which is lost before reaching the divertor target. + + kappa_e0 + Electron heat conductivity constant, such that :math:`q_{e,\parallel,cond}=\kappa_{e0}T_{e}^{5/2}\nabla_\parallel T_e`. + + toroidal_flux_expansion + Ratio of the divertor target major radius to the :term:`upstream` major radius for the two point model :math:`R_{target} / R_{upstream}`. + + nesep_over_nebar + Ratio of the separatrix electron density to the volume-averaged electron density :math:`n_{e,sep} / \bar n_e`. + + parallel_connection_length + Length along a field-line from :term:`upstream` to the divertor target. + + upstream + The point where heat enters the flux-tube being considered for the two-point-model. Usually 'upstream' means the outboard-midplane separatrix. + + upstream_electron_temp + The :term:`upstream` electron temperature. + + target_electron_density + The :term:`target` electron density. + + target + The divertor target. Although there are several divertor targets, we usually perform the two-point-model analysis for the low-field-side (outboard) divertor target. + + target_electron_temp + The :term:`target` electron temperature. + + target_electron_flux + The rate of electrons per unit area reaching the :term:`target`. + + target_q_parallel + The parallel heat flux density at the :term:`target`. + + neutron_power_flux_to_walls + Neutron power per unit area to the wall. + + neutron_rate + Number of neutrons produced per second. + + B_t_out_mid + Toroidal magnetic field at outboard midplane separatrix + + B_pol_omp + B_pol_out_mid + Poloidal magnetic field at outboard midplane separatrix + + fieldline_pitch_at_omp + The :term:`upstream` pitch of the magnetic field :math:`B_{tot} / B_{pol}`, used to convert from poloidal to parallel heat flux density. + + lambda_q_scaling + A :class:`~cfspopcon.named_options.LambdaQScaling` indicating which scaling to use for :term:`lambda_q`. + + lambda_q + The :term:`upstream` parallel heat flux density (:math:`q_\parallel`) near-SOL cross-field decay length. + + lambda_q_factor + A scaling factor :math:`C` which can be used to increase or decrease :math:`\lambda_q=C \lambda_{q,scaling}`. + + q_perp + The :term:`upstream` poloidal heat flux density. + + q_parallel + The :term:`upstream` parallel heat flux density. + + PBpRnSq + :math:`P_{SOL}B_{pol}/(R n_{sep}^2)`, a metric used to estimate how challenging heat exhaust will be. This metric is approximately :math:`q_\parallel/n_{e,sep}^2`, which in the Lengyel model gives the impurity concentration required for detachment. + + PB_over_R + :math:`P_{SOL}B_0/R`, a metric used to estimate how challenging heat exhaust will be. + + atomic_data + Dictionary mapping :class:`~cfspopcon.named_options.Impurity` to datasets giving coronal and non-coronal :math:`L_z` radiated power factors and :math:`\langle Z \rangle` mean charge state curves from `radas `_. + + impurities + A :class:`xarray.DataArray` giving the concentration of non-fuel species relative to the electron density. + This array must have a dimension `dim_species` with :class:`~cfspopcon.named_options.Impurity` coordinates. + There are several functions in the :mod:`cfspopcon.helpers` module to help you make and extend the `impurities` array. + + impurity_species + An :class:`~cfspopcon.named_options.Impurity` indicating which non-fuel atomic species we are performing a calculation for. + + impurity_concentration + Concentration of a non-fuel atomic species relative to the electron density :math:`c_Z = n_Z / n_e`. + + impurity_charge_state + The mean charge state of a non-fuel species. + + greenwald_fraction + Ratio of the average electron density to the Greenwald density limit :math:`f_{G}=\bar n_e / n_G`. + + tau_i + Impurity residence/recycling time, which leads to a non-coronal enhancement of radiated power. + + radiated_power_method + A :class:`~cfspopcon.named_options.RadiationMethod` indicating how we should calculate the power radiated from the confined region. + + dilution + Fuel-species concentration as a fraction of the electron density :math:`n_{DT}/n_e`. + + core_radiator + An :class:`~cfspopcon.named_options.Impurity` indicating which :term:`extrinsic` core radiator species should be injected into the confined region to enhance the core radiated power. + + core_radiator_charge_state + Charge state of the :term:`extrinsic` core radiator. + + core_radiator_concentration + Concentration of the :term:`extrinsic` core radiator required to achieve the desired core radiated power fraction, relative to the electron density :math:`c_{core} = n_{core}/n_e`. + + electron_density_profile + A 1D profile of the electron density as a function of :math:`\rho_{pol}`. + + electron_temp_profile + A 1D profile of the electron temperature as a function of :math:`\rho_{pol}`. + + ion_temp_profile + A 1D profile of the ion temperature as a function of :math:`\rho_{pol}`. + + profile_form + A :class:`~cfspopcon.named_options.ProfileForm` indicating which sort of assumed profile shape we should use. + + z_effective + The "effective charge" of the ions, defined as :math:`\sum_j Z_j^2 n_j / n_e`. + + rho + The square-root of the normalized poloidal flux :math:`\rho_{pol}=\sqrt{\psi_N}`, used as a flux surface label. + + plasma_volume + Plasma volume inside the last-closed-flux-surface. + + normalized_inverse_temp_scale_length + Inverse normalized electron temperature gradient scale length :math:`a / ( T_e / \nabla T_e )`, which defines the shape of the :class:`~cfspopcon.named_options.ProfileForm.prf` profiles. + + inverse_aspect_ratio + Ratio of minor to major radius :math:`\epsilon= a / R_0`. + + confinement_time_scalar + Usually denoted :math:`H`, scalar applied to the energy confinement time calculated from a scaling such that :math:`\tau_e = H \tau_{e,scaling}`. + + plasma_current + Current carried by the plasma :math:`I_p`. + + magnetic_field_on_axis + Magnetic field at the geometric magnetic axis :math:`B_0 = BR / R0`. + + average_electron_density + Volume-averaged electron density in the confined region :math:`\bar n_e`. + + average_electron_temp + Volume-averaged electron temperature in the confined region :math:`\bar T_e`. + + summed_impurity_density + Density of non-fuel ions. + + average_ion_density + Volume-averaged ion density in the confined region :math:`\bar n_i`. + + average_ion_temp + Volume-averaged ion temperature in the confined region :math:`\bar T_i`. + + average_total_pressure + Sum of electron and ion pressures. + + areal_elongation + Elongation of the confined region computed using the poloidal area inside the last-closed-flux-surface :math:`\kappa_A = S_{pol} / (\pi a^2)`. + + beta_toroidal + Ratio of plasma pressure to magnetic pressure provided by the toroidal magnetic field. + + beta_poloidal + Ratio of plasma pressure to magnetic pressure provided by the poloidal magnetic field. + + beta_total + Ratio of plasma pressure to magnetic pressure provided by the total magnetic field. + + beta_N + Ratio of plasma pressure to magnetic pressure provided by the total magnetic field, normalized to :math:`I_MA / a B_0`. + + separatrix_elongation + Elongation of the last-closed-flux-surface :math:`(Z_{max,LCFS} - Z_{min,LCFS}) / (R_{max,LCFS} - R_{min,LCFS})`. + + elongation_ratio_sep_to_areal + Ratio of separatrix elongation to areal elongation :math:`\kappa_{sep}/\kappa_A`. + + triangularity_ratio_sep_to_psi95 + Ratio of separatrix triangularity to triangularity at the :math:`psi_N=0.95` surface :math:`\delta_{sep}/\delta_{95}.` + + f_shaping + Shaping factor used to compute :math:`q_*`. + + fuel_average_mass_number + Average mass of fuel ions, with the average weighted by the relative concentration of each species. + + surface_area + Area of the last-closed-flux-surface, i.e. the surface defined by toroidally revolving the poloidal last-closed-flux-surface. + + triangularity_psi95 + Usually denoted :math:`\delta_{95}`, average of upper and lower triangularity at the :math:`\psi_N=0.95` surface. + + spitzer_resistivity + Plasma loop collisional resistivity. + + neoclassical_loop_resistivity + Plasma loop neoclassical resistivity. + + inductive_plasma_current + Plasma current driven by the central solenoid (i.e. excluding the contribution of the bootstrap current). + + electron_density_peaking_offset + Scalar offset of the electron density peaking relative to the density peaking scaling. + + ion_density_peaking_offset + Scalar offset of the ion density peaking relative to the density peaking scaling. + + ion_density_peaking + Ratio of the peak ion density to the volume-averaged ion density. + + electron_density_peaking + Ratio of the peak ion density to the volume-averaged electron density. + + temperature_peaking + Ratio of the peak (electron or ion) temperature to the volume-averaged temperature. + + bootstrap_fraction + Fraction of the plasma current due to the bootstrap current. + + effective_collisionality + Estimate of collisionality used for computing the expected density peaking. + + nu_n + Either the :term:`ion_density_peaking` or the :term:`electron_density_peaking` + + peak_ion_temp + Peak ion temperature + + peak_fuel_ion_density + Peak fuel ion density (i.e. product of fuel dilution, ion peaking factor and average electron density). + + peak_electron_temp + Peak electron temperature + + peak_electron_density + Peak electron density + + current_relaxation_time + Time constant for the radial current diffusion. + + trapped_particle_fraction + Global average of the fraction of trapped electrons used in the calculation of global plasma resistivity. + + minimum_core_radiated_fraction + Minimum fraction of :math:`P_{in}` which should be radiated from the confined region, below which + we will inject an additional :term:`extrinsic` core radiator to increase + the radiated power up to this value. + + radiated_power_scalar + An enhancement factor :math:`C` to modify the radiated power :math:`P_{rad} = C P_{rad,calculated}`. + + zeff_change_from_core_rad + Change in :term:`z_effective` due to the injection of a core radiator. + + dilution_change_from_core_rad + Change in :term:`dilution` due to the injection of a core radiator. + + fuel_ion_density_profile + A 1D profile of the fuel ion density as a function of :math:`\rho_{pol}`. + + separatrix_triangularity + Separatrix triangularity (average of upper and lower triangularity). + + plasma_stored_energy + Thermal energy in the plasma. + + q_star + Analytical approximation of safety factor at :math:`\rho=0.95`. + + loop_voltage + inductive loop voltage + + energy_confinement_scaling + tau_e_scaling + A :class:`~cfspopcon.named_options.ConfinementScaling` indicating which :math:`\tau_e` energy confinement scaling should be used. + + energy_confinement_time + A characteristic time which gives the rate at which the plasma loses energy. In steady-state, :math:`\tau_e=W_p / P_in`. + + P_in + Total input power to the plasma. Sum of ohmic, auxillary and alpha power. + + fraction_of_P_SOL_to_divertor + fraction of the total power going towards the :term:`target`. + + P_LH_thresh + Power required to cross the L-H transition. + + SOC_LOC_ratio + Ratio of the energy confinement time from the chosen saturated ohmic confinement (SOC) scaling and the chosen linear ohmic confinement (LOC) scaling. + + P_LI_thresh + Power required to cross the L-I transition. + + P_ohmic + P_Ohmic + Power deposited in the plasma due to resistive ohmic heating. + + major_radius + The major radius of the geometric magnetic axis. + + minor_radius + Horizontal minor radius of the plasma :math:`(R_{max,LCFS}-R_{min,LCFS})/2` + + vertical_minor_radius + Vertical minor radius of the plasma :math:`(Z_{max,LCFS}-Z_{min,LCFS})/2` + + product_of_magnetic_field_and_radius + Product of the major radius and the (vacuum) magnetic field :math:`B \times R`. + + fusion_reaction + A :class:`~cfspopcon.named_options.ReactionType` indicating which fusion reaction should be used. + + heavier_fuel_species_fraction + Fraction of fuel ions which are the heavier species. i.e. for DT fusion, this is :math:`f_T = n_T/(n_T+n_D)`. + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..dab35578 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,27 @@ +.. cfspopcon documentation master file, created by + sphinx-quickstart on Mon Nov 14 16:09:52 2022. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +##################################### +Welcome to cfspopcon's documentation! +##################################### + +POPCONs (Plasma OPerating CONtours) is a tool developed to explore the performance and constraints of tokamak designs based on 0D scaling laws, model plasma kinetic profiles, and physics assumptions on the properties and behavior of the core plasma. + +POPCONs was initially described in :cite:`prd` where it was applied to the design of the SPARC tokamak. + +To start generating your fist plasma operating contours with cfspopcon, head over to the :ref:`Getting Started ` guide. + +A usefull resource is our :ref:`Physics Glossary ` which lists all input and output variables, including definitions and citations for formulas where relevant. + +If you are interested in how to setup a development environment to make changes to cfspopcon, we suggest you checkout the :ref:`Developer's Guide `. + +.. toctree:: + :maxdepth: 1 + + doc_sources/Usage + doc_sources/physics_glossary + doc_sources/dev_guide + doc_sources/api + doc_sources/bib diff --git a/docs/refs.bib b/docs/refs.bib new file mode 100644 index 00000000..b9723c26 --- /dev/null +++ b/docs/refs.bib @@ -0,0 +1,438 @@ +@article{eich_scaling_2013, + title = {Scaling of the tokamak near the scrape-off layer {H}-mode power width and implications for {ITER}}, + volume = {53}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/53/9/093031}, + language = {en}, + number = {9}, + journal = {Nuclear Fusion}, + author = {Eich, T. and Leonard, A. W. and Pitts, R. A. and Fundamenski, W. and Goldston, R. J. and Gray, T. K. and Herrmann, A. and Kirk, A. and Kallenbach, A. and Kardaun, O. and Kukushkin, A. S. and LaBombard, B. and Maingi, R. and Makowski, M. A. and Scarabosio, A. and Sieglin, B. and Terry, J. and Thornton, A. and Team, ASDEX Upgrade and Contributors, JET EFDA}, + month = aug, + year = {2013}, + note = {Publisher: IOP Publishing and International Atomic Energy Agency}, + pages = {093031}, +} + +@article{Bonoli, + title = {Observation of Efficient Lower Hybrid Current Drive at High Density in Diverted Plasmas on the Alcator C-Mod Tokamak}, + author = {Baek, S. G. and Wallace, G. M. and Bonoli, P. T. and Brunner, D. and Faust, I. C. and Hubbard, A. E. and Hughes, J. W. and LaBombard, B. and Parker, R. R. and Porkolab, M. and Shiraiwa, S. and Wukitch, S.}, + journal = {Phys. Rev. Lett.}, + volume = {121}, + issue = {5}, + pages = {055001}, + numpages = {6}, + year = {2018}, + month = {Aug}, + publisher = {American Physical Society}, + doi = {10.1103/PhysRevLett.121.055001}, +} + +@article{prd, + title={Overview of the SPARC tokamak}, + volume={86}, + DOI={10.1017/S0022377820001257}, + number={5}, + journal={Journal of Plasma Physics}, + publisher={Cambridge University Press}, + author={Creely, A. J. and Greenwald, M. J. and Ballinger, S. B. and Brunner, D. and Canik, J. and Doody, J. and Fülöp, T. and Garnier, D. T. and Granetz, R. and Gray, T. K. and et al.}, + year={2020}, + pages={865860502} +} + +@article{suckewer_radiation_1981, + title = {Radiation losses in {PLT} during neutral-beam and {ICRF} heating experiments}, + volume = {21}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/21/8/007}, + abstract = {Radiation and charge-exchange losses in the PLT tokamak are compared for discharges with Ohmic heating only (OH), and with additional heating by neutral beams (NB) or RF in the ion cyclotron frequency range (ICRF). Spectroscopic, bolometric and soft-X-ray diagnostics were used. The effects of discharge cleaning, vacuum wall gettering, and rate of gas inlet on radiation losses from OH plasmas and the correlation between radiation from plasma core and edge temperatures are discussed. – For discharges with neutral-beam injection the radiation dependence on type of injection (e.g. co-injection versus counter- and co- plus counter-injection) was investigated. Radial profiles of radiation loss were compared with profiles of power deposition. Although total radiation was in the range of 30–60\% of total input power into relatively clean plasma, nevertheless only 10–20\% of the total central input power to ions and electrons was radiated from the plasma core. The radiated power was increased mainly by increased influx of impurities, however, a fraction of this radiation was due to the change in charge-state distribution associated with charge-exchange recombination. – During ICRF heating radiation losses were higher than or comparable to those experienced during co- plus counter-injection at similar power levels. At these low power levels of ICRF heating the total radiated power was ∼ 80\% of auxiliary-heating power. Radiation losses changed somewhat less rapidly than linearly with ICRF power input up to the maximum available at the time of these measurements (0.65 MW).}, + language = {en}, + number = {8}, + journal = {Nuclear Fusion}, + author = {Suckewer, S. and Hinnov, E. and Hwang, D. and Schivell, J. and Schmidt, G. L. and Bol, K. and Bretz, N. and Colestock, P. L. and Dimock, D. and Eubank, H. P. and Goldston, R. J. and Hawryluk, R. J. and Hosea, J. C. and Hsuan, H. and Johnson, D. W. and Meservey, E. and McNeill, D.}, + month = aug, + year = {1981}, + pages = {981}, +} + +@article{brunner_2018_heat_flux, + title = {High-resolution heat flux width measurements at reactor-level magnetic fields and observation of a unified width scaling across confinement regimes in the Alcator C-Mod tokamak}, + volume = {58}, + pages = {094002}, + doi = {10.1088/1741-4326/aad0d6}, + journal = {Nuclear Fusion}, + year = {2018}, + author = {Brunner, D. and LaBombard, B. and Kuang, A. Q. and Terry, J. L.} +} + +@article{stangeby_2018, + title = {Basic physical processes and reduced models for plasma detachment}, + volume = {60}, + doi = {10.1088/1361-6587/aaacf6}, + journal = {Plasma Physics and Controlled Fusion}, + author = {Stangeby, P.}, + year = {2018}, + pages = {044022}, +} + +@article{bosch_improved_1992, + title = {Improved formulas for fusion cross-sections and thermal reactivities}, + volume = {32}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/32/4/I07}, + language = {en}, + number = {4}, + journal = {Nuclear Fusion}, + author = {Bosch, H.-S. and Hale, G. M.}, + month = apr, + year = {1992}, + pages = {611}, +} + + +@techreport{langenbrunner_temperature_2016, + title = {Temperature derivatives for fusion reactivity of {D}-{D} and {D}-{T}}, + abstract = {Deuterium-tritium (D-T) and deuterium-deuterium (D-D) fusion reaction rates are observable using leakage gamma flux. A direct measurement of γ-rays with equipment that exhibits fast temporal response could be used to infer temperature, if the detector signal is amenable for taking the logarithmic time-derivative, alpha. We consider the temperature dependence for fusion cross section reactivity.}, + language = {English}, + number = {LA-UR-16-29065}, + institution = {Los Alamos National Lab. (LANL), Los Alamos, NM (United States)}, + author = {Langenbrunner, James R. and Makaruk, Hanna Ewa}, + month = nov, + year = {2016}, + doi = {10.2172/1334107}, +} + +@article{nevins_thermonuclear_2000, + title = {The thermonuclear fusion rate coefficient for p-¹¹{B} reactions}, + volume = {40}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/40/4/310}, + language = {en}, + number = {4}, + journal = {Nuclear Fusion}, + author = {Nevins, W.M and Swain, R}, + month = apr, + year = {2000}, + pages = {865--872}, +} + +@article{sikora_new_2016, + title = {A {New} {Evaluation} of the ¹¹{B}(p,α)αα {Reaction} {Rates}}, + volume = {35}, + issn = {1572-9591}, + doi = {10.1007/s10894-016-0069-y}, + language = {en}, + number = {3}, + journal = {Journal of Fusion Energy}, + author = {Sikora, M. H. and Weller, H. R.}, + month = jun, + year = {2016}, + pages = {538--543}, +} + +@book{richardson_nrl_2019, + title = {{NRL} {Plasma} {Formulary}}, + language = {en}, + publisher = {Naval Research Lab.}, + author = {Richardson, A S}, + year = {2019}, + url = {https://www.nrl.navy.mil/Portals/38/PDF%20Files/NRL_Plasma_Formulary_2019.pdf} +} + +@article{putvinski_fusion_2019, + title = {Fusion reactivity of the {pB11} plasma revisited}, + volume = {59}, + issn = {0029-5515}, + doi = {10.1088/1741-4326/ab1a60}, + language = {en}, + number = {7}, + journal = {Nuclear Fusion}, + author = {Putvinski, S. V. and Ryutov, D. D. and Yushmanov, P. N.}, + month = jun, + year = {2019}, + note = {Publisher: IOP Publishing}, + pages = {076018}, +} + +@techreport{macfarlane_bucky-1_1995, + title = {{BUCKY}-1 - {A} 1-{D} {Radiation} {Hydrodynamics} {Code} for {Simulating} {Inertial} {Confinement} {Fusion} {High} {Energy} {Density} {Plasmas}}, + url = {https://fti.neep.wisc.edu/fti.neep.wisc.edu/pdf/fdm984.pdf}, + number = {UWFDM-984}, + institution = {University of Wisconsin Fusion Technology Institute}, + author = {MacFarlane, J.J. and Moses, G.A. and Peterson, R.R.}, + month = aug, + year = {1995}, +} + +@article{gibson_impurity_1978, + title = {Impurity behaviour in real and simulated tokamak plasmas}, + volume = {76-77}, + issn = {0022-3115}, + doi = {10.1016/0022-3115(78)90122-8}, + language = {en}, + journal = {Journal of Nuclear Materials}, + author = {Gibson, A.}, + month = sep, + year = {1978}, + pages = {92--102}, +} + +@techreport{post_steady_1977, + title = {Steady state radiative cooling rates for low-density high-temperature plasmas}, + language = {English}, + number = {PPPL-1352}, + institution = {Princeton Univ., NJ (USA). Plasma Physics Lab.}, + author = {Post, D. E. and Jensen, R. V. and Tarter, C. B. and Grasberger, W. H. and Lokke, W. A.}, + month = jul, + year = {1977}, + doi = {10.2172/7297293}, +} + +@article{uckan_iter_1991, + title = {{ITER} {Confinement} {Capability}}, + volume = {19}, + issn = {0748-1896}, + doi = {10.13182/FST91-A29553}, + number = {3P2B}, + journal = {Fusion Technology}, + author = {Uckan, N. A. and Hogan, J. T.}, + month = may, + year = {1991}, + pages = {1499--1503}, +} + +@article{editors_iter_1999, + title = {The {ITER} {Physics} {Basis} - {Chapter} 1: {Overview} and summary}, + volume = {39}, + issn = {0029-5515}, + shorttitle = {Chapter 1}, + doi = {10.1088/0029-5515/39/12/301}, + language = {en}, + number = {12}, + journal = {Nuclear Fusion}, + author = {Editors, ITER Physics Basis and Chairs, ITER Physics Expert Group and {Co-Chairs} and Team, ITER Joint Central and Unit, Physics Integration}, + month = dec, + year = {1999}, + pages = {2137}, +} + +@article{angioni_particle_2009, + title = {Particle transport in tokamak plasmas, theory and experiment}, + volume = {51}, + issn = {0741-3335}, + doi = {10.1088/0741-3335/51/12/124017}, + language = {en}, + number = {12}, + journal = {Plasma Physics and Controlled Fusion}, + author = {Angioni, C. and Fable, E. and Greenwald, M. and Maslov, M. and Peeters, A. G. and Takenaga, H. and Weisen, H.}, + month = nov, + year = {2009}, + pages = {124017}, +} + +@article{martin_power_2008, + title = {Power requirement for accessing the {H}-mode in {ITER}}, + volume = {123}, + issn = {1742-6596}, + doi = {10.1088/1742-6596/123/1/012033}, + language = {en}, + number = {1}, + journal = {Journal of Physics: Conference Series}, + author = {Martin, Y. R. and Takizuka, T. and Group), (andthe ITPA CDBM H.-mode Threshold Database Working}, + month = jul, + year = {2008}, + pages = {012033}, +} + +@article{ryter_i-mode_2016, + title = {I-mode studies at {ASDEX} {Upgrade}: {L}-{I} and {I}-{H} transitions, pedestal and confinement properties}, + volume = {57}, + issn = {0029-5515}, + shorttitle = {I-mode studies at {ASDEX} {Upgrade}}, + doi = {10.1088/0029-5515/57/1/016004}, + language = {en}, + number = {1}, + journal = {Nuclear Fusion}, + author = {Ryter, F. and Fischer, R. and Fuchs, J. C. and Happel, T. and McDermott, R. M. and Viezzer, E. and Wolfrum, E. and Orte, L. Barrera and Bernert, M. and Burckhart, A. and Graça, S. da and Kurzan, B. and McCarthy, P. and Pütterich, T. and Suttrop, W. and Willensdorfer, M. and Team, the ASDEX Upgrade}, + month = sep, + year = {2016}, + note = {Publisher: IOP Publishing}, + pages = {016004}, +} + +@article{Ryter_2014, +doi = {10.1088/0029-5515/54/8/083003}, +url = {https://dx.doi.org/10.1088/0029-5515/54/8/083003}, +year = {2014}, +month = {may}, +publisher = {IOP Publishing}, +volume = {54}, +number = {8}, +pages = {083003}, +author = {F. Ryter and L. Barrera Orte and B. Kurzan and R.M. McDermott and G. Tardini and E. Viezzer and M. Bernert and R. Fischer and The ASDEX Upgrade Team}, +title = {Experimental evidence for the key role of the ion heat channel in the physics of the L–H transition}, +journal = {Nuclear Fusion}, +} + +@article{hubbard_threshold_2012, + title = {Threshold conditions for transitions to {I}-mode and {H}-mode with unfavourable ion grad {B} drift direction}, + volume = {52}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/52/11/114009}, + language = {en}, + number = {11}, + journal = {Nuclear Fusion}, + author = {Hubbard, A. E. and Whyte, D. G. and Churchill, R. M. and Dominguez, A. and Hughes, J. W. and Ma, Y. and Marmar, E. S. and Lin, Y. and Reinke, M. L. and White, A. E.}, + month = oct, + year = {2012}, + note = {Publisher: IOP Publishing and International Atomic Energy Agency}, + pages = {114009}, +} + +@article{angioni_scaling_2007, + title = {Scaling of density peaking in {H}-mode plasmas based on a combined database of {AUG} and {JET} observations}, + volume = {47}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/47/9/033}, + language = {en}, + number = {9}, + journal = {Nuclear Fusion}, + author = {Angioni, C. and Weisen, H. and Kardaun, O. J. W. F. and Maslov, M. and Zabolotsky, A. and Fuchs, C. and Garzotti, L. and Giroud, C. and Kurzan, B. and Mantica, P. and Peeters, A. G. and Stober, J. and Team, the ASDEX Upgrade and Workprogramme, contributors to the EFDA-JET}, + month = aug, + year = {2007}, + pages = {1326}, +} + +@book{wesson_tokamaks_2004, + address = {Oxford, New York}, + edition = {3rd}, + series = {International {Series} of {Monographs} on {Physics}}, + title = {Tokamaks}, + isbn = {9780198509226}, + publisher = {Oxford University Press}, + author = {Wesson, John}, + year = {2004}, +} + +@book{wesson_tokamaks_2011, + address = {Oxford, New York}, + edition = {4th}, + series = {International {Series} of {Monographs} on {Physics}}, + title = {Tokamaks}, + isbn = {978-0-19-959223-4}, + publisher = {Oxford University Press}, + author = {Wesson, John}, + month = dec, + year = {2011}, +} + +@article{gi_bootstrap_2014, + title = {Bootstrap current fraction scaling for a tokamak reactor design study}, + volume = {89}, + issn = {0920-3796}, + doi = {10.1016/j.fusengdes.2014.07.009}, + language = {en}, + number = {11}, + journal = {Fusion Engineering and Design}, + author = {Gi, Keii and Nakamura, Makoto and Tobita, Kenji and Ono, Yasushi}, + month = nov, + year = {2014}, + keywords = {Bootstrap current fraction, Reactor design, Scaling, Spherical tokamak, Systems codes, Tokamak}, + pages = {2709--2715}, +} + +@book{freidberg_plasma_2007, + address = {Cambridge}, + title = {Plasma {Physics} and {Fusion} {Energy}}, + isbn = {978-0-521-73317-5}, + publisher = {Cambridge University Press}, + author = {Freidberg, Jeffrey P.}, + year = {2007}, + doi = {10.1017/CBO9780511755705}, +} +@article{hively_convenient_1977, + title = {Convenient computational forms for maxwellian reactivities}, + volume = {17}, + issn = {0029-5515}, + doi = {10.1088/0029-5515/17/4/019}, + language = {en}, + number = {4}, + journal = {Nuclear Fusion}, + author = {Hively, L. M.}, + month = aug, + year = {1977}, + pages = {873}, +} + +@techreport{langenbrunner_analytic_2017, + title = {Analytic, empirical and delta method temperature derivatives of {D}-{D} and {D}-{T} fusion reactivity formulations, as a means of verification}, + language = {en}, + institution = {Los Alamos National Lab. (LANL), Los Alamos, NM (United States)}, + number = {LA-UR--17-26143, 1372790}, + author = {Langenbrunner, James R. and Booker, Jane M.}, + month = jul, + year = {2017}, + doi = {10.2172/1372790}, +} + +@article{mavrin_improved_2018, + title = {Improved fits of coronal radiative cooling rates for high-temperature plasmas}, + volume = {173}, + issn = {10294953}, + url = {https://doi.org/10.1080/10420150.2018.1462361}, + doi = {10.1080/10420150.2018.1462361}, + pages = {388--398}, + number = {5}, + journal = {Radiation Effects and Defects in Solids}, + author = {Mavrin, A. A.}, + year = {2018}, +} + +@article{mavrin_radiative_2017, + title = {Radiative Cooling Rates for Low-Z Impurities in Non-coronal Equilibrium State}, + volume = {36}, + issn = {01640313}, + url = {https://doi.org/10.1007/s10894-017-0136-z}, + doi = {10.1007/s10894-017-0136-z}, + pages = {161--172}, + number = {4}, + journal = {Journal of Fusion Energy}, + author = {Mavrin, A. A.}, + year = {2017}, +} + +@article{stott_feasibility_2005, + title = {The feasibility of using D-3He and D-D fusion fuels}, + volume = {47}, + issn = {07413335}, + url = {https://doi.org/10.1088/0741-3335/47/8/011}, + doi = {10.1088/0741-3335/47/8/011}, + pages = {1305}, + journal = {Plasma Physics and Controlled Fusion}, + author = {Stott, P. E.}, + year = {2005}, +} + +@article{zohm_use_2019, + title = {On the Use of High Magnetic Field in Reactor Grade Tokamaks}, + volume = {38}, + url = {https://doi.org/10.1007/s10894-018-0177-y}, + doi = {10.1007/s10894-018-0177-y}, + pages = {3-10}, + journal = {Journal of Fusion Energy}, + author = {Zohm, H.}, + year = {2019}, +} + +@article{Verdoolaege_2021, +doi = {10.1088/1741-4326/abdb91}, +url = {https://dx.doi.org/10.1088/1741-4326/abdb91}, +year = {2021}, +month = {may}, +publisher = {IOP Publishing}, +volume = {61}, +number = {7}, +pages = {076006}, +author = {G. Verdoolaege and S.M. Kaye and C. Angioni and O.J.W.F. Kardaun and M. Maslov and M. Romanelli and F. Ryter and K. Thomsen and the ASDEX Upgrade Team and the EUROfusion MST1 Team and JET Contributors}, +title = {The updated ITPA global H-mode confinement database: description and analysis}, +journal = {Nuclear Fusion}, +} \ No newline at end of file diff --git a/docs/static/theme_overrides.css b/docs/static/theme_overrides.css new file mode 100644 index 00000000..94af5f01 --- /dev/null +++ b/docs/static/theme_overrides.css @@ -0,0 +1,29 @@ +/* Fix for: https://github.com/readthedocs/sphinx_rtd_theme/issues/301 +/* Fix taken from: https://github.com/readthedocs/sphinx_rtd_theme/pull/383/ */ +span.eqno { + margin-left: 5px; + float: right; + /* position the number above the equation so that :hover is activated */ + z-index: 1; + position: relative; +} + +span.eqno .headerlink { + display: none; + visibility: hidden; +} + +span.eqno:hover .headerlink { + display: inline-block; + visibility: visible; +} + + +.sig.sig-object.py dl{ + margin: 0 0 0 0; +} + +.sig.sig-object.py * dd{ + margin: 0 0 0px 24px; +} + diff --git a/example_cases/SPARC_PRD/input.yaml b/example_cases/SPARC_PRD/input.yaml new file mode 100644 index 00000000..a34044ab --- /dev/null +++ b/example_cases/SPARC_PRD/input.yaml @@ -0,0 +1,168 @@ +# Primary Reference Discharge, see https://doi.org/10.1017/S0022377820001257 +algorithms: + # The POPCON algorithm starts by selecting an average density + # and temperature, which defines a stored energy stored_energy. From this, + # we can compute P_in from stored_energy and a tau_e scaling. + - calc_geometry + - calc_q_star_from_plasma_current + - calc_fuel_average_mass_number + - calc_average_ion_temp + - calc_zeff_and_dilution_from_impurities + - calc_plasma_stored_energy + - calc_power_balance_from_tau_e + # Once we have P_in (=P_loss in steady-state), we want to split + # it into components. For this, we need to estimate 1D plasma + # profiles in the confined region. + - calc_beta + - calc_peaked_profiles + # Once we have the profiles, we can then estimate the power + # radiated from the confined region. + - calc_core_radiated_power + - require_P_rad_less_than_P_in + # To control the power crossing the separatrix, we can inject + # a core radiator (high-Z species like Xenon) to intentionally + # increase the power radiated from the core. This increases + # the fuel dilution and Zeff (computed), as well as degrading + # core confinement (not yet computed). + - calc_extrinsic_core_radiator + # We then recompute the profiles with the dilution due to the + # core radiator, and use this to determine the fusion power rate. + - calc_peaked_profiles + - calc_fusion_gain + # We compute the ohmic heating power from the inductive current and + # loop voltage, and then set P_auxillary = P_in - P_ohmic + - calc_bootstrap_fraction + - calc_ohmic_power + - calc_auxillary_power + # Once we have the power input into and radiated from the confined + # region, we can determine the power crossing the separatrix. We use + # a scaling for lambda_q to calculate a corresponding q_parallel, and + # then use the two-point-model to determine how much edge seeding we + # require to protect the divertor. + - calc_P_SOL + - calc_average_total_pressure + - calc_heat_exhaust + - two_point_model_fixed_tet + # Finally, we calculate several parameters which aren't used in other + # calculations, but which are useful for characterizing operational + # points. These can be used later when masking inaccessible operational + # space, such as regions with f_Greenwald >~ 1.0 or where P_SOL < P_LH. + - calc_greenwald_fraction + - calc_confinement_transition_threshold_power + - calc_ratio_P_LH + - calc_f_rad_core + - calc_normalised_collisionality + - calc_rho_star + - calc_triple_product + - calc_peak_pressure + - calc_current_relaxation_time + +grid: + # input variables in the 'grid' block will be replaced by + # a corresponding linspace or logspace of values + + average_electron_density: + # Average electron density in 1e19 particles / m^3 + min: 1.0 + max: 40.0 + num: 40 + spacing: linear + + average_electron_temp: + # Average electron temperature in keV + min: 5.0 + max: 20.0 + num: 30 + spacing: linear + +points: + PRD: + maximize: Q + where: + P_auxillary: + min: 0.0 + max: 25.0 + units: MW + greenwald_fraction: + max: 0.9 + ratio_of_P_SOL_to_P_LH: + min: 1.0 + P_fusion: + max: 140.0 + units: MW + +# Major radius in metres +major_radius: 1.85 +# Toroidal field on-axis in Tesla +magnetic_field_on_axis: 12.2 +# Inverse aspect ratio +inverse_aspect_ratio: 0.3081 +# Areal elongation +areal_elongation: 1.75 +# Ratio of separatrix_elongation to kappa_A +elongation_ratio_sep_to_areal: 1.125 +# Triangularity at rho_pol = 0.95 +triangularity_psi95: 0.3 +# Ratio of separatrix_triangularity to delta_95 +triangularity_ratio_sep_to_psi95: 1.8 +# Plasma current in Ampere +plasma_current: 8.7e+6 +# Fraction of launched power absorbed by the plasma. Affects Q=P_fusion / (P_external / f_coupled). +fraction_of_external_power_coupled: 0.9 + +# What fusion reaction are we using? +fusion_reaction: DT +# Fraction of fuel ions which are the heavier species +heavier_fuel_species_fraction: 0.5 + +# What sort of 1D profiles should be assumed? +profile_form: prf +# Inverse normalized electron temp scale length a / L_Te = a / (Te / grad(Te)) +normalized_inverse_temp_scale_length: 2.5 +# Offset for the electron density peaking factor +electron_density_peaking_offset: -0.1 +# Offset for the ion density peaking factor +ion_density_peaking_offset: -0.2 +# Temperature peaking factor +temperature_peaking: 2.5 +# Ratio of volume-averaged temperatures (Ti / Te) +ion_to_electron_temp_ratio: 1.0 + +# Ratio of confinement-mode threshold power to scaling +confinement_threshold_scalar: 1.0 +# Confinement enhancement factor +confinement_time_scalar: 1.0 +# Name of the tau_e scaling used +energy_confinement_scaling: ITER98y2 + +radiated_power_method: Radas +radiated_power_scalar: 1.0 +minimum_core_radiated_fraction: 0.0 + +impurities: + # Impurity concentration relative to electron density. + Tungsten: 1.5e-5 + Helium: 6.0e-2 + Oxygen: 3.1e-3 + +core_radiator: Xenon + +# Inputs for two-point-model +# Ratio of separatrix to average density +nesep_over_nebar: 0.3 +# R_t/R_u = major radius at target / major radius upstream (outboard midplane) +toroidal_flux_expansion: 0.6974 +# Length along field-line from upstream (outboard midplane) to target in m +parallel_connection_length: 30.0 +# Lambda_q scaling (matching a LambdaQScaling in named_options) +lambda_q_scaling: EichRegression15 +# Scaling factor for lambda_q relative to selected scaling +lambda_q_factor: 1.0 +# Function used to calculate the momentum loss as a function of target Te in the SOL (matching a MomentumLossFunction in named_options) +SOL_momentum_loss_function: KotovReiter +# Fraction of P_SOL going to the outer divertor +fraction_of_P_SOL_to_divertor: 0.6 +# Electron thermal conductivity in W / (eV**3.5 m) +kappa_e0: 2600.0 +# Calculate P_rad_SOL such that the target electron temperature in eV reaches this value (for FixedTargetElectronTemp) +target_electron_temp: 25.0 diff --git a/example_cases/SPARC_PRD/plot_popcon.yaml b/example_cases/SPARC_PRD/plot_popcon.yaml new file mode 100644 index 00000000..5dfff0e7 --- /dev/null +++ b/example_cases/SPARC_PRD/plot_popcon.yaml @@ -0,0 +1,65 @@ +type: popcon + +figsize: [8, 6] +show_dpi: 150 +save_as: "SPARC_PRD" + +coords: + x: + dimension: average_electron_temp + label: "$$ [$keV$]" + units: keV + y: + dimension: average_electron_density + label: "$$ [$10^{20} m^{-3}$]" + units: n20 + +fill: + variable: Q + where: + Q: + min: 1.0 + P_auxillary: + min: 0.0 + max: 25.0 + units: MW + greenwald_fraction: + max: 0.9 + ratio_of_P_SOL_to_P_LH: + min: 1.0 + +points: + PRD: + label: "PRD" + marker: "x" + color: "red" + size: 50.0 + +# Suggested colors are "tab:red", "tab:blue", "tab:orange", "tab:green", "tab:purple", +# "tab:brown", "tab:pink", "tab:gray", "tab:olive", "tab:cyan" +contour: + + Q: + label: $Q$ + levels: [0.1, 1.0, 2.0, 5.0, 10.0, 50.0] + color: "tab:red" + format: "1.2g" + + ratio_of_P_SOL_to_P_LH: + label: "$P_{SOL}/P_{LH}$" + color: "tab:blue" + levels: [1.0] + format: "1.2g" + + P_auxillary: + label: "$P_{aux}$" + levels: [1.0, 5.0, 10.0, 25.0, 50.0] + color: "tab:gray" + format: "1.2g" + + P_fusion: + label: "$P_{fusion}$" + color: "tab:purple" + levels: [50.0, 100.0, 150.0, 200.0] + format: "1.2g" + \ No newline at end of file diff --git a/example_cases/SPARC_PRD/plot_remapped.yaml b/example_cases/SPARC_PRD/plot_remapped.yaml new file mode 100644 index 00000000..8aeb2ee6 --- /dev/null +++ b/example_cases/SPARC_PRD/plot_remapped.yaml @@ -0,0 +1,65 @@ +type: popcon + +figsize: [8, 6] +show_dpi: 150 + +new_coords: + x: + dimension: P_auxillary + label: "$P_{RF}$ [$MW$]" + units: MW + max: 25.0 + y: + dimension: average_electron_density + label: "$$ [$10^{20} m^{-3}$]" + units: n20 + +fill: + variable: Q + where: + Q: + min: 1.0 + P_auxillary: + min: 0.0 + max: 25.0 + units: MW + greenwald_fraction: + max: 0.9 + ratio_of_P_SOL_to_P_LH: + min: 1.0 + +points: + PRD: + label: "PRD" + marker: "x" + color: "red" + size: 50.0 + +# Suggested colors are "tab:red", "tab:blue", "tab:orange", "tab:green", "tab:purple", +# "tab:brown", "tab:pink", "tab:gray", "tab:olive", "tab:cyan" +contour: + + Q: + label: $Q$ + levels: [0.1, 1.0, 2.0, 5.0, 10.0, 50.0] + color: "tab:red" + format: "1.2g" + + ratio_of_P_SOL_to_P_LH: + label: "$P_{SOL}/P_{LH}$" + color: "tab:blue" + levels: [1.0] + format: "1.2g" + + P_auxillary: + label: "$P_{aux}$" + levels: [1.0, 5.0, 10.0, 25.0, 50.0] + color: "tab:gray" + format: "1.2g" + + P_fusion: + label: "$P_{fusion}$" + color: "tab:purple" + levels: [50.0, 100.0, 150.0, 200.0] + format: "1.2g" + \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..fa9d915d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,2929 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + +[[package]] +name = "appnope" +version = "0.1.3" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = "*" +files = [ + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, +] + +[[package]] +name = "asttokens" +version = "2.4.0" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.0-py2.py3-none-any.whl", hash = "sha256:cf8fc9e61a86461aa9fb161a14a0841a03c405fa829ac6b202670b3495d2ce69"}, + {file = "asttokens-2.4.0.tar.gz", hash = "sha256:2e0171b991b2c959acc6c49318049236844a5da1d65ba2672c4880c1c894834e"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +test = ["astroid", "pytest"] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "babel" +version = "2.12.1" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, + {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, +] + +[[package]] +name = "backcall" +version = "0.2.0" +description = "Specifications for callback functions passed in to an API" +optional = false +python-versions = "*" +files = [ + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, +] + +[[package]] +name = "beautifulsoup4" +version = "4.12.2" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, + {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "black" +version = "22.12.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.7" +files = [ + {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, + {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, + {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, + {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, + {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, + {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, + {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, + {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, + {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, + {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, + {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, + {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "bleach" +version = "6.0.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.7" +files = [ + {file = "bleach-6.0.0-py3-none-any.whl", hash = "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4"}, + {file = "bleach-6.0.0.tar.gz", hash = "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.2)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.2.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "comm" +version = "0.1.4" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.6" +files = [ + {file = "comm-0.1.4-py3-none-any.whl", hash = "sha256:6d52794cba11b36ed9860999cd10fd02d6b2eac177068fdd585e1e2f8a96e67a"}, + {file = "comm-0.1.4.tar.gz", hash = "sha256:354e40a59c9dd6db50c5cc6b4acc887d82e9603787f83b68c01a80a923984d15"}, +] + +[package.dependencies] +traitlets = ">=4" + +[package.extras] +lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"] +test = ["pytest"] +typing = ["mypy (>=0.990)"] + +[[package]] +name = "contourpy" +version = "1.1.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.8" +files = [ + {file = "contourpy-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:89f06eff3ce2f4b3eb24c1055a26981bffe4e7264acd86f15b97e40530b794bc"}, + {file = "contourpy-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dffcc2ddec1782dd2f2ce1ef16f070861af4fb78c69862ce0aab801495dda6a3"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25ae46595e22f93592d39a7eac3d638cda552c3e1160255258b695f7b58e5655"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:17cfaf5ec9862bc93af1ec1f302457371c34e688fbd381f4035a06cd47324f48"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18a64814ae7bce73925131381603fff0116e2df25230dfc80d6d690aa6e20b37"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c81f22b4f572f8a2110b0b741bb64e5a6427e0a198b2cdc1fbaf85f352a3aa"}, + {file = "contourpy-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53cc3a40635abedbec7f1bde60f8c189c49e84ac180c665f2cd7c162cc454baa"}, + {file = "contourpy-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:1f795597073b09d631782e7245016a4323cf1cf0b4e06eef7ea6627e06a37ff2"}, + {file = "contourpy-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b7b04ed0961647691cfe5d82115dd072af7ce8846d31a5fac6c142dcce8b882"}, + {file = "contourpy-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27bc79200c742f9746d7dd51a734ee326a292d77e7d94c8af6e08d1e6c15d545"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052cc634bf903c604ef1a00a5aa093c54f81a2612faedaa43295809ffdde885e"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9382a1c0bc46230fb881c36229bfa23d8c303b889b788b939365578d762b5c18"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5cec36c5090e75a9ac9dbd0ff4a8cf7cecd60f1b6dc23a374c7d980a1cd710e"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0cbd657e9bde94cd0e33aa7df94fb73c1ab7799378d3b3f902eb8eb2e04a3a"}, + {file = "contourpy-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:181cbace49874f4358e2929aaf7ba84006acb76694102e88dd15af861996c16e"}, + {file = "contourpy-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb3b7d9e6243bfa1efb93ccfe64ec610d85cfe5aec2c25f97fbbd2e58b531256"}, + {file = "contourpy-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcb41692aa09aeb19c7c213411854402f29f6613845ad2453d30bf421fe68fed"}, + {file = "contourpy-1.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5d123a5bc63cd34c27ff9c7ac1cd978909e9c71da12e05be0231c608048bb2ae"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62013a2cf68abc80dadfd2307299bfa8f5aa0dcaec5b2954caeb5fa094171103"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b6616375d7de55797d7a66ee7d087efe27f03d336c27cf1f32c02b8c1a5ac70"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:317267d915490d1e84577924bd61ba71bf8681a30e0d6c545f577363157e5e94"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d551f3a442655f3dcc1285723f9acd646ca5858834efeab4598d706206b09c9f"}, + {file = "contourpy-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7a117ce7df5a938fe035cad481b0189049e8d92433b4b33aa7fc609344aafa1"}, + {file = "contourpy-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4f26b25b4f86087e7d75e63212756c38546e70f2a92d2be44f80114826e1cd4"}, + {file = "contourpy-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc00bb4225d57bff7ebb634646c0ee2a1298402ec10a5fe7af79df9a51c1bfd9"}, + {file = "contourpy-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:189ceb1525eb0655ab8487a9a9c41f42a73ba52d6789754788d1883fb06b2d8a"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f2931ed4741f98f74b410b16e5213f71dcccee67518970c42f64153ea9313b9"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f511c05fab7f12e0b1b7730ebdc2ec8deedcfb505bc27eb570ff47c51a8f15"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143dde50520a9f90e4a2703f367cf8ec96a73042b72e68fcd184e1279962eb6f"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e94bef2580e25b5fdb183bf98a2faa2adc5b638736b2c0a4da98691da641316a"}, + {file = "contourpy-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed614aea8462735e7d70141374bd7650afd1c3f3cb0c2dbbcbe44e14331bf002"}, + {file = "contourpy-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:438ba416d02f82b692e371858143970ed2eb6337d9cdbbede0d8ad9f3d7dd17d"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a698c6a7a432789e587168573a864a7ea374c6be8d4f31f9d87c001d5a843493"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b0ac8a12880412da3551a8cb5a187d3298a72802b45a3bd1805e204ad8439"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a67259c2b493b00e5a4d0f7bfae51fb4b3371395e47d079a4446e9b0f4d70e76"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2b836d22bd2c7bb2700348e4521b25e077255ebb6ab68e351ab5aa91ca27e027"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084eaa568400cfaf7179b847ac871582199b1b44d5699198e9602ecbbb5f6104"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:911ff4fd53e26b019f898f32db0d4956c9d227d51338fb3b03ec72ff0084ee5f"}, + {file = "contourpy-1.1.0.tar.gz", hash = "sha256:e53046c3863828d21d531cc3b53786e6580eb1ba02477e8681009b6aa0870b21"}, +] + +[package.dependencies] +numpy = ">=1.16" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.2.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "wurlitzer"] + +[[package]] +name = "coverage" +version = "6.5.0" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, + {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, + {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, + {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, + {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, + {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, + {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, + {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, + {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, + {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, + {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, + {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, + {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, + {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, + {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cycler" +version = "0.11.0" +description = "Composable style cycles" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, + {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, +] + +[[package]] +name = "debugpy" +version = "1.8.0" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"}, + {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"}, + {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"}, + {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"}, + {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"}, + {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"}, + {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"}, + {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"}, + {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"}, + {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"}, + {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"}, + {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"}, + {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"}, + {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"}, + {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"}, + {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"}, + {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"}, + {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"}, +] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + +[[package]] +name = "distlib" +version = "0.3.7" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + +[[package]] +name = "docutils" +version = "0.20.1" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "executing" +version = "1.2.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = "*" +files = [ + {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, + {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, +] + +[package.extras] +tests = ["asttokens", "littleutils", "pytest", "rich"] + +[[package]] +name = "fastjsonschema" +version = "2.18.1" +description = "Fastest Python implementation of JSON schema" +optional = false +python-versions = "*" +files = [ + {file = "fastjsonschema-2.18.1-py3-none-any.whl", hash = "sha256:aec6a19e9f66e9810ab371cc913ad5f4e9e479b63a7072a2cd060a9369e329a8"}, + {file = "fastjsonschema-2.18.1.tar.gz", hash = "sha256:06dc8680d937628e993fa0cd278f196d20449a1adc087640710846b324d422ea"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + +[[package]] +name = "filelock" +version = "3.12.3" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.12.3-py3-none-any.whl", hash = "sha256:f067e40ccc40f2b48395a80fcbd4728262fab54e232e090a4063ab804179efeb"}, + {file = "filelock-3.12.3.tar.gz", hash = "sha256:0ecc1dd2ec4672a10c8550a8182f1bd0c0a5088470ecd5a125e45f49472fac3d"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.7.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "fonttools" +version = "4.42.1" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ed1a13a27f59d1fc1920394a7f596792e9d546c9ca5a044419dca70c37815d7c"}, + {file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9b1ce7a45978b821a06d375b83763b27a3a5e8a2e4570b3065abad240a18760"}, + {file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f720fa82a11c0f9042376fd509b5ed88dab7e3cd602eee63a1af08883b37342b"}, + {file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db55cbaea02a20b49fefbd8e9d62bd481aaabe1f2301dabc575acc6b358874fa"}, + {file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a35981d90feebeaef05e46e33e6b9e5b5e618504672ca9cd0ff96b171e4bfff"}, + {file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68a02bbe020dc22ee0540e040117535f06df9358106d3775e8817d826047f3fd"}, + {file = "fonttools-4.42.1-cp310-cp310-win32.whl", hash = "sha256:12a7c247d1b946829bfa2f331107a629ea77dc5391dfd34fdcd78efa61f354ca"}, + {file = "fonttools-4.42.1-cp310-cp310-win_amd64.whl", hash = "sha256:a398bdadb055f8de69f62b0fc70625f7cbdab436bbb31eef5816e28cab083ee8"}, + {file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:689508b918332fb40ce117131633647731d098b1b10d092234aa959b4251add5"}, + {file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e36344e48af3e3bde867a1ca54f97c308735dd8697005c2d24a86054a114a71"}, + {file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7db825c8adee96fac0692e6e1ecd858cae9affb3b4812cdb9d934a898b29e"}, + {file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113337c2d29665839b7d90b39f99b3cac731f72a0eda9306165a305c7c31d341"}, + {file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37983b6bdab42c501202500a2be3a572f50d4efe3237e0686ee9d5f794d76b35"}, + {file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6ed2662a3d9c832afa36405f8748c250be94ae5dfc5283d668308391f2102861"}, + {file = "fonttools-4.42.1-cp311-cp311-win32.whl", hash = "sha256:179737095eb98332a2744e8f12037b2977f22948cf23ff96656928923ddf560a"}, + {file = "fonttools-4.42.1-cp311-cp311-win_amd64.whl", hash = "sha256:f2b82f46917d8722e6b5eafeefb4fb585d23babd15d8246c664cd88a5bddd19c"}, + {file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:62f481ac772fd68901573956231aea3e4b1ad87b9b1089a61613a91e2b50bb9b"}, + {file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2f806990160d1ce42d287aa419df3ffc42dfefe60d473695fb048355fe0c6a0"}, + {file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db372213d39fa33af667c2aa586a0c1235e88e9c850f5dd5c8e1f17515861868"}, + {file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d18fc642fd0ac29236ff88ecfccff229ec0386090a839dd3f1162e9a7944a40"}, + {file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8708b98c278012ad267ee8a7433baeb809948855e81922878118464b274c909d"}, + {file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c95b0724a6deea2c8c5d3222191783ced0a2f09bd6d33f93e563f6f1a4b3b3a4"}, + {file = "fonttools-4.42.1-cp38-cp38-win32.whl", hash = "sha256:4aa79366e442dbca6e2c8595645a3a605d9eeabdb7a094d745ed6106816bef5d"}, + {file = "fonttools-4.42.1-cp38-cp38-win_amd64.whl", hash = "sha256:acb47f6f8680de24c1ab65ebde39dd035768e2a9b571a07c7b8da95f6c8815fd"}, + {file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb289b7a815638a7613d46bcf324c9106804725b2bb8ad913c12b6958ffc4ec"}, + {file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:53eb5091ddc8b1199330bb7b4a8a2e7995ad5d43376cadce84523d8223ef3136"}, + {file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46a0ec8adbc6ff13494eb0c9c2e643b6f009ce7320cf640de106fb614e4d4360"}, + {file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cc7d685b8eeca7ae69dc6416833fbfea61660684b7089bca666067cb2937dcf"}, + {file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:be24fcb80493b2c94eae21df70017351851652a37de514de553435b256b2f249"}, + {file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:515607ec756d7865f23070682622c49d922901943697871fc292277cf1e71967"}, + {file = "fonttools-4.42.1-cp39-cp39-win32.whl", hash = "sha256:0eb79a2da5eb6457a6f8ab904838454accc7d4cccdaff1fd2bd3a0679ea33d64"}, + {file = "fonttools-4.42.1-cp39-cp39-win_amd64.whl", hash = "sha256:7286aed4ea271df9eab8d7a9b29e507094b51397812f7ce051ecd77915a6e26b"}, + {file = "fonttools-4.42.1-py3-none-any.whl", hash = "sha256:9398f244e28e0596e2ee6024f808b06060109e33ed38dcc9bded452fd9bbb853"}, + {file = "fonttools-4.42.1.tar.gz", hash = "sha256:c391cd5af88aacaf41dd7cfb96eeedfad297b5899a39e12f4c2c3706d0a3329d"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "scipy"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.0.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "identify" +version = "2.5.28" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.28-py2.py3-none-any.whl", hash = "sha256:87816de144bf46d161bd5b3e8f5596b16cade3b80be537087334b26bc5c177f3"}, + {file = "identify-2.5.28.tar.gz", hash = "sha256:94bb59643083ebd60dc996d043497479ee554381fbc5307763915cda49b0e78f"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "importlib-resources" +version = "6.0.1" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"}, + {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "ipdb" +version = "0.13.13" +description = "IPython-enabled pdb" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "ipdb-0.13.13-py3-none-any.whl", hash = "sha256:45529994741c4ab6d2388bfa5d7b725c2cf7fe9deffabdb8a6113aa5ed449ed4"}, + {file = "ipdb-0.13.13.tar.gz", hash = "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726"}, +] + +[package.dependencies] +decorator = {version = "*", markers = "python_version > \"3.6\""} +ipython = {version = ">=7.31.1", markers = "python_version > \"3.6\""} +tomli = {version = "*", markers = "python_version > \"3.6\" and python_version < \"3.11\""} + +[[package]] +name = "ipykernel" +version = "6.25.2" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.25.2-py3-none-any.whl", hash = "sha256:2e2ee359baba19f10251b99415bb39de1e97d04e1fab385646f24f0596510b77"}, + {file = "ipykernel-6.25.2.tar.gz", hash = "sha256:f468ddd1f17acb48c8ce67fcfa49ba6d46d4f9ac0438c1f441be7c3d1372230b"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=20" +tornado = ">=6.1" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "ipython" +version = "8.15.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.9" +files = [ + {file = "ipython-8.15.0-py3-none-any.whl", hash = "sha256:45a2c3a529296870a97b7de34eda4a31bee16bc7bf954e07d39abe49caf8f887"}, + {file = "ipython-8.15.0.tar.gz", hash = "sha256:2baeb5be6949eeebf532150f81746f8333e2ccce02de1c7eedde3f23ed5e9f1e"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "sys_platform == \"darwin\""} +backcall = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pickleshare = "*" +prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} + +[package.extras] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] + +[[package]] +name = "jedi" +version = "0.19.0" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"}, + {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonschema" +version = "4.19.1" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.19.1-py3-none-any.whl", hash = "sha256:cd5f1f9ed9444e554b38ba003af06c0a8c2868131e56bfbef0550fb450c0330e"}, + {file = "jsonschema-4.19.1.tar.gz", hash = "sha256:ec84cc37cfa703ef7cd4928db24f9cb31428a5d0fa77747b8b51a847458e0bbf"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.7.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"}, + {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"}, +] + +[package.dependencies] +referencing = ">=0.28.0" + +[[package]] +name = "jupyter-client" +version = "8.3.1" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.3.1-py3-none-any.whl", hash = "sha256:5eb9f55eb0650e81de6b7e34308d8b92d04fe4ec41cd8193a913979e33d8e1a5"}, + {file = "jupyter_client-8.3.1.tar.gz", hash = "sha256:60294b2d5b869356c893f57b1a877ea6510d60d45cf4b38057f1672d85699ac9"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.3.2" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.3.2-py3-none-any.whl", hash = "sha256:a4af53c3fa3f6330cebb0d9f658e148725d15652811d1c32dc0f63bb96f2e6d6"}, + {file = "jupyter_core-5.3.2.tar.gz", hash = "sha256:0c28db6cbe2c37b5b398e1a1a5b22f84fd64cd10afc1f6c05b02fb09481ba45f"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "jupyterlab-pygments" +version = "0.2.2" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, + {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, +] + +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, +] + +[[package]] +name = "latexcodec" +version = "2.0.1" +description = "A lexer and codec to work with LaTeX code in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "latexcodec-2.0.1-py2.py3-none-any.whl", hash = "sha256:c277a193638dc7683c4c30f6684e3db728a06efb0dc9cf346db8bd0aa6c5d271"}, + {file = "latexcodec-2.0.1.tar.gz", hash = "sha256:2aa2551c373261cefe2ad3a8953a6d6533e68238d180eb4bb91d7964adb3fe9a"}, +] + +[package.dependencies] +six = ">=1.4.1" + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + +[[package]] +name = "matplotlib" +version = "3.7.3" +description = "Python plotting package" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib-3.7.3-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:085c33b27561d9c04386789d5aa5eb4a932ddef43cfcdd0e01735f9a6e85ce0c"}, + {file = "matplotlib-3.7.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c568e80e1c17f68a727f30f591926751b97b98314d8e59804f54f86ae6fa6a22"}, + {file = "matplotlib-3.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7baf98c5ad59c5c4743ea884bb025cbffa52dacdfdac0da3e6021a285a90377e"}, + {file = "matplotlib-3.7.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236024f582e40dac39bca592258888b38ae47a9fed7b8de652d68d3d02d47d2b"}, + {file = "matplotlib-3.7.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12b4f6795efea037ce2d41e7c417ad8bd02d5719c6ad4a8450a0708f4a1cfb89"}, + {file = "matplotlib-3.7.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b2136cc6c5415b78977e0e8c608647d597204b05b1d9089ccf513c7d913733"}, + {file = "matplotlib-3.7.3-cp310-cp310-win32.whl", hash = "sha256:122dcbf9be0086e2a95d9e5e0632dbf3bd5b65eaa68c369363310a6c87753059"}, + {file = "matplotlib-3.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:4aab27d9e33293389e3c1d7c881d414a72bdfda0fedc3a6bf46c6fa88d9b8015"}, + {file = "matplotlib-3.7.3-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:d5adc743de91e8e0b13df60deb1b1c285b8effea3d66223afceb14b63c9b05de"}, + {file = "matplotlib-3.7.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:55de4cf7cd0071b8ebf203981b53ab64f988a0a1f897a2dff300a1124e8bcd8b"}, + {file = "matplotlib-3.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ac03377fd908aaee2312d0b11735753e907adb6f4d1d102de5e2425249693f6c"}, + {file = "matplotlib-3.7.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:755bafc10a46918ce9a39980009b54b02dd249594e5adf52f9c56acfddb5d0b7"}, + {file = "matplotlib-3.7.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a6094c6f8e8d18db631754df4fe9a34dec3caf074f6869a7db09f18f9b1d6b2"}, + {file = "matplotlib-3.7.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:272dba2f1b107790ed78ebf5385b8d14b27ad9e90419de340364b49fe549a993"}, + {file = "matplotlib-3.7.3-cp311-cp311-win32.whl", hash = "sha256:591c123bed1cb4b9996fb60b41a6d89c2ec4943244540776c5f1283fb6960a53"}, + {file = "matplotlib-3.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:3bf3a178c6504694cee8b88b353df0051583f2f6f8faa146f67115c27c856881"}, + {file = "matplotlib-3.7.3-cp312-cp312-macosx_10_12_universal2.whl", hash = "sha256:edf54cac8ee3603f3093616b40a931e8c063969756a4d78a86e82c2fea9659f7"}, + {file = "matplotlib-3.7.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:91e36a85ea639a1ba9f91427041eac064b04829945fe331a92617b6cb21d27e5"}, + {file = "matplotlib-3.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:caf5eaaf7c68f8d7df269dfbcaf46f48a70ff482bfcebdcc97519671023f2a7d"}, + {file = "matplotlib-3.7.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74bf57f505efea376097e948b7cdd87191a7ce8180616390aef496639edf601f"}, + {file = "matplotlib-3.7.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee152a88a0da527840a426535514b6ed8ac4240eb856b1da92cf48124320e346"}, + {file = "matplotlib-3.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:67a410a9c9e07cbc83581eeea144bbe298870bf0ac0ee2f2e10a015ab7efee19"}, + {file = "matplotlib-3.7.3-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:259999c05285cb993d7f2a419cea547863fa215379eda81f7254c9e932963729"}, + {file = "matplotlib-3.7.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3f4e7fd5a6157e1d018ce2166ec8e531a481dd4a36f035b5c23edfe05a25419a"}, + {file = "matplotlib-3.7.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:faa3d12d8811d08d14080a8b7b9caea9a457dc495350166b56df0db4b9909ef5"}, + {file = "matplotlib-3.7.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:336e88900c11441e458da01c8414fc57e04e17f9d3bb94958a76faa2652bcf6b"}, + {file = "matplotlib-3.7.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:12f4c0dd8aa280d796c8772ea8265a14f11a04319baa3a16daa5556065e8baea"}, + {file = "matplotlib-3.7.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1990955b11e7918d256cf3b956b10997f405b7917a3f1c7d8e69c1d15c7b1930"}, + {file = "matplotlib-3.7.3-cp38-cp38-win32.whl", hash = "sha256:e78707b751260b42b721507ad7aa60fe4026d7f51c74cca6b9cd8b123ebb633a"}, + {file = "matplotlib-3.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:e594ee43c59ea39ca5c6244667cac9d017a3527febc31f5532ad9135cf7469ec"}, + {file = "matplotlib-3.7.3-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:6eaa1cf0e94c936a26b78f6d756c5fbc12e0a58c8a68b7248a2a31456ce4e234"}, + {file = "matplotlib-3.7.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0a97af9d22e8ebedc9f00b043d9bbd29a375e9e10b656982012dded44c10fd77"}, + {file = "matplotlib-3.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f9c6c16597af660433ab330b59ee2934b832ee1fabcaf5cbde7b2add840f31e"}, + {file = "matplotlib-3.7.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7240259b4b9cbc62381f6378cff4d57af539162a18e832c1e48042fabc40b6b"}, + {file = "matplotlib-3.7.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747c6191d2e88ae854809e69aa358dbf852ff1a5738401b85c1cc9012309897a"}, + {file = "matplotlib-3.7.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec726b08a5275d827aa91bb951e68234a4423adb91cf65bc0fcdc0f2777663f7"}, + {file = "matplotlib-3.7.3-cp39-cp39-win32.whl", hash = "sha256:40e3b9b450c6534f07278310c4e34caff41c2a42377e4b9d47b0f8d3ac1083a2"}, + {file = "matplotlib-3.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfc118642903a23e309b1da32886bb39a4314147d013e820c86b5fb4cb2e36d0"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:165c8082bf8fc0360c24aa4724a22eaadbfd8c28bf1ccf7e94d685cad48261e4"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebd8470cc2a3594746ff0513aecbfa2c55ff6f58e6cef2efb1a54eb87c88ffa2"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7153453669c9672b52095119fd21dd032d19225d48413a2871519b17db4b0fde"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:498a08267dc69dd8f24c4b5d7423fa584d7ce0027ba71f7881df05fc09b89bb7"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48999c4b19b5a0c058c9cd828ff6fc7748390679f6cf9a2ad653a3e802c87d3"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22d65d18b4ee8070a5fea5761d59293f1f9e2fac37ec9ce090463b0e629432fd"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c40cde976c36693cc0767e27cf5f443f91c23520060bd9496678364adfafe9c"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:39018a2b17592448fbfdf4b8352955e6c3905359939791d4ff429296494d1a0c"}, + {file = "matplotlib-3.7.3.tar.gz", hash = "sha256:f09b3dd6bdeb588de91f853bbb2d6f0ff8ab693485b0c49035eaa510cb4f142e"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.0.1" +numpy = ">=1.20,<2" +packaging = ">=20.0" +pillow = ">=6.2.0" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" +setuptools_scm = ">=7" + +[[package]] +name = "matplotlib-inline" +version = "0.1.6" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.5" +files = [ + {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, + {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, +] + +[[package]] +name = "mypy" +version = "1.5.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"}, + {file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"}, + {file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"}, + {file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"}, + {file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"}, + {file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"}, + {file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"}, + {file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"}, + {file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"}, + {file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"}, + {file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"}, + {file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"}, + {file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"}, + {file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"}, + {file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"}, + {file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"}, + {file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"}, + {file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"}, + {file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"}, + {file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"}, + {file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"}, + {file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"}, + {file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"}, + {file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"}, + {file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"}, + {file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"}, + {file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nbclient" +version = "0.6.8" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "nbclient-0.6.8-py3-none-any.whl", hash = "sha256:7cce8b415888539180535953f80ea2385cdbb444944cdeb73ffac1556fdbc228"}, + {file = "nbclient-0.6.8.tar.gz", hash = "sha256:268fde3457cafe1539e32eb1c6d796bbedb90b9e92bacd3e43d83413734bb0e8"}, +] + +[package.dependencies] +jupyter-client = ">=6.1.5" +nbformat = ">=5.0" +nest-asyncio = "*" +traitlets = ">=5.2.2" + +[package.extras] +sphinx = ["Sphinx (>=1.7)", "autodoc-traits", "mock", "moto", "myst-parser", "sphinx-book-theme"] +test = ["black", "check-manifest", "flake8", "ipykernel", "ipython", "ipywidgets", "mypy", "nbconvert", "pip (>=18.1)", "pre-commit", "pytest (>=4.1)", "pytest-asyncio", "pytest-cov (>=2.6.1)", "setuptools (>=60.0)", "testpath", "twine (>=1.11.0)", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.9.2" +description = "Converting Jupyter Notebooks" +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbconvert-7.9.2-py3-none-any.whl", hash = "sha256:39fe4b8bdd1b0104fdd86fc8a43a9077ba64c720bda4c6132690d917a0a154ee"}, + {file = "nbconvert-7.9.2.tar.gz", hash = "sha256:e56cc7588acc4f93e2bb5a34ec69028e4941797b2bfaf6462f18a41d1cc258c9"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +bleach = "!=5.0.0" +defusedxml = "*" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.1" + +[package.extras] +all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["nbconvert[qtpng]"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest", "pytest-dependency"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.9.2" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"}, + {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"}, +] + +[package.dependencies] +fastjsonschema = "*" +jsonschema = ">=2.6" +jupyter-core = "*" +traitlets = ">=5.1" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["pep440", "pre-commit", "pytest", "testpath"] + +[[package]] +name = "nbmake" +version = "1.4.3" +description = "Pytest plugin for testing notebooks" +optional = false +python-versions = ">=3.7.0,<4.0.0" +files = [ + {file = "nbmake-1.4.3-py3-none-any.whl", hash = "sha256:0318dd5dd30066e83717bf38888b2bec1b4744ad669a9801b41858e589493330"}, + {file = "nbmake-1.4.3.tar.gz", hash = "sha256:9afc46ba05cc22f5a78047a758dca32386c95eaaa41501b25ce108cf733d9622"}, +] + +[package.dependencies] +ipykernel = ">=5.4.0" +nbclient = ">=0.6.6,<0.7.0" +nbformat = ">=5.0.8,<6.0.0" +Pygments = ">=2.7.3,<3.0.0" +pytest = ">=6.1.0" + +[[package]] +name = "nbsphinx" +version = "0.9.3" +description = "Jupyter Notebook Tools for Sphinx" +optional = false +python-versions = ">=3.6" +files = [ + {file = "nbsphinx-0.9.3-py3-none-any.whl", hash = "sha256:6e805e9627f4a358bd5720d5cbf8bf48853989c79af557afd91a5f22e163029f"}, + {file = "nbsphinx-0.9.3.tar.gz", hash = "sha256:ec339c8691b688f8676104a367a4b8cf3ea01fd089dc28d24dec22d563b11562"}, +] + +[package.dependencies] +docutils = "*" +jinja2 = "*" +nbconvert = "!=5.4" +nbformat = "*" +sphinx = ">=1.8" +traitlets = ">=5" + +[[package]] +name = "nest-asyncio" +version = "1.5.8" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.5.8-py3-none-any.whl", hash = "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d"}, + {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, +] + +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "numpy" +version = "1.25.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, +] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pandas" +version = "1.5.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406"}, + {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:972d8a45395f2a2d26733eb8d0f629b2f90bebe8e8eddbb8829b180c09639572"}, + {file = "pandas-1.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50869a35cbb0f2e0cd5ec04b191e7b12ed688874bd05dd777c19b28cbea90996"}, + {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3ac844a0fe00bfaeb2c9b51ab1424e5c8744f89860b138434a363b1f620f354"}, + {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a0a56cef15fd1586726dace5616db75ebcfec9179a3a55e78f72c5639fa2a23"}, + {file = "pandas-1.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:478ff646ca42b20376e4ed3fa2e8d7341e8a63105586efe54fa2508ee087f328"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc"}, + {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae"}, + {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6"}, + {file = "pandas-1.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14e45300521902689a81f3f41386dc86f19b8ba8dd5ac5a3c7010ef8d2932813"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9842b6f4b8479e41968eced654487258ed81df7d1c9b7b870ceea24ed9459b31"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:26d9c71772c7afb9d5046e6e9cf42d83dd147b5cf5bcb9d97252077118543792"}, + {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fbcb19d6fceb9e946b3e23258757c7b225ba450990d9ed63ccceeb8cae609f7"}, + {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:565fa34a5434d38e9d250af3c12ff931abaf88050551d9fbcdfafca50d62babf"}, + {file = "pandas-1.5.3-cp38-cp38-win32.whl", hash = "sha256:87bd9c03da1ac870a6d2c8902a0e1fd4267ca00f13bc494c9e5a9020920e1d51"}, + {file = "pandas-1.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:41179ce559943d83a9b4bbacb736b04c928b095b5f25dd2b7389eda08f46f373"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c74a62747864ed568f5a82a49a23a8d7fe171d0c69038b38cedf0976831296fa"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c4c00e0b0597c8e4f59e8d461f797e5d70b4d025880516a8261b2817c47759ee"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a50d9a4336a9621cab7b8eb3fb11adb82de58f9b91d84c2cd526576b881a0c5a"}, + {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd05f7783b3274aa206a1af06f0ceed3f9b412cf665b7247eacd83be41cf7bf0"}, + {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f69c4029613de47816b1bb30ff5ac778686688751a5e9c99ad8c7031f6508e5"}, + {file = "pandas-1.5.3-cp39-cp39-win32.whl", hash = "sha256:7cec0bee9f294e5de5bbfc14d0573f65526071029d036b753ee6507d2a21480a"}, + {file = "pandas-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9"}, + {file = "pandas-1.5.3.tar.gz", hash = "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, +] +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] + +[[package]] +name = "pandas-stubs" +version = "1.5.3.230321" +description = "Type annotations for pandas" +optional = false +python-versions = ">=3.8,<3.12" +files = [ + {file = "pandas_stubs-1.5.3.230321-py3-none-any.whl", hash = "sha256:4bf36b3071dd55f0e558ac8efe07676a120f2ed89e7a3df0fb78ddf2733bf247"}, + {file = "pandas_stubs-1.5.3.230321.tar.gz", hash = "sha256:2fa860df9e6058e9f0d2c09bc711c09abb8f0516eee7f0b9f9950d29b835fc6f"}, +] + +[package.dependencies] +types-pytz = ">=2022.1.1" + +[[package]] +name = "pandocfilters" +version = "1.5.0" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, + {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, +] + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "pexpect" +version = "4.8.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pickleshare" +version = "0.7.5" +description = "Tiny 'shelve'-like database with concurrency support" +optional = false +python-versions = "*" +files = [ + {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, + {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, +] + +[[package]] +name = "pillow" +version = "10.0.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"}, + {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"}, + {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"}, + {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"}, + {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"}, + {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"}, + {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"}, + {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"}, + {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "pint" +version = "0.22" +description = "Physical quantities module" +optional = false +python-versions = ">=3.9" +files = [ + {file = "Pint-0.22-py3-none-any.whl", hash = "sha256:6e2b3c5c2b4d9b516608bc860a417a39d66eb99c958f36540cf931d2c2e9f80f"}, + {file = "Pint-0.22.tar.gz", hash = "sha256:2d139f6abbcf3016cad7d3cec05707fe908ac4f99cf59aedfd6ee667b7a64433"}, +] + +[package.dependencies] +typing-extensions = "*" + +[package.extras] +babel = ["babel (<=2.8)"] +dask = ["dask"] +mip = ["mip (>=1.13)"] +numpy = ["numpy (>=1.19.5)"] +pandas = ["pint-pandas (>=0.3)"] +test = ["pytest", "pytest-cov", "pytest-mpl", "pytest-subtests"] +uncertainties = ["uncertainties (>=3.1.6)"] +xarray = ["xarray"] + +[[package]] +name = "pint-xarray" +version = "0.3" +description = "Physical units interface to xarray using Pint" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pint-xarray-0.3.tar.gz", hash = "sha256:3545dfa78bee3f98eba29b8bd17500e3b5cb7c7b03a2c2781c4d4d59b6a82841"}, + {file = "pint_xarray-0.3-py3-none-any.whl", hash = "sha256:a7d87c792a2e981cbff464bd1c875e872ef7a0c882a9395cfbc34512b3dcb1ab"}, +] + +[package.dependencies] +numpy = ">=1.17" +pint = ">=0.16" +xarray = ">=0.16.1" + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pluggy" +version = "1.3.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "2.21.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, + {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "prompt-toolkit" +version = "3.0.39" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "5.9.5" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, + {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, + {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, + {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, + {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, + {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, + {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, + {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pybtex" +version = "0.24.0" +description = "A BibTeX-compatible bibliography processor in Python" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" +files = [ + {file = "pybtex-0.24.0-py2.py3-none-any.whl", hash = "sha256:e1e0c8c69998452fea90e9179aa2a98ab103f3eed894405b7264e517cc2fcc0f"}, + {file = "pybtex-0.24.0.tar.gz", hash = "sha256:818eae35b61733e5c007c3fcd2cfb75ed1bc8b4173c1f70b56cc4c0802d34755"}, +] + +[package.dependencies] +latexcodec = ">=1.0.4" +PyYAML = ">=3.01" +six = "*" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "pybtex-docutils" +version = "1.0.3" +description = "A docutils backend for pybtex." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pybtex-docutils-1.0.3.tar.gz", hash = "sha256:3a7ebdf92b593e00e8c1c538aa9a20bca5d92d84231124715acc964d51d93c6b"}, + {file = "pybtex_docutils-1.0.3-py3-none-any.whl", hash = "sha256:8fd290d2ae48e32fcb54d86b0efb8d573198653c7e2447d5bec5847095f430b9"}, +] + +[package.dependencies] +docutils = ">=0.14" +pybtex = ">=0.16" + +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] + +[[package]] +name = "pygments" +version = "2.16.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pyparsing" +version = "3.1.1" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pytest" +version = "7.4.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2023.3.post1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, +] + +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "pyzmq" +version = "25.1.1" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76"}, + {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849"}, + {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71"}, + {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd"}, + {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7"}, + {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9"}, + {file = "pyzmq-25.1.1-cp310-cp310-win32.whl", hash = "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790"}, + {file = "pyzmq-25.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f"}, + {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83"}, + {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9"}, + {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f"}, + {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505"}, + {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752"}, + {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca"}, + {file = "pyzmq-25.1.1-cp311-cp311-win32.whl", hash = "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329"}, + {file = "pyzmq-25.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6"}, + {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762"}, + {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a"}, + {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b"}, + {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69"}, + {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e"}, + {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb"}, + {file = "pyzmq-25.1.1-cp312-cp312-win32.whl", hash = "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075"}, + {file = "pyzmq-25.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787"}, + {file = "pyzmq-25.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d"}, + {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb"}, + {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062"}, + {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22"}, + {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf"}, + {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e"}, + {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123"}, + {file = "pyzmq-25.1.1-cp36-cp36m-win32.whl", hash = "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71"}, + {file = "pyzmq-25.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3"}, + {file = "pyzmq-25.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115"}, + {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28"}, + {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0"}, + {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222"}, + {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf"}, + {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7"}, + {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae"}, + {file = "pyzmq-25.1.1-cp37-cp37m-win32.whl", hash = "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e"}, + {file = "pyzmq-25.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3"}, + {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a"}, + {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d"}, + {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995"}, + {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f"}, + {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618"}, + {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb"}, + {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2"}, + {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0"}, + {file = "pyzmq-25.1.1-cp38-cp38-win32.whl", hash = "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c"}, + {file = "pyzmq-25.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1"}, + {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45"}, + {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa"}, + {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414"}, + {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae"}, + {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6"}, + {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c"}, + {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8"}, + {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2"}, + {file = "pyzmq-25.1.1-cp39-cp39-win32.whl", hash = "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2"}, + {file = "pyzmq-25.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996"}, + {file = "pyzmq-25.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a"}, + {file = "pyzmq-25.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728"}, + {file = "pyzmq-25.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180"}, + {file = "pyzmq-25.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304"}, + {file = "pyzmq-25.1.1.tar.gz", hash = "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "referencing" +version = "0.30.2" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"}, + {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rpds-py" +version = "0.10.3" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.10.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:485747ee62da83366a44fbba963c5fe017860ad408ccd6cd99aa66ea80d32b2e"}, + {file = "rpds_py-0.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c55f9821f88e8bee4b7a72c82cfb5ecd22b6aad04033334f33c329b29bfa4da0"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3b52a67ac66a3a64a7e710ba629f62d1e26ca0504c29ee8cbd99b97df7079a8"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3aed39db2f0ace76faa94f465d4234aac72e2f32b009f15da6492a561b3bbebd"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271c360fdc464fe6a75f13ea0c08ddf71a321f4c55fc20a3fe62ea3ef09df7d9"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef5fddfb264e89c435be4adb3953cef5d2936fdeb4463b4161a6ba2f22e7b740"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a771417c9c06c56c9d53d11a5b084d1de75de82978e23c544270ab25e7c066ff"}, + {file = "rpds_py-0.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:52b5cbc0469328e58180021138207e6ec91d7ca2e037d3549cc9e34e2187330a"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6ac3fefb0d168c7c6cab24fdfc80ec62cd2b4dfd9e65b84bdceb1cb01d385c33"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8d54bbdf5d56e2c8cf81a1857250f3ea132de77af543d0ba5dce667183b61fec"}, + {file = "rpds_py-0.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cd2163f42868865597d89399a01aa33b7594ce8e2c4a28503127c81a2f17784e"}, + {file = "rpds_py-0.10.3-cp310-none-win32.whl", hash = "sha256:ea93163472db26ac6043e8f7f93a05d9b59e0505c760da2a3cd22c7dd7111391"}, + {file = "rpds_py-0.10.3-cp310-none-win_amd64.whl", hash = "sha256:7cd020b1fb41e3ab7716d4d2c3972d4588fdfbab9bfbbb64acc7078eccef8860"}, + {file = "rpds_py-0.10.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:1d9b5ee46dcb498fa3e46d4dfabcb531e1f2e76b477e0d99ef114f17bbd38453"}, + {file = "rpds_py-0.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:563646d74a4b4456d0cf3b714ca522e725243c603e8254ad85c3b59b7c0c4bf0"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e626b864725680cd3904414d72e7b0bd81c0e5b2b53a5b30b4273034253bb41f"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485301ee56ce87a51ccb182a4b180d852c5cb2b3cb3a82f7d4714b4141119d8c"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42f712b4668831c0cd85e0a5b5a308700fe068e37dcd24c0062904c4e372b093"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c9141af27a4e5819d74d67d227d5047a20fa3c7d4d9df43037a955b4c748ec5"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef750a20de1b65657a1425f77c525b0183eac63fe7b8f5ac0dd16f3668d3e64f"}, + {file = "rpds_py-0.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1a0ffc39f51aa5f5c22114a8f1906b3c17eba68c5babb86c5f77d8b1bba14d1"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f4c179a7aeae10ddf44c6bac87938134c1379c49c884529f090f9bf05566c836"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:176287bb998fd1e9846a9b666e240e58f8d3373e3bf87e7642f15af5405187b8"}, + {file = "rpds_py-0.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6446002739ca29249f0beaaf067fcbc2b5aab4bc7ee8fb941bd194947ce19aff"}, + {file = "rpds_py-0.10.3-cp311-none-win32.whl", hash = "sha256:c7aed97f2e676561416c927b063802c8a6285e9b55e1b83213dfd99a8f4f9e48"}, + {file = "rpds_py-0.10.3-cp311-none-win_amd64.whl", hash = "sha256:8bd01ff4032abaed03f2db702fa9a61078bee37add0bd884a6190b05e63b028c"}, + {file = "rpds_py-0.10.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:4cf0855a842c5b5c391dd32ca273b09e86abf8367572073bd1edfc52bc44446b"}, + {file = "rpds_py-0.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:69b857a7d8bd4f5d6e0db4086da8c46309a26e8cefdfc778c0c5cc17d4b11e08"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:975382d9aa90dc59253d6a83a5ca72e07f4ada3ae3d6c0575ced513db322b8ec"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35fbd23c1c8732cde7a94abe7fb071ec173c2f58c0bd0d7e5b669fdfc80a2c7b"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:106af1653007cc569d5fbb5f08c6648a49fe4de74c2df814e234e282ebc06957"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce5e7504db95b76fc89055c7f41e367eaadef5b1d059e27e1d6eabf2b55ca314"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aca759ada6b1967fcfd4336dcf460d02a8a23e6abe06e90ea7881e5c22c4de6"}, + {file = "rpds_py-0.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b5d4bdd697195f3876d134101c40c7d06d46c6ab25159ed5cbd44105c715278a"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a657250807b6efd19b28f5922520ae002a54cb43c2401e6f3d0230c352564d25"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:177c9dd834cdf4dc39c27436ade6fdf9fe81484758885f2d616d5d03c0a83bd2"}, + {file = "rpds_py-0.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e22491d25f97199fc3581ad8dd8ce198d8c8fdb8dae80dea3512e1ce6d5fa99f"}, + {file = "rpds_py-0.10.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:2f3e1867dd574014253b4b8f01ba443b9c914e61d45f3674e452a915d6e929a3"}, + {file = "rpds_py-0.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c22211c165166de6683de8136229721f3d5c8606cc2c3d1562da9a3a5058049c"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40bc802a696887b14c002edd43c18082cb7b6f9ee8b838239b03b56574d97f71"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e271dd97c7bb8eefda5cca38cd0b0373a1fea50f71e8071376b46968582af9b"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95cde244e7195b2c07ec9b73fa4c5026d4a27233451485caa1cd0c1b55f26dbd"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08a80cf4884920863623a9ee9a285ee04cef57ebedc1cc87b3e3e0f24c8acfe5"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763ad59e105fca09705d9f9b29ecffb95ecdc3b0363be3bb56081b2c6de7977a"}, + {file = "rpds_py-0.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:187700668c018a7e76e89424b7c1042f317c8df9161f00c0c903c82b0a8cac5c"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5267cfda873ad62591b9332fd9472d2409f7cf02a34a9c9cb367e2c0255994bf"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2ed83d53a8c5902ec48b90b2ac045e28e1698c0bea9441af9409fc844dc79496"}, + {file = "rpds_py-0.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:255f1a10ae39b52122cce26ce0781f7a616f502feecce9e616976f6a87992d6b"}, + {file = "rpds_py-0.10.3-cp38-none-win32.whl", hash = "sha256:a019a344312d0b1f429c00d49c3be62fa273d4a1094e1b224f403716b6d03be1"}, + {file = "rpds_py-0.10.3-cp38-none-win_amd64.whl", hash = "sha256:efb9ece97e696bb56e31166a9dd7919f8f0c6b31967b454718c6509f29ef6fee"}, + {file = "rpds_py-0.10.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:570cc326e78ff23dec7f41487aa9c3dffd02e5ee9ab43a8f6ccc3df8f9327623"}, + {file = "rpds_py-0.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cff7351c251c7546407827b6a37bcef6416304fc54d12d44dbfecbb717064717"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:177914f81f66c86c012311f8c7f46887ec375cfcfd2a2f28233a3053ac93a569"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:448a66b8266de0b581246ca7cd6a73b8d98d15100fb7165974535fa3b577340e"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bbac1953c17252f9cc675bb19372444aadf0179b5df575ac4b56faaec9f6294"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dd9d9d9e898b9d30683bdd2b6c1849449158647d1049a125879cb397ee9cd12"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c71ea77536149e36c4c784f6d420ffd20bea041e3ba21ed021cb40ce58e2c9"}, + {file = "rpds_py-0.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16a472300bc6c83fe4c2072cc22b3972f90d718d56f241adabc7ae509f53f154"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b9255e7165083de7c1d605e818025e8860636348f34a79d84ec533546064f07e"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:53d7a3cd46cdc1689296348cb05ffd4f4280035770aee0c8ead3bbd4d6529acc"}, + {file = "rpds_py-0.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22da15b902f9f8e267020d1c8bcfc4831ca646fecb60254f7bc71763569f56b1"}, + {file = "rpds_py-0.10.3-cp39-none-win32.whl", hash = "sha256:850c272e0e0d1a5c5d73b1b7871b0a7c2446b304cec55ccdb3eaac0d792bb065"}, + {file = "rpds_py-0.10.3-cp39-none-win_amd64.whl", hash = "sha256:de61e424062173b4f70eec07e12469edde7e17fa180019a2a0d75c13a5c5dc57"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:af247fd4f12cca4129c1b82090244ea5a9d5bb089e9a82feb5a2f7c6a9fe181d"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ad59efe24a4d54c2742929001f2d02803aafc15d6d781c21379e3f7f66ec842"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642ed0a209ced4be3a46f8cb094f2d76f1f479e2a1ceca6de6346a096cd3409d"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37d0c59548ae56fae01c14998918d04ee0d5d3277363c10208eef8c4e2b68ed6"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aad6ed9e70ddfb34d849b761fb243be58c735be6a9265b9060d6ddb77751e3e8"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f94fdd756ba1f79f988855d948ae0bad9ddf44df296770d9a58c774cfbcca72"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77076bdc8776a2b029e1e6ffbe6d7056e35f56f5e80d9dc0bad26ad4a024a762"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87d9b206b1bd7a0523375dc2020a6ce88bca5330682ae2fe25e86fd5d45cea9c"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8efaeb08ede95066da3a3e3c420fcc0a21693fcd0c4396d0585b019613d28515"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a4d9bfda3f84fc563868fe25ca160c8ff0e69bc4443c5647f960d59400ce6557"}, + {file = "rpds_py-0.10.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d27aa6bbc1f33be920bb7adbb95581452cdf23005d5611b29a12bb6a3468cc95"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ed8313809571a5463fd7db43aaca68ecb43ca7a58f5b23b6e6c6c5d02bdc7882"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:e10e6a1ed2b8661201e79dff5531f8ad4cdd83548a0f81c95cf79b3184b20c33"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:015de2ce2af1586ff5dc873e804434185199a15f7d96920ce67e50604592cae9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae87137951bb3dc08c7d8bfb8988d8c119f3230731b08a71146e84aaa919a7a9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bb4f48bd0dd18eebe826395e6a48b7331291078a879295bae4e5d053be50d4c"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09362f86ec201288d5687d1dc476b07bf39c08478cde837cb710b302864e7ec9"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821392559d37759caa67d622d0d2994c7a3f2fb29274948ac799d496d92bca73"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7170cbde4070dc3c77dec82abf86f3b210633d4f89550fa0ad2d4b549a05572a"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:5de11c041486681ce854c814844f4ce3282b6ea1656faae19208ebe09d31c5b8"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:4ed172d0c79f156c1b954e99c03bc2e3033c17efce8dd1a7c781bc4d5793dfac"}, + {file = "rpds_py-0.10.3-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:11fdd1192240dda8d6c5d18a06146e9045cb7e3ba7c06de6973000ff035df7c6"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f602881d80ee4228a2355c68da6b296a296cd22bbb91e5418d54577bbf17fa7c"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:691d50c99a937709ac4c4cd570d959a006bd6a6d970a484c84cc99543d4a5bbb"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24cd91a03543a0f8d09cb18d1cb27df80a84b5553d2bd94cba5979ef6af5c6e7"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc2200e79d75b5238c8d69f6a30f8284290c777039d331e7340b6c17cad24a5a"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea65b59882d5fa8c74a23f8960db579e5e341534934f43f3b18ec1839b893e41"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:829e91f3a8574888b73e7a3feb3b1af698e717513597e23136ff4eba0bc8387a"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eab75a8569a095f2ad470b342f2751d9902f7944704f0571c8af46bede438475"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:061c3ff1f51ecec256e916cf71cc01f9975af8fb3af9b94d3c0cc8702cfea637"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:39d05e65f23a0fe897b6ac395f2a8d48c56ac0f583f5d663e0afec1da89b95da"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4eca20917a06d2fca7628ef3c8b94a8c358f6b43f1a621c9815243462dcccf97"}, + {file = "rpds_py-0.10.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e8d0f0eca087630d58b8c662085529781fd5dc80f0a54eda42d5c9029f812599"}, + {file = "rpds_py-0.10.3.tar.gz", hash = "sha256:fcc1ebb7561a3e24a6588f7c6ded15d80aec22c66a070c757559b57b17ffd1cb"}, +] + +[[package]] +name = "ruff" +version = "0.0.292" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.292-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:02f29db018c9d474270c704e6c6b13b18ed0ecac82761e4fcf0faa3728430c96"}, + {file = "ruff-0.0.292-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:69654e564342f507edfa09ee6897883ca76e331d4bbc3676d8a8403838e9fade"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c3c91859a9b845c33778f11902e7b26440d64b9d5110edd4e4fa1726c41e0a4"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4476f1243af2d8c29da5f235c13dca52177117935e1f9393f9d90f9833f69e4"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be8eb50eaf8648070b8e58ece8e69c9322d34afe367eec4210fdee9a555e4ca7"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9889bac18a0c07018aac75ef6c1e6511d8411724d67cb879103b01758e110a81"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdfabd4334684a4418b99b3118793f2c13bb67bf1540a769d7816410402a205"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7c77c53bfcd75dbcd4d1f42d6cabf2485d2e1ee0678da850f08e1ab13081a8"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e087b24d0d849c5c81516ec740bf4fd48bf363cfb104545464e0fca749b6af9"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f160b5ec26be32362d0774964e218f3fcf0a7da299f7e220ef45ae9e3e67101a"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ac153eee6dd4444501c4bb92bff866491d4bfb01ce26dd2fff7ca472c8df9ad0"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_i686.whl", hash = "sha256:87616771e72820800b8faea82edd858324b29bb99a920d6aa3d3949dd3f88fb0"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b76deb3bdbea2ef97db286cf953488745dd6424c122d275f05836c53f62d4016"}, + {file = "ruff-0.0.292-py3-none-win32.whl", hash = "sha256:e854b05408f7a8033a027e4b1c7f9889563dd2aca545d13d06711e5c39c3d003"}, + {file = "ruff-0.0.292-py3-none-win_amd64.whl", hash = "sha256:f27282bedfd04d4c3492e5c3398360c9d86a295be00eccc63914438b4ac8a83c"}, + {file = "ruff-0.0.292-py3-none-win_arm64.whl", hash = "sha256:7f67a69c8f12fbc8daf6ae6d36705037bde315abf8b82b6e1f4c9e74eb750f68"}, + {file = "ruff-0.0.292.tar.gz", hash = "sha256:1093449e37dd1e9b813798f6ad70932b57cf614e5c2b5c51005bf67d55db33ac"}, +] + +[[package]] +name = "scipy" +version = "1.11.2" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = "<3.13,>=3.9" +files = [ + {file = "scipy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2b997a5369e2d30c97995dcb29d638701f8000d04df01b8e947f206e5d0ac788"}, + {file = "scipy-1.11.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:95763fbda1206bec41157582bea482f50eb3702c85fffcf6d24394b071c0e87a"}, + {file = "scipy-1.11.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e367904a0fec76433bf3fbf3e85bf60dae8e9e585ffd21898ab1085a29a04d16"}, + {file = "scipy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d690e1ca993c8f7ede6d22e5637541217fc6a4d3f78b3672a6fe454dbb7eb9a7"}, + {file = "scipy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d2b813bfbe8dec6a75164523de650bad41f4405d35b0fa24c2c28ae07fcefb20"}, + {file = "scipy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:afdb0d983f6135d50770dd979df50bf1c7f58b5b33e0eb8cf5c73c70600eae1d"}, + {file = "scipy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d9886f44ef8c9e776cb7527fb01455bf4f4a46c455c4682edc2c2cc8cd78562"}, + {file = "scipy-1.11.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1342ca385c673208f32472830c10110a9dcd053cf0c4b7d4cd7026d0335a6c1d"}, + {file = "scipy-1.11.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b133f237bd8ba73bad51bc12eb4f2d84cbec999753bf25ba58235e9fc2096d80"}, + {file = "scipy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aeb87661de987f8ec56fa6950863994cd427209158255a389fc5aea51fa7055"}, + {file = "scipy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90d3b1364e751d8214e325c371f0ee0dd38419268bf4888b2ae1040a6b266b2a"}, + {file = "scipy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:f73102f769ee06041a3aa26b5841359b1a93cc364ce45609657751795e8f4a4a"}, + {file = "scipy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa4909c6c20c3d91480533cddbc0e7c6d849e7d9ded692918c76ce5964997898"}, + {file = "scipy-1.11.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ac74b1512d38718fb6a491c439aa7b3605b96b1ed3be6599c17d49d6c60fca18"}, + {file = "scipy-1.11.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8425fa963a32936c9773ee3ce44a765d8ff67eed5f4ac81dc1e4a819a238ee9"}, + {file = "scipy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:542a757e2a6ec409e71df3d8fd20127afbbacb1c07990cb23c5870c13953d899"}, + {file = "scipy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ea932570b1c2a30edafca922345854ff2cd20d43cd9123b6dacfdecebfc1a80b"}, + {file = "scipy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:4447ad057d7597476f9862ecbd9285bbf13ba9d73ce25acfa4e4b11c6801b4c9"}, + {file = "scipy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b0620240ef445b5ddde52460e6bc3483b7c9c750275369379e5f609a1050911c"}, + {file = "scipy-1.11.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:f28f1f6cfeb48339c192efc6275749b2a25a7e49c4d8369a28b6591da02fbc9a"}, + {file = "scipy-1.11.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:214cdf04bbae7a54784f8431f976704ed607c4bc69ba0d5d5d6a9df84374df76"}, + {file = "scipy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10eb6af2f751aa3424762948e5352f707b0dece77288206f227864ddf675aca0"}, + {file = "scipy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0f3261f14b767b316d7137c66cc4f33a80ea05841b9c87ad83a726205b901423"}, + {file = "scipy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:2c91cf049ffb5575917f2a01da1da082fd24ed48120d08a6e7297dfcac771dcd"}, + {file = "scipy-1.11.2.tar.gz", hash = "sha256:b29318a5e39bd200ca4381d80b065cdf3076c7d7281c5e36569e99273867f61d"}, +] + +[package.dependencies] +numpy = ">=1.21.6,<1.28.0" + +[package.extras] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + +[[package]] +name = "seaborn" +version = "0.12.2" +description = "Statistical data visualization" +optional = false +python-versions = ">=3.7" +files = [ + {file = "seaborn-0.12.2-py3-none-any.whl", hash = "sha256:ebf15355a4dba46037dfd65b7350f014ceb1f13c05e814eda2c9f5fd731afc08"}, + {file = "seaborn-0.12.2.tar.gz", hash = "sha256:374645f36509d0dcab895cba5b47daf0586f77bfe3b36c97c607db7da5be0139"}, +] + +[package.dependencies] +matplotlib = ">=3.1,<3.6.1 || >3.6.1" +numpy = ">=1.17,<1.24.0 || >1.24.0" +pandas = ">=0.25" + +[package.extras] +dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] +docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] +stats = ["scipy (>=1.3)", "statsmodels (>=0.10)"] + +[[package]] +name = "setuptools" +version = "68.2.1" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.1-py3-none-any.whl", hash = "sha256:eff96148eb336377ab11beee0c73ed84f1709a40c0b870298b0d058828761bae"}, + {file = "setuptools-68.2.1.tar.gz", hash = "sha256:56ee14884fd8d0cd015411f4a13f40b4356775a0aefd9ebc1d3bfb9a1acb32f1"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "setuptools-scm" +version = "7.1.0" +description = "the blessed package to manage your versions by scm tags" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setuptools_scm-7.1.0-py3-none-any.whl", hash = "sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e"}, + {file = "setuptools_scm-7.1.0.tar.gz", hash = "sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27"}, +] + +[package.dependencies] +packaging = ">=20.0" +setuptools = "*" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +typing-extensions = "*" + +[package.extras] +test = ["pytest (>=6.2)", "virtualenv (>20)"] +toml = ["setuptools (>=42)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + +[[package]] +name = "sphinx" +version = "7.2.6" +description = "Python documentation generator" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, + {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.21" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.14" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.9" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] + +[[package]] +name = "sphinx-copybutton" +version = "0.5.2" +description = "Add a copy button to each of your code cells." +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, + {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, +] + +[package.dependencies] +sphinx = ">=1.8" + +[package.extras] +code-style = ["pre-commit (==2.12.1)"] +rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] + +[[package]] +name = "sphinx-rtd-theme" +version = "2.0.0rc2" +description = "Read the Docs theme for Sphinx" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinx_rtd_theme-2.0.0rc2-py2.py3-none-any.whl", hash = "sha256:f04df9213acf421c3b42f4f39005c8bc68fc4696c5b4ed4ef13d1678369713f7"}, + {file = "sphinx_rtd_theme-2.0.0rc2.tar.gz", hash = "sha256:d1270effe620df9164b1cd2d617909472a63531e21a716fd22d0fbcedf9d24ff"}, +] + +[package.dependencies] +docutils = "<0.21" +sphinx = ">=5,<8" +sphinxcontrib-jquery = ">=4,<5" + +[package.extras] +dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.7" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"}, + {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"}, +] + +[package.dependencies] +Sphinx = ">=5" + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-bibtex" +version = "2.6.1" +description = "Sphinx extension for BibTeX style citations." +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinxcontrib-bibtex-2.6.1.tar.gz", hash = "sha256:046b49f070ae5276af34c1b8ddb9bc9562ef6de2f7a52d37a91cb8e53f54b863"}, + {file = "sphinxcontrib_bibtex-2.6.1-py3-none-any.whl", hash = "sha256:094c772098fe6b030cda8618c45722b2957cad0c04f328ba2b154aa08dfe720a"}, +] + +[package.dependencies] +docutils = ">=0.8,<0.18.dev0 || >=0.20.dev0" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +pybtex = ">=0.24" +pybtex-docutils = ">=1.0.0" +Sphinx = ">=3.5" + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.5" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"}, + {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"}, +] + +[package.dependencies] +Sphinx = ">=5" + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.4" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"}, + {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"}, +] + +[package.dependencies] +Sphinx = ">=5" + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jquery" +version = "4.1" +description = "Extension to include jQuery on newer Sphinx releases" +optional = false +python-versions = ">=2.7" +files = [ + {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, + {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, +] + +[package.dependencies] +Sphinx = ">=1.8" + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.6" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"}, + {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"}, +] + +[package.dependencies] +Sphinx = ">=5" + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.9" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl", hash = "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"}, + {file = "sphinxcontrib_serializinghtml-1.1.9.tar.gz", hash = "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54"}, +] + +[package.dependencies] +Sphinx = ">=5" + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "stack-data" +version = "0.6.2" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, + {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[package]] +name = "tinycss2" +version = "1.2.1" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, + {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["flake8", "isort", "pytest"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tornado" +version = "6.3.3" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, + {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, + {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, + {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, +] + +[[package]] +name = "traitlets" +version = "5.9.0" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.7" +files = [ + {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, + {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] + +[[package]] +name = "types-pytz" +version = "2023.3.0.1" +description = "Typing stubs for pytz" +optional = false +python-versions = "*" +files = [ + {file = "types-pytz-2023.3.0.1.tar.gz", hash = "sha256:1a7b8d4aac70981cfa24478a41eadfcd96a087c986d6f150d77e3ceb3c2bdfab"}, + {file = "types_pytz-2023.3.0.1-py3-none-any.whl", hash = "sha256:65152e872137926bb67a8fe6cc9cfd794365df86650c5d5fdc7b167b0f38892e"}, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.11" +description = "Typing stubs for PyYAML" +optional = false +python-versions = "*" +files = [ + {file = "types-PyYAML-6.0.12.11.tar.gz", hash = "sha256:7d340b19ca28cddfdba438ee638cd4084bde213e501a3978738543e27094775b"}, + {file = "types_PyYAML-6.0.12.11-py3-none-any.whl", hash = "sha256:a461508f3096d1d5810ec5ab95d7eeecb651f3a15b71959999988942063bf01d"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "urllib3" +version = "2.0.4" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, + {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "virtualenv" +version = "20.24.5" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"}, + {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<4" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "xarray" +version = "2023.8.0" +description = "N-D labeled arrays and datasets in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "xarray-2023.8.0-py3-none-any.whl", hash = "sha256:eb42b56aea2c7d5db2a7d0c33fb005b78eb5c4421eb747f2ced138c70b5c204e"}, + {file = "xarray-2023.8.0.tar.gz", hash = "sha256:825c6d64202a731a4e49321edd1e9dfabf4be06802f1b8c8a3c00a3ebfc8cedf"}, +] + +[package.dependencies] +numpy = ">=1.21" +packaging = ">=21.3" +pandas = ">=1.4" + +[package.extras] +accel = ["bottleneck", "flox", "numbagg", "scipy"] +complete = ["bottleneck", "cftime", "dask[complete]", "flox", "fsspec", "h5netcdf", "matplotlib", "nc-time-axis", "netCDF4", "numbagg", "pooch", "pydap", "scipy", "seaborn", "zarr"] +docs = ["bottleneck", "cftime", "dask[complete]", "flox", "fsspec", "h5netcdf", "ipykernel", "ipython", "jupyter-client", "matplotlib", "nbsphinx", "nc-time-axis", "netCDF4", "numbagg", "pooch", "pydap", "scanpydoc", "scipy", "seaborn", "sphinx-autosummary-accessors", "sphinx-rtd-theme", "zarr"] +io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap", "scipy", "zarr"] +parallel = ["dask[complete]"] +viz = ["matplotlib", "nc-time-axis", "seaborn"] + +[[package]] +name = "zipp" +version = "3.16.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.9,<3.12" +content-hash = "8e793db7290f8a86f60f35a23a53854f72aabc094d4ecde0ddbc2a9214165f2e" diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 00000000..dcd755d1 --- /dev/null +++ b/poetry.toml @@ -0,0 +1,6 @@ +# This tells poetry to build the cfspopcon virtual environment +# in a .venv folder inside the cfspopcon repository. This makes +# it easier to clean up afterwards (just delete the folder) +# and to find the virtual environment to use with the Jupyter +# notebooks. +virtualenvs.in-project = true \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..dad822fc --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,114 @@ +[tool.black] +line-length = 140 +target-version = ['py39', 'py310', 'py311'] + +[tool.poetry] +name = "cfspopcon" +version = "4.0.0" +description = "Empirically-derived scoping of tokamak operational space." +authors = ["Commonwealth Fusion Systems"] +classifiers = [ +"Development Status :: 5 - Production/Stable", +"Intended Audience :: Science/Research", +"Programming Language :: Python :: 3", +"Programming Language :: Python :: 3.9", +"Programming Language :: Python :: 3.10", +"Programming Language :: Python :: 3.11", +"Programming Language :: Python :: 3 :: Only", +"Topic :: Scientific/Engineering :: Physics", +"License :: OSI Approved :: MIT License", +] + + +[tool.poetry.scripts] +popcon = 'cfspopcon.cli:run_popcon_cli' + +[tool.poetry.dependencies] +python = ">=3.9,<3.12" +numpy = "^1.22.4" +pandas = "^1.4" +scipy = "^1.8" +seaborn = "^0.12" +pyyaml = "^6.0" +toml = "^0.10.2" +typing-extensions = "^4.0.1" +pint = "^0.22" +xarray = "^2023.4.1" +pint-xarray = "^0.3" +ipdb = "^0.13.13" +click = "^8.1.0" + +[tool.poetry.group.dev.dependencies] +pre-commit = "^2.20.0" +black = "^22.10.0" +pytest = "^7.2.0" +coverage = "^6.5.0" +pytest-cov = "^4.0.0" +types-pyyaml = "^6.0.12.2" +pandas-stubs = "^1.5.1.221024" +mypy = "^1.4.1" +sphinx = "^7.2.6" +sphinx-rtd-theme = "^2.0.0rc2" +sphinxcontrib-bibtex = "^2.6.1" +sphinx-copybutton = "^0.5.2" +ruff = "^0.0.292" +nbmake = "^1.4.3" +nbsphinx = "^0.9.3" + +[tool.coverage.report] +fail_under = 82 + +[tool.pytest.ini_options] +addopts = "--cov=cfspopcon --cov-report term-missing --cov-report xml:coverage.xml --verbose -s --nbmake" +testpaths = [ + "tests", + "docs/doc_sources" +] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.mypy] +plugins = "numpy.typing.mypy_plugin" +strict = true +disallow_any_generics=false +exclude = [ + '^cfspopcon/plotting/.*\.py$', # these need to fixed +] + +[tool.ruff] +select = [ + "A", # avoid shadowing + "B", # flake8-bugbear + "C4", # comprehensions + "D", #docstrings + "E", # pycodestyle Errors + "ERA", # no commented out code + "F", # pyflakes + "FLY", # flynt + "I001", # isort + "ISC", # implicit string concatenation + "PERF", # Perflint + "PIE", # flake8-pie + "PGH", # pygrep-hooks + "PL", # pylint + "Q", # flake8-quotes + "RUF", # ruff builtins e.g. noqa checking + "T10", # flake8-debugger (no breakpoint etc) + "TCH",# type-checking imports + "UP", # pyupgrade + "W", # pycodestyle warnings + ] + +ignore = [ + "E501", # Never enforce line length violations, we have black for that. + "PLR0913", #ignore limit on number of args + "PLR2004", #ignore magic values warning, at least for now + "C408", # use {} instead of dict(), but we use dict heavily, for now leave it +] +pyupgrade.keep-runtime-typing=true +pydocstyle.convention = "google" +target-version = "py39" +line-length = 140 + diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..9e4a7b42 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,40 @@ +from pathlib import Path + +import pytest +import yaml + + +@pytest.fixture(scope="session") +def test_directory() -> Path: + path = Path(__file__).parent + assert path.exists() + return path + + +@pytest.fixture(scope="session") +def repository_directory(test_directory) -> Path: + path = test_directory.parent + assert path.exists() + return path + + +@pytest.fixture(scope="session") +def module_directory(repository_directory) -> Path: + path = repository_directory / "cfspopcon" + assert path.exists() + return path + + +@pytest.fixture(scope="session") +def cases_directory(repository_directory) -> Path: + path = repository_directory / "example_cases" + assert path.exists() + return path + + +@pytest.fixture(scope="session") +def example_inputs(cases_directory) -> dict: + filepath = cases_directory / "SPARC_PRD" / "input.yaml" + assert filepath.exists() + + return yaml.safe_load(filepath) diff --git a/tests/regression_results/PRD.json b/tests/regression_results/PRD.json new file mode 100644 index 00000000..e32ad68e --- /dev/null +++ b/tests/regression_results/PRD.json @@ -0,0 +1,1101 @@ +{ + "coords": { + "dim_species": { + "dims": [ + "dim_0" + ], + "attrs": {}, + "data": [ + "Tungsten", + "Helium", + "Oxygen" + ] + }, + "dim_average_electron_density": { + "dims": [], + "attrs": {}, + "data": 25.0 + }, + "dim_average_electron_temp": { + "dims": [], + "attrs": {}, + "data": 9.137931034482758 + } + }, + "attrs": {}, + "dims": { + "dim_0": 3, + "dim_species": 3, + "dim_rho": 50 + }, + "data_vars": { + "major_radius": { + "dims": [], + "attrs": { + "units": "meter" + }, + "data": 1.85 + }, + "magnetic_field_on_axis": { + "dims": [], + "attrs": { + "units": "tesla" + }, + "data": 12.2 + }, + "inverse_aspect_ratio": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.3081 + }, + "areal_elongation": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.75 + }, + "elongation_ratio_sep_to_areal": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.125 + }, + "triangularity_psi95": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.3 + }, + "triangularity_ratio_sep_to_psi95": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.8 + }, + "plasma_current": { + "dims": [], + "attrs": { + "units": "ampere" + }, + "data": 8700000.0 + }, + "fraction_of_external_power_coupled": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.9 + }, + "fusion_reaction": { + "dims": [], + "attrs": {}, + "data": "DT" + }, + "heavier_fuel_species_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.5 + }, + "profile_form": { + "dims": [], + "attrs": {}, + "data": "prf" + }, + "normalized_inverse_temp_scale_length": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 2.5 + }, + "electron_density_peaking_offset": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": -0.1 + }, + "ion_density_peaking_offset": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": -0.2 + }, + "temperature_peaking": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 2.5 + }, + "ion_to_electron_temp_ratio": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.0 + }, + "confinement_threshold_scalar": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.0 + }, + "confinement_time_scalar": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.0 + }, + "energy_confinement_scaling": { + "dims": [], + "attrs": {}, + "data": "ITER98y2" + }, + "radiated_power_method": { + "dims": [], + "attrs": {}, + "data": "Radas" + }, + "radiated_power_scalar": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.0 + }, + "minimum_core_radiated_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.0 + }, + "impurities": { + "dims": [ + "dim_species" + ], + "attrs": { + "units": "dimensionless" + }, + "data": [ + 1.5e-05, + 0.06, + 0.0031 + ] + }, + "core_radiator": { + "dims": [], + "attrs": {}, + "data": "Xenon" + }, + "nesep_over_nebar": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.3 + }, + "toroidal_flux_expansion": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.6974 + }, + "parallel_connection_length": { + "dims": [], + "attrs": { + "units": "meter" + }, + "data": 30.0 + }, + "lambda_q_scaling": { + "dims": [], + "attrs": {}, + "data": "EichRegression15" + }, + "lambda_q_factor": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.0 + }, + "SOL_momentum_loss_function": { + "dims": [], + "attrs": {}, + "data": "KotovReiter" + }, + "fraction_of_P_SOL_to_divertor": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.6 + }, + "kappa_e0": { + "dims": [], + "attrs": { + "units": "watt / electron_volt ** 3.5 / meter" + }, + "data": 2600.0 + }, + "target_electron_temp": { + "dims": [], + "attrs": { + "units": "electron_volt" + }, + "data": 25.0 + }, + "average_electron_density": { + "dims": [], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": 25.0 + }, + "average_electron_temp": { + "dims": [], + "attrs": { + "units": "kiloelectron_volt" + }, + "data": 9.137931034482758 + }, + "separatrix_elongation": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.96875 + }, + "separatrix_triangularity": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.54 + }, + "minor_radius": { + "dims": [], + "attrs": { + "units": "meter" + }, + "data": 0.569985 + }, + "vertical_minor_radius": { + "dims": [], + "attrs": { + "units": "meter" + }, + "data": 1.1221579687499998 + }, + "plasma_volume": { + "dims": [], + "attrs": { + "units": "meter ** 3" + }, + "data": 19.79484837055445 + }, + "surface_area": { + "dims": [], + "attrs": { + "units": "meter ** 2" + }, + "data": 55.536257947812175 + }, + "f_shaping": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 2.6721853873123846 + }, + "q_star": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 3.2902757162288694 + }, + "fuel_average_mass_number": { + "dims": [], + "attrs": { + "units": "unified_atomic_mass_unit" + }, + "data": 2.5 + }, + "average_ion_temp": { + "dims": [], + "attrs": { + "units": "kiloelectron_volt" + }, + "data": 9.137931034482758 + }, + "impurity_charge_state": { + "dims": [ + "dim_species" + ], + "attrs": { + "units": "dimensionless" + }, + "data": [ + 58.37812639204965, + 1.9999999473503665, + 7.999453250480196 + ] + }, + "z_effective": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.343818980316905 + }, + "dilution": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.8543260261866087 + }, + "summed_impurity_density": { + "dims": [], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": 1.5778750000000001 + }, + "average_ion_density": { + "dims": [], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": 21.358150654665216 + }, + "plasma_stored_energy": { + "dims": [], + "attrs": { + "units": "megajoule" + }, + "data": 20.838369393350952 + }, + "energy_confinement_time": { + "dims": [], + "attrs": { + "units": "second" + }, + "data": 0.6623168189838371 + }, + "P_in": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 31.462841945222415 + }, + "beta_toroidal": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.012360853882996833 + }, + "beta_poloidal": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.19742242875250135 + }, + "beta": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.011632527455851185 + }, + "normalized_beta": { + "dims": [], + "attrs": { + "units": "meter * percent * tesla / megaampere" + }, + "data": 0.9297754847754564 + }, + "effective_collisionality": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.07443149734873825 + }, + "ion_density_peaking": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.4011372596580545 + }, + "electron_density_peaking": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.5011372596580543 + }, + "peak_electron_density": { + "dims": [], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": 37.52843149145136 + }, + "peak_fuel_ion_density": { + "dims": [], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": 29.925700679641505 + }, + "peak_electron_temp": { + "dims": [], + "attrs": { + "units": "kiloelectron_volt" + }, + "data": 22.844827586206897 + }, + "peak_ion_temp": { + "dims": [], + "attrs": { + "units": "kiloelectron_volt" + }, + "data": 22.844827586206897 + }, + "rho": { + "dims": [ + "dim_rho" + ], + "attrs": { + "units": "dimensionless" + }, + "data": [ + 0.0, + 0.02, + 0.04, + 0.06, + 0.08, + 0.1, + 0.12, + 0.14, + 0.16, + 0.18, + 0.2, + 0.22, + 0.24, + 0.26, + 0.28, + 0.3, + 0.32, + 0.34, + 0.36, + 0.38, + 0.4, + 0.42, + 0.44, + 0.46, + 0.48, + 0.5, + 0.52, + 0.54, + 0.56, + 0.58, + 0.6, + 0.62, + 0.64, + 0.66, + 0.68, + 0.7000000000000001, + 0.72, + 0.74, + 0.76, + 0.78, + 0.8, + 0.8200000000000001, + 0.84, + 0.86, + 0.88, + 0.9, + 0.92, + 0.9400000000000001, + 0.96, + 0.98 + ] + }, + "electron_density_profile": { + "dims": [ + "dim_rho" + ], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": [ + 37.53973991173976, + 37.525773878667486, + 37.48390694669497, + 37.414232501660116, + 37.31690580091254, + 37.19214339685033, + 37.04022233407129, + 36.86147912430463, + 36.65630850443169, + 36.425161984011304, + 36.16854618978988, + 35.88702101569157, + 35.58119758774254, + 35.2517360542804, + 34.899343212629205, + 34.524769984176736, + 34.12880875047038, + 33.712290563546276, + 33.27608224422068, + 32.821083382500014, + 32.34822325460498, + 31.858457671353335, + 31.35276577280437, + 30.832146784137247, + 30.29761674771379, + 29.75020524616831, + 29.191315206719494, + 28.635808239756525, + 28.090872498795516, + 27.55630681476778, + 27.031913846826107, + 26.51750000949417, + 26.012875401202333, + 25.517853734183333, + 25.032252265702123, + 24.55589173059437, + 24.088596275088708, + 23.63019339188838, + 23.18051385648825, + 22.739391664703735, + 22.306663971388474, + 21.882171030318258, + 21.46575613521895, + 21.057265561916612, + 20.65654851158853, + 20.263457055094147, + 19.877846078365405, + 19.313144858739772, + 18.306469509218292, + 11.626327009971213 + ] + }, + "fuel_ion_density_profile": { + "dims": [ + "dim_rho" + ], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": [ + 29.93008777129205, + 29.921121867704638, + 29.89424026876438, + 29.84949126169168, + 29.786955164570898, + 29.70674408613263, + 29.60900159085816, + 29.493902270806633, + 29.36165122595213, + 29.21248345519584, + 29.04666316058415, + 28.86448296761599, + 28.66626306486003, + 28.452350266421917, + 28.22311700110349, + 27.97896023237639, + 27.720300313552418, + 27.44757978276909, + 27.161262102621862, + 26.86183034946199, + 26.549785857541163, + 26.225646823319906, + 25.88994687536565, + 25.5432336153486, + 25.186067135698064, + 24.819018519509868, + 24.442913113607805, + 24.067691512122792, + 23.69822991352968, + 23.334439896391167, + 22.976234396621773, + 22.623527686651272, + 22.276235354907886, + 21.93427428561651, + 21.597562638906986, + 21.266019831227815, + 20.939566516060445, + 20.618124564929666, + 20.301617048705527, + 19.989968219192242, + 19.683103490999756, + 19.380949423693576, + 19.083433704218645, + 18.790485129592994, + 18.50203358986711, + 18.21801005134483, + 17.93834654006188, + 17.52688019511696, + 16.61331182624222, + 10.551012903566784 + ] + }, + "electron_temp_profile": { + "dims": [ + "dim_rho" + ], + "attrs": { + "units": "kiloelectron_volt" + }, + "data": [ + 22.81700031005393, + 22.794916213858393, + 22.72879209094119, + 22.61901119942156, + 22.46620818995649, + 22.271262994778876, + 22.035292388010884, + 21.759639330503582, + 21.44586024142759, + 21.095710365374412, + 20.71112742738783, + 20.294213788755364, + 19.84721733324049, + 19.372511326493818, + 18.872573500483547, + 18.349964619853683, + 17.807306788148814, + 17.247261748912724, + 16.672509429922524, + 16.085726968478994, + 15.489568442015889, + 14.886645511652285, + 14.279509167072204, + 13.67063273969366, + 13.06239632792736, + 12.457072753886544, + 11.857198932297228, + 11.278916509472818, + 10.728837253556305, + 10.205585679849829, + 9.707853386836657, + 9.234395784495796, + 8.784028982178587, + 8.355626828265335, + 7.948118094199611, + 7.560483795858814, + 7.1917546455630434, + 6.841008628350937, + 6.50736869646198, + 6.190000576260198, + 5.888110682115468, + 5.600944132026026, + 5.327782860020225, + 5.067943820617523, + 4.820777280858972, + 4.585665195636339, + 4.36201966225737, + 4.046835325082298, + 3.835898711955329, + 2.4361558507970544 + ] + }, + "ion_temp_profile": { + "dims": [ + "dim_rho" + ], + "attrs": { + "units": "kiloelectron_volt" + }, + "data": [ + 22.81700031005393, + 22.794916213858393, + 22.72879209094119, + 22.61901119942156, + 22.46620818995649, + 22.271262994778876, + 22.035292388010884, + 21.759639330503582, + 21.44586024142759, + 21.095710365374412, + 20.71112742738783, + 20.294213788755364, + 19.84721733324049, + 19.372511326493818, + 18.872573500483547, + 18.349964619853683, + 17.807306788148814, + 17.247261748912724, + 16.672509429922524, + 16.085726968478994, + 15.489568442015889, + 14.886645511652285, + 14.279509167072204, + 13.67063273969366, + 13.06239632792736, + 12.457072753886544, + 11.857198932297228, + 11.278916509472818, + 10.728837253556305, + 10.205585679849829, + 9.707853386836657, + 9.234395784495796, + 8.784028982178587, + 8.355626828265335, + 7.948118094199611, + 7.560483795858814, + 7.1917546455630434, + 6.841008628350937, + 6.50736869646198, + 6.190000576260198, + 5.888110682115468, + 5.600944132026026, + 5.327782860020225, + 5.067943820617523, + 4.820777280858972, + 4.585665195636339, + 4.36201966225737, + 4.046835325082298, + 3.835898711955329, + 2.4361558507970544 + ] + }, + "P_radiation": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 5.871591678614546 + }, + "core_radiator_concentration": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.0 + }, + "P_radiated_by_core_radiator": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 0.0 + }, + "core_radiator_charge_state": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 45.77499167746534 + }, + "zeff_change_from_core_rad": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.0 + }, + "dilution_change_from_core_rad": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.0 + }, + "P_fusion": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 112.79346348616448 + }, + "P_neutron": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 90.23477078893161 + }, + "P_alpha": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 22.558692697232903 + }, + "P_external": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 8.904149247989512 + }, + "P_launched": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 9.893499164432791 + }, + "Q": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 11.40076545330472 + }, + "neutron_power_flux_to_walls": { + "dims": [], + "attrs": { + "units": "megawatt / meter ** 2" + }, + "data": 1.624790256371358 + }, + "neutron_rate": { + "dims": [], + "attrs": { + "units": "1 / second" + }, + "data": 4.00000810164065e+19 + }, + "bootstrap_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.08515117576845077 + }, + "spitzer_resistivity": { + "dims": [], + "attrs": { + "units": "meter * ohm" + }, + "data": 1.0136457814443183e-09 + }, + "trapped_particle_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 2.377505168672477 + }, + "neoclassical_loop_resistivity": { + "dims": [], + "attrs": { + "units": "meter * ohm" + }, + "data": 2.9146805798816443e-09 + }, + "loop_voltage": { + "dims": [], + "attrs": { + "units": "volt" + }, + "data": 0.1509719887879264 + }, + "P_ohmic": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 1.2016139539804378 + }, + "P_auxillary": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 7.702535294009074 + }, + "P_sol": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 25.59125026660787 + }, + "average_total_pressure": { + "dims": [], + "attrs": { + "units": "pascal" + }, + "data": 732028.9793275861 + }, + "PB_over_R": { + "dims": [], + "attrs": { + "units": "megawatt * tesla / meter" + }, + "data": 168.76392067708971 + }, + "PBpRnSq": { + "dims": [], + "attrs": { + "units": "megawatt * tesla / _1e20_per_cubic_metre ** 2 / meter" + }, + "data": 8.206676168550032 + }, + "B_pol_out_mid": { + "dims": [], + "attrs": { + "units": "tesla" + }, + "data": 3.0527119151332296 + }, + "B_t_out_mid": { + "dims": [], + "attrs": { + "units": "tesla" + }, + "data": 9.326504089901384 + }, + "fieldline_pitch_at_omp": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 3.214648364176006 + }, + "lambda_q": { + "dims": [], + "attrs": { + "units": "millimeter" + }, + "data": 0.28326855346030794 + }, + "q_parallel": { + "dims": [], + "attrs": { + "units": "gigawatt / meter ** 2" + }, + "data": 11.460018573149283 + }, + "q_perp": { + "dims": [], + "attrs": { + "units": "megawatt / meter ** 2" + }, + "data": 5941.561499571544 + }, + "upstream_electron_temp": { + "dims": [], + "attrs": { + "units": "electron_volt" + }, + "data": 299.12304931555707 + }, + "target_electron_density": { + "dims": [], + "attrs": { + "units": "_1e19_per_cubic_metre" + }, + "data": 44.86845739733103 + }, + "SOL_power_loss_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.9639674438709462 + }, + "target_electron_flux": { + "dims": [], + "attrs": { + "units": "1 / meter ** 2 / second" + }, + "data": 1.971000727006153e+25 + }, + "target_q_parallel": { + "dims": [], + "attrs": { + "units": "gigawatt / meter ** 2" + }, + "data": 0.41293376247700014 + }, + "greenwald_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.2932901530528177 + }, + "P_LH_thresh": { + "dims": [], + "attrs": { + "units": "megawatt" + }, + "data": 24.59383938922551 + }, + "ratio_of_P_SOL_to_P_LH": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 1.0405553139384702 + }, + "core_radiated_power_fraction": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.18661987651456066 + }, + "nu_star": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.023749179486475976 + }, + "rho_star": { + "dims": [], + "attrs": { + "units": "dimensionless" + }, + "data": 0.0022127891680210022 + }, + "fusion_triple_product": { + "dims": [], + "attrs": { + "units": "_1e20_per_cubic_metre * kiloelectron_volt * second" + }, + "data": 45.2791219241439 + }, + "peak_pressure": { + "dims": [], + "attrs": { + "units": "pascal" + }, + "data": 2468918.97623166 + }, + "current_relaxation_time": { + "dims": [], + "attrs": { + "units": "second" + }, + "data": 16.361532562672082 + } + } +} \ No newline at end of file diff --git a/tests/regression_results/SPARC_PRD_result.nc b/tests/regression_results/SPARC_PRD_result.nc new file mode 100644 index 00000000..c00afd12 Binary files /dev/null and b/tests/regression_results/SPARC_PRD_result.nc differ diff --git a/tests/regression_results/generate_regression_results.py b/tests/regression_results/generate_regression_results.py new file mode 100644 index 00000000..f643424c --- /dev/null +++ b/tests/regression_results/generate_regression_results.py @@ -0,0 +1,25 @@ +from pathlib import Path + +import xarray as xr + +from cfspopcon.file_io import write_dataset_to_netcdf, write_point_to_file +from cfspopcon.input_file_handling import read_case + +CASES_DIR = Path(__file__).parent.parent.parent / "example_cases" +ALL_CASE_PATHS = list(CASES_DIR.rglob("input.yaml")) +ALL_CASE_NAMES = [path.parent.relative_to(CASES_DIR).stem for path in ALL_CASE_PATHS] + +if __name__ == "__main__": + + for case in ALL_CASE_PATHS: + + input_parameters, algorithm, points = read_case(case) + + dataset = xr.Dataset(input_parameters) + + dataset = algorithm.update_dataset(dataset) + + write_dataset_to_netcdf(dataset, Path(__file__).parent / f"{case.parent.stem}_result.nc") + + for point, point_params in points.items(): + write_point_to_file(dataset, point, point_params, output_dir=Path(__file__).parent) diff --git a/tests/test_algorithms_class.py b/tests/test_algorithms_class.py new file mode 100644 index 00000000..7579ffb6 --- /dev/null +++ b/tests/test_algorithms_class.py @@ -0,0 +1,275 @@ +import contextlib +from typing import Any + +import pytest +import xarray as xr + +from cfspopcon.algorithms import get_algorithm +from cfspopcon.algorithms.algorithm_class import Algorithm, CompositeAlgorithm +from cfspopcon.named_options import Algorithms +from cfspopcon.unit_handling import ureg + + +@pytest.fixture() +def BIRDS(): + return [ + "ducks", + "chooks", + "all_birds", + ] + + +@pytest.fixture() +def how_many_birds(BIRDS): + def count_birds(things_that_quack: int, things_that_cluck: int = 2) -> dict[str, Any]: + ducks = things_that_quack + chooks = things_that_cluck + all_birds = ducks + chooks + + local_vars = locals() + return {key: local_vars[key] for key in BIRDS} + + return Algorithm(function=count_birds, return_keys=BIRDS) + + +@pytest.fixture() +def ANIMALS(): + return [ + "sheep", + "all_birds", + "all_animals", + ] + + +@pytest.fixture() +def how_many_animals(ANIMALS): + def count_animals(things_that_baa: int, all_birds: int, new_chickens_per_count: int = 2) -> dict[str, Any]: + sheep = things_that_baa + + all_birds = all_birds + new_chickens_per_count + all_animals = sheep + all_birds + + local_vars = locals() + return {key: local_vars[key] for key in ANIMALS} + + return Algorithm(function=count_animals, return_keys=ANIMALS) + + +def test_algorithm_kw_only(): + def test(p1, p2, /, p_or_kw, *, kw): + return {"p2_2": 10} + + with pytest.raises(ValueError, match="Algorithm only supports functions with keyword arguments.*?POSITIONAL_ONLY parameter p1"): + _ = Algorithm(function=test, return_keys=["p2_2"]) + + +def test_composite_signature(how_many_birds, how_many_animals): + composite = how_many_birds + how_many_animals + assert ( + str(composite.run.__signature__) + == "(things_that_quack: int, things_that_baa: int, things_that_cluck: int = 2, new_chickens_per_count: int = 2) -> xarray.core.dataset.Dataset" + ) + + +def test_dummy_algorithm(how_many_birds, BIRDS): + + assert how_many_birds.return_keys == BIRDS + assert how_many_birds.input_keys == ["things_that_quack", "things_that_cluck"] + assert how_many_birds.required_input_keys == ["things_that_quack"] + assert how_many_birds.default_keys == ["things_that_cluck"] + assert how_many_birds.default_values["things_that_cluck"] == 2 + + with contextlib.redirect_stdout(None): + repr(how_many_birds) + + result = how_many_birds.run(things_that_quack=1) + assert result["all_birds"] == 3 + assert result["ducks"] == 1 + assert result["chooks"] == 2 + + ds = xr.Dataset(dict(things_that_quack=3)) + resulting_ds = how_many_birds.update_dataset(ds) + assert resulting_ds["all_birds"] == 5 + assert resulting_ds["ducks"] == 3 + assert resulting_ds["chooks"] == 2 + + ds = xr.Dataset(dict(things_that_cluck=3)) + with pytest.raises(KeyError): + resulting_ds = how_many_birds.update_dataset(ds) + + +def test_dummy_composite_algorithm(how_many_birds, BIRDS, how_many_animals, ANIMALS): + + count_the_farm = how_many_birds + how_many_animals + + assert set(count_the_farm.return_keys) == set(BIRDS).union(set(ANIMALS)) + assert set(count_the_farm.input_keys) == {"things_that_quack", "things_that_cluck", "things_that_baa", "new_chickens_per_count"} + assert set(count_the_farm.required_input_keys) == {"things_that_quack", "things_that_baa"} + + with contextlib.redirect_stdout(None): + repr(count_the_farm) + + with pytest.warns(): + result = count_the_farm.run(things_that_quack=1, things_that_baa=4, crocodiles=3) + + assert result["all_birds"] == 5 # N.b. this includes the new chickens + assert result["ducks"] == 1 + assert result["chooks"] == 2 + assert result["sheep"] == 4 + assert result["all_animals"] == 9 + + ds = xr.Dataset(dict(things_that_quack=1, things_that_baa=4, crocodiles=3)) + ds = count_the_farm.update_dataset(ds) + assert ds["all_birds"] == 5 # N.b. this includes the new chickens + assert ds["ducks"] == 1 + assert ds["chooks"] == 2 + assert ds["sheep"] == 4 + assert ds["all_animals"] == 9 + + # Here is a subtlety which is worth considering + # If we call count_the_farm again, how many birds will we have? + # At first glance, we could have 7, since we add 2 new chickens + # each time we call count_the_farm + # However, we actually still have just 5. Why? When we call + # update_dataset, we first call how_many_birds, which sets + # all_birds = ducks + chooks, ignoring the number of chickens + # that we have. Then, all_birds gets passed to how_many_animals + # where we add two more chickens. + # + # A few conclusions + # 1. You should be very careful when relying on the internal + # state of the dataset. The .run() method is more explicit + # and can help to catch some of these tricky cases. + # 2. The algorithm is doing what we asked of it. To be sure, + # see test_repeated_dataset_updates + # 3. Before writing a big unit test, ask yourself how much you + # want to commit to the whole farm thing and not just call + # your variables something boring like 'a' or 'my_var' + # 4. Be careful counting your chickens before they've hatched. + ds = count_the_farm.update_dataset(ds) + assert ds["all_birds"] == 5 + + +def test_composite_of_composite(how_many_birds: Algorithm, how_many_animals: Algorithm): + # add of Algorihtm + Composite should flatten into Composite of all Algorithms + count_the_farm = how_many_birds + CompositeAlgorithm([how_many_animals, how_many_animals]) + # thus the lenght of algorithms should be 3 + assert len(count_the_farm.algorithms) == 3 + + ds = xr.Dataset(dict(things_that_quack=1, things_that_baa=4, crocodiles=3)) + ds = count_the_farm.update_dataset(ds) + assert ds["all_animals"] == 11 # Each time we count how many animals, we get two new chickens + + # test the flattening of composites in __init__ and __add__ + comp = CompositeAlgorithm([how_many_birds, count_the_farm]) + assert len(comp.algorithms) == 4 + comp2 = comp + how_many_birds + assert len(comp2.algorithms) == 5 + comp3 = comp + comp2 + assert len(comp3.algorithms) == 9 + + with pytest.raises(TypeError, match=".*missing arguments.*"): + _ = count_the_farm.run() + + input_ds = xr.Dataset(dict(things_that_quack=1, things_that_baa=4)) + with pytest.warns(UserWarning, match="The following variables were overridden.*"): + assert count_the_farm.validate_inputs( + input_ds, + quiet=False, + raise_error_on_missing_inputs=True, + warn_for_overridden_variables=True, + ) + + input_ds["crocodiles"] = 10 + with pytest.warns(UserWarning, match="Unused input parameters .crocodiles.."): + ret = count_the_farm.validate_inputs( + input_ds, + quiet=False, + raise_error_on_missing_inputs=True, + warn_for_overridden_variables=False, + ) + + assert ret is False + + # missing + unused now + input_ds = input_ds.drop_vars("things_that_baa") + with pytest.raises(RuntimeError, match="Missing input parameters.*Also had unused.*"): + count_the_farm.validate_inputs( + input_ds, + quiet=False, + raise_error_on_missing_inputs=True, + warn_for_overridden_variables=False, + ) + + # missing only + input_ds = input_ds.drop_vars("crocodiles") + with pytest.raises(RuntimeError, match="Missing input parameters .things_that_baa.."): + count_the_farm.validate_inputs( + input_ds, + quiet=False, + raise_error_on_missing_inputs=True, + warn_for_overridden_variables=False, + ) + + wrong_order_comp = how_many_animals + how_many_birds + with pytest.raises(RuntimeError, match="Algorithms out of order. all_birds needed by Algorithm.*"): + wrong_order_comp.validate_inputs( + input_ds, + quiet=False, + raise_error_on_missing_inputs=True, + warn_for_overridden_variables=False, + ) + + +def test_repeated_dataset_updates(how_many_animals): + + ds = xr.Dataset(dict(all_birds=0, things_that_baa=0, new_chickens_per_count=1)) + ds = how_many_animals.update_dataset(ds) + assert ds["all_animals"] == 1 + ds["new_chickens_per_count"] = 10 + ds = how_many_animals.update_dataset(ds) + assert ds["all_animals"] == 11 + + composite = how_many_animals + how_many_animals + ds = xr.Dataset(dict(all_birds=0, things_that_baa=0, new_chickens_per_count=11)) + ds = composite.update_dataset(ds) + assert ds["all_animals"] == 22 + + +def test_composite_of_a_single_algorithm_fails(how_many_birds): + + with pytest.raises(TypeError): + CompositeAlgorithm(how_many_birds) + + +def test_single_function_algorithm(): + def dummy_func(a, b): + """A very descriptive docstring.""" + c, d = b, a + return c, d + + alg = Algorithm.from_single_function(dummy_func, return_keys=["c", "d"], name="test_dummy", skip_unit_conversion=True) + + result = alg.run(a=1, b=2) + assert result["c"] == 2 + assert result["d"] == 1 + + def in_and_out(average_electron_density): + return average_electron_density * 2 + + alg = Algorithm.from_single_function(in_and_out, return_keys=["average_electron_density"], name="test_dummy_in_and_out") + result = alg.run(average_electron_density=1.2 * ureg.n20) + assert result["average_electron_density"] == 24.0 * ureg.n19 + + +def test_get_algorithm(): + + # Pass in Algorithm Enums + for key in Algorithms: + alg = get_algorithm(key) + assert alg._name in [f"run_{key.name}", key.name, ""] + + # Pass in strings instead + for key in Algorithms: + alg = get_algorithm(key.name) + assert alg._name in [f"run_{key.name}", key.name, ""] diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 00000000..654ecd05 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,20 @@ +from pathlib import Path + +import matplotlib +import pytest +from click.testing import CliRunner + +from cfspopcon.cli import run_popcon_cli + + +@pytest.mark.filterwarnings("ignore:Matplotlib is currently using agg") +def test_popcon_cli(): + matplotlib.use("Agg") + + runner = CliRunner() + example_case = Path(__file__).parents[1] / "example_cases" / "SPARC_PRD" + result = runner.invoke( + run_popcon_cli, + [str(example_case), "-p", str(example_case / "plot_popcon.yaml"), "-p", str(example_case / "plot_remapped.yaml"), "--show"], + ) + assert result.exit_code == 0 diff --git a/tests/test_helpers.py b/tests/test_helpers.py new file mode 100644 index 00000000..5261d442 --- /dev/null +++ b/tests/test_helpers.py @@ -0,0 +1,55 @@ +import pytest +import xarray as xr + +from cfspopcon import named_options +from cfspopcon.helpers import ( + convert_named_options, + extend_impurities_array, + make_impurities_array, + make_impurities_array_from_kwargs, +) + + +def test_convert_named_options(): + + for (val, key) in ( + (named_options.Algorithms.predictive_popcon, "algorithms"), + (named_options.ConfinementScaling.ITER98y2, "energy_confinement_scaling"), + (named_options.ProfileForm.analytic, "profile_form"), + (named_options.RadiationMethod.Radas, "radiated_power_method"), + (named_options.ReactionType.DT, "fusion_reaction"), + (named_options.Impurity.Neon, "impurity"), + (named_options.Impurity.Xenon, "core_radiator"), + (named_options.LambdaQScaling.EichRegression15, "lambda_q_scaling"), + (named_options.MomentumLossFunction.KotovReiter, "SOL_momentum_loss_function"), + ): + assert convert_named_options(key=key, val=val.name) == val + + assert convert_named_options(key="ducks", val=23.0) == 23.0 + + da = convert_named_options(key="impurities", val=dict(tungsten=1e-5, helium=1e-2)) + + assert da.sel(dim_species=named_options.Impurity.Tungsten) == 1e-5 + assert da.sel(dim_species=named_options.Impurity.Helium) == 1e-2 + + +def test_impurity_array_helpers(): + + array = xr.DataArray([[1, 2], [3, 4]], coords=dict(a=[1, 2], b=[3, 5])) + + make_impurities_array(xr.DataArray("tungsten"), array) + + from_lists = make_impurities_array([named_options.Impurity.Tungsten, "Xenon"], [array, 2 * array]) + from_kwargs = make_impurities_array_from_kwargs(tungsten=array, xenon=2 * array) + + assert from_lists.equals(from_kwargs) + + from_extension = make_impurities_array(["tungsten"], [array]) + from_extension = extend_impurities_array(from_extension, "xenon", 2 * array) + + assert from_extension.equals(from_kwargs) + + with pytest.raises(ValueError): + from_lists = make_impurities_array("Xenon", [array, 2 * array, 3 * array]) + with pytest.raises(ValueError): + from_lists = make_impurities_array(["Xenon", "tungsten"], [array]) diff --git a/tests/test_infra/conftest.py b/tests/test_infra/conftest.py new file mode 100644 index 00000000..73ff8eb3 --- /dev/null +++ b/tests/test_infra/conftest.py @@ -0,0 +1,42 @@ +import numpy as np +import pytest +import xarray as xr + + +@pytest.fixture() +def x(): + return np.linspace(0, 10, num=400) + + +@pytest.fixture() +def y(): + return np.linspace(-5, 5, num=500) + + +@pytest.fixture() +def z(x, y): + x_grid, y_grid = np.meshgrid(x, y) + return xr.DataArray(x_grid + y_grid, coords=dict(y=y, x=x)) + + +@pytest.fixture() +def z1(x, y): + x_grid, y_grid = np.meshgrid(x, y) + return xr.DataArray(x_grid + y_grid**2, coords=dict(y=y, x=x)) + + +@pytest.fixture() +def z2(x, y): + x_grid, y_grid = np.meshgrid(x, y) + return xr.DataArray(x_grid**2 + y_grid, coords=dict(y=y, x=x)) + + +@pytest.fixture() +def z3(x, y): + x_grid, y_grid = np.meshgrid(x, y) + return xr.DataArray(np.abs(y_grid + x_grid), coords=dict(y=y, x=x)) + + +@pytest.fixture() +def ds(x, y, z, z1, z2, z3): + return xr.Dataset(dict(x=x, y=y, z=z, z1=z1, z2=z2, z3=z3)) diff --git a/tests/test_infra/test_plotting.py b/tests/test_infra/test_plotting.py new file mode 100644 index 00000000..6761b8c0 --- /dev/null +++ b/tests/test_infra/test_plotting.py @@ -0,0 +1,42 @@ +import matplotlib.pyplot as plt +import numpy as np +import pytest + +from cfspopcon import plotting +from cfspopcon.unit_handling import ureg + + +def test_coordinate_formatter(z): + formatter = plotting.CoordinateFormatter(z) + + x_test = 1.23 + y_test = -3.45 + ret_string = formatter(x_test, y_test) + + x_string, y_string, z_string = ret_string.split(",") + + assert np.isclose(float(x_string.split("=")[1]), x_test) + assert np.isclose(float(y_string.split("=")[1]), y_test) + # Nearest-neighbor interpolation is not particularly accurate. + assert np.isclose(float(z_string.split("=")[1]), x_test + y_test, atol=0.01) + + +@pytest.mark.filterwarnings("error") +def test_label_contour(z): + # Make sure that the label contour functionality runs through. + _, ax = plt.subplots() + CS = z.plot.contour(ax=ax, colors=["r"]) + + contour_labels = dict() + contour_labels["z"] = plotting.label_contour(ax=ax, contour_set=CS, format_spec="3.2f", fontsize=12) + + ax.legend(contour_labels.values(), contour_labels.keys()) + + plt.close() + + +def test_units_to_string(): + + assert plotting.units_to_string(ureg.dimensionless) == "" + assert plotting.units_to_string(ureg.m) == "[m]" + assert plotting.units_to_string(ureg.percent) == "[percent]" diff --git a/tests/test_infra/test_point_selection.py b/tests/test_infra/test_point_selection.py new file mode 100644 index 00000000..5a00efd6 --- /dev/null +++ b/tests/test_infra/test_point_selection.py @@ -0,0 +1,21 @@ +import numpy as np + +from cfspopcon.point_selection import find_coords_of_maximum + + +def test_find_coords(ds): + + coords = find_coords_of_maximum(ds.z3) + assert np.isclose(ds.z3.max(), ds.isel(coords).z3) + + coords = find_coords_of_maximum(ds.z3, keep_dims="x") + assert np.allclose(ds.z3.max(dim="y"), ds.isel(coords).z3) + + coords = find_coords_of_maximum(ds.z3, keep_dims="y") + assert np.allclose(ds.z3.max(dim="x"), ds.isel(coords).z3) + + mask = (ds.y < 1.0) & (ds.x < 5.0) + + coords = find_coords_of_maximum(ds.z3, mask=mask) + # z3 is x + y, so must be close to but less than 1 + 5 + assert np.isclose(ds.isel(coords).z3, 6.0, atol=0.1) diff --git a/tests/test_infra/test_transform.py b/tests/test_infra/test_transform.py new file mode 100644 index 00000000..1ffef0c0 --- /dev/null +++ b/tests/test_infra/test_transform.py @@ -0,0 +1,27 @@ +import pytest +import xarray as xr + +from cfspopcon import transform + + +def test_interpolate_onto_new_coords(z, z1, z2): + + z_interp = transform.interpolate_array_onto_new_coords(array=z, new_coords=dict(z1=z1, z2=z2), default_resolution=5) + + assert z_interp.min() >= z.min() + assert z_interp.max() <= z.max() + assert "z1" in z_interp.dims + assert "z2" in z_interp.dims + + +def test_order_dimensions(z): + + assert transform.order_dimensions(z, dims=("x", "y"), order_for_plotting=True).dims == ("y", "x") + assert transform.order_dimensions(z, dims=("x", "y"), order_for_plotting=False).dims == ("x", "y") + + with pytest.raises(ValueError): + assert transform.order_dimensions(z.isel(x=0), dims=("x", "y")).dims == ("x", "y") + + assert transform.order_dimensions(z.isel(x=0), dims=("x", "y"), template=z).dims == ("y", "x") + ds = xr.Dataset(dict(z=z)) + assert transform.order_dimensions(z.isel(x=0), dims=("x", "y"), template=ds).dims == ("y", "x") diff --git a/tests/test_read_atomic_data.py b/tests/test_read_atomic_data.py new file mode 100644 index 00000000..ecd43bfc --- /dev/null +++ b/tests/test_read_atomic_data.py @@ -0,0 +1,20 @@ +import pytest + +import cfspopcon + + +@pytest.mark.filterwarnings("error") +def test_read_atomic_data(): + cfspopcon.atomic_data.read_atomic_data() + + +@pytest.mark.filterwarnings("error") +def test_read_atomic_data_from_explicit_directory(module_directory): + cfspopcon.atomic_data.read_atomic_data(module_directory / "atomic_data") + + +@pytest.mark.filterwarnings("error") +def test_read_atomic_data_from_missing_directory(module_directory): + + with pytest.raises(FileNotFoundError): + cfspopcon.atomic_data.read_atomic_data(module_directory / "this_doesnt_exist") diff --git a/tests/test_regression_against_cases.py b/tests/test_regression_against_cases.py new file mode 100644 index 00000000..0513ae97 --- /dev/null +++ b/tests/test_regression_against_cases.py @@ -0,0 +1,43 @@ +from pathlib import Path + +import pytest +import xarray as xr +from regression_results.generate_regression_results import ( + ALL_CASE_NAMES, + ALL_CASE_PATHS, +) +from xarray.testing import assert_allclose + +from cfspopcon.file_io import read_dataset_from_netcdf +from cfspopcon.input_file_handling import read_case + + +@pytest.mark.parametrize("case", ALL_CASE_PATHS, ids=ALL_CASE_NAMES) +@pytest.mark.filterwarnings("ignore:Not all input parameters were used") +def test_regression_against_case(case: Path): + + input_parameters, algorithm, _ = read_case(case) + case_name = case.parent.stem + + dataset = algorithm.run(**input_parameters) + + reference_dataset = read_dataset_from_netcdf(Path(__file__).parent / "regression_results" / f"{case_name}_result.nc").load() + + assert_allclose(dataset, reference_dataset, rtol=1e-8, atol=0) + + +@pytest.mark.parametrize("case", ALL_CASE_PATHS, ids=ALL_CASE_NAMES) +@pytest.mark.filterwarnings("ignore:Not all input parameters were used") +def test_regression_against_case_with_update(case: Path): + + input_parameters, algorithm, _ = read_case(case) + case_name = case.parent.stem + + dataset = xr.Dataset(input_parameters) + + for alg in algorithm.algorithms: # type: ignore + dataset = alg.update_dataset(dataset) + + reference_dataset = read_dataset_from_netcdf(Path(__file__).parent / "regression_results" / f"{case_name}_result.nc").load() + + assert_allclose(dataset, reference_dataset, rtol=1e-8, atol=0) diff --git a/tests/test_unit_handling/test_custom_units.py b/tests/test_unit_handling/test_custom_units.py new file mode 100644 index 00000000..84314202 --- /dev/null +++ b/tests/test_unit_handling/test_custom_units.py @@ -0,0 +1,13 @@ +import numpy as np + +from cfspopcon.unit_handling import Quantity, ureg + + +def test_custom_units(): + + assert np.isclose(Quantity(10.0, ureg.n19), Quantity(1.0, ureg.n20)) + assert np.isclose(Quantity(1.0, ureg.n19), Quantity(1e19, ureg.m**-3)) + assert np.isclose(Quantity(1.0, ureg.n20), Quantity(1e20, ureg.m**-3)) + + assert np.isclose(Quantity(100.0, ureg.percent), Quantity(1.0, ureg.dimensionless)) + assert np.isclose(Quantity(100.0, ureg.percent), 1.0) diff --git a/tests/test_unit_handling/test_wraps_ufunc_decorator.py b/tests/test_unit_handling/test_wraps_ufunc_decorator.py new file mode 100644 index 00000000..9fac237b --- /dev/null +++ b/tests/test_unit_handling/test_wraps_ufunc_decorator.py @@ -0,0 +1,182 @@ +"""Test the pint-xarray wraps_ufunc decorator.""" + +import warnings + +import numpy as np +import pytest +import xarray as xr + +from cfspopcon.unit_handling import UnitStrippedWarning, dimensionless_magnitude, ureg, wraps_ufunc + + +def check_equal(a, b, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + ratio = a / b + ratio[(a == 0) & (b == 0)] = 1.0 + + return np.allclose(dimensionless_magnitude(ratio), 1.0, **kwargs) + + +@pytest.mark.filterwarnings("error") +def test_wraps_simple(): + @wraps_ufunc(return_units=dict(doubled=None), input_units=dict(x=None)) + def simple_function(x): + return 2 * x + + x_test = xr.DataArray(np.linspace(0.0, 100.0)) + assert check_equal(2.0 * x_test, simple_function(x_test)) + assert isinstance(simple_function(x_test), xr.DataArray) + + x_test_2 = np.linspace(0.0, 100.0) + assert check_equal(2.0 * x_test_2, simple_function(x_test_2)) + + +@pytest.mark.filterwarnings("error") +def test_wraps_with_too_many_input_units(): + + with pytest.raises(ValueError): + + @wraps_ufunc(return_units=dict(result=ureg.m), input_units=dict(a=ureg.m, b=ureg.mm)) + def in_and_out(a): + return a + + +@pytest.mark.filterwarnings("error") +def test_wraps_with_too_many_output_units(): + @wraps_ufunc(return_units=dict(a=ureg.m, b=ureg.m), input_units=dict(a=ureg.m)) + def in_and_out(a): + return a + + with pytest.raises(ValueError): + in_and_out(ureg.Quantity(1.2, ureg.m)) + + +@pytest.mark.filterwarnings("error") +def test_wraps_with_wrong_arguments(): + + with pytest.raises(ValueError): + + @wraps_ufunc(return_units=dict(result=ureg.m), input_units=dict(b=ureg.m)) + def in_and_out(a): + return a + + +@pytest.mark.filterwarnings("error") +def test_jumbled_inputs(): + @wraps_ufunc(return_units=dict(result=ureg.m), input_units=dict(a=ureg.m, b=ureg.m)) + def add_together(a, b): + return a + b + + with pytest.raises(RuntimeError): + add_together(ureg.Quantity(7.0, ureg.mm), a=ureg.Quantity(3.0, ureg.m)) + + +@pytest.mark.filterwarnings("error") +def test_pass_as_kwargs(): + @wraps_ufunc(return_units=dict(result=ureg.m), input_units=dict(a=ureg.m, b=ureg.m), pass_as_kwargs=("a", "b")) + def add_together(a, b): + return a + b + + add_together(a=ureg.Quantity(7.0, ureg.m), b=ureg.Quantity(3.0, ureg.feet)) + + +@pytest.mark.filterwarnings("error") +def test_pass_as_kwargs_in_wrong_order(): + with pytest.raises(ValueError): + + @wraps_ufunc(return_units=dict(result=ureg.m), input_units=dict(a=ureg.m, b=ureg.m), pass_as_kwargs=("a")) + def add_together(a, b): + return a + b + + add_together(a=ureg.Quantity(7.0, ureg.m), b=ureg.Quantity(3.0, ureg.feet)) + + +@pytest.mark.filterwarnings("error") +def test_multiple_return(): + @wraps_ufunc( + return_units=dict(b=ureg.m, a=ureg.m), + input_units=dict(a=ureg.m, b=ureg.m), + output_core_dims=[(), ()], + ) + def swap(a, b): + return b, a + + a = xr.DataArray(ureg.Quantity(np.linspace(0.0, 100.0), ureg.m)) + b = ureg.Quantity(np.pi, ureg.m) + + b2, a2 = swap(a, b) + + assert check_equal(a2, a) + assert np.all(np.abs(b2 - b) < ureg.Quantity(1.0, ureg.mm)) + + assert isinstance(a2, xr.DataArray) + assert isinstance(b2, xr.DataArray) + + assert a2.pint.units == ureg.m + assert b2.pint.units == ureg.m + + +@pytest.mark.filterwarnings("error") +def test_multiple_return_with_wrong_number_of_units(): + @wraps_ufunc(return_units=dict(a=ureg.m), input_units=dict(a=ureg.m, b=ureg.m), output_core_dims=[(), ()]) + def swap(a, b): + return b, a + + a = xr.DataArray(ureg.Quantity(np.linspace(0.0, 100.0), ureg.m)) + b = ureg.Quantity(np.pi, ureg.m) + + with pytest.raises(ValueError): + b2, a2 = swap(a, b) + + +@pytest.mark.filterwarnings("error") +def test_no_return(): + @wraps_ufunc(return_units=dict(), input_units=dict(a=ureg.m)) + def do_nothing(a): + pass + + a = ureg.Quantity(np.pi, ureg.m) + do_nothing(a) + + +@pytest.mark.filterwarnings("error") +def test_no_return_with_too_many_units(): + @wraps_ufunc(return_units=dict(a=ureg.m), input_units=dict(a=ureg.m)) + def do_nothing(a): + pass + + a = ureg.Quantity(np.pi, ureg.m) + + # Returns Quantity(None, ureg.m) + do_nothing(a) + + +@pytest.mark.filterwarnings("error") +def test_illegal_chained_call_input(): + @wraps_ufunc(return_units=dict(doubled=None), input_units=dict(x=ureg.m)) + def simple_function(x): + return 2 * x + + @wraps_ufunc(return_units=dict(doubled=None), input_units=dict(x=ureg.m)) + def simple_function2(x): + return simple_function(x) + + with pytest.raises( + RuntimeError, match=r".*Calling `wraps_ufunc` decorated function from within.*\n.*\n.*\n.*simple_function.unitless_func.*" + ): + simple_function2(10 * ureg.m) + + +@pytest.mark.filterwarnings("error") +def test_illegal_chained_call_ouput(): + @wraps_ufunc(return_units=dict(doubled=ureg.m), input_units=dict(x=None)) + def simple_function(x): + return 2 * x + + @wraps_ufunc(return_units=dict(doubled=ureg.m), input_units=dict(x=None)) + def simple_function2(x): + return simple_function(x) + + with pytest.raises(UnitStrippedWarning): + simple_function2(10)