diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index d722118f..acbca68b 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -5,7 +5,7 @@ on: branches: - '**' - '!joss-paper' - + pull_request: jobs: formatting: runs-on: ubuntu-latest @@ -18,7 +18,7 @@ jobs: testing: needs: formatting runs-on: ubuntu-latest - container: ghcr.io/cosima/regional-test-env:updated + container: ghcr.io/cosima/regional-test-env:updated_curvilinear defaults: run: shell: bash -el {0} @@ -54,7 +54,9 @@ jobs: ln -s /data demos/PATH_TO_GLORYS_DATA ln -s /data demos/PATH_TO_GEBCO_FILE ln -s /build/FRE-NCtools/tools demos/PATH_TO_FRE_TOOLS - python -m pytest --nbval demos/reanalysis-forced.ipynb --nbval-current-env --cov=regional_mom6 --cov-report=xml tests/ + ln -s /data demos/PATH_TO_YOUR_HORIZONTAL_GRID + ln -s /data demos/PATH_TO_ERA5_DATA + python -m pytest --nbval demos/reanalysis-forced.ipynb demos/BYO-domain.ipynb --nbval-current-env --cov=regional_mom6 --cov-report=xml tests/ - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 diff --git a/.gitignore b/.gitignore index d5e30b89..ca12e855 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ regional_mom6.egg-info .env env docker +*.swp inputdir/ rundir/ + diff --git a/__init__.py b/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/demos/BYO-domain.ipynb b/demos/BYO-domain.ipynb new file mode 100644 index 00000000..3ad8f14a --- /dev/null +++ b/demos/BYO-domain.ipynb @@ -0,0 +1,454 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bring-your-own rotated and/or curved domain \n", + "\n", + "This example is forced by GLORYS, ERA5 reanalysis datasets, and TPXO tidal model\n", + "\n", + "**Note**: FRE-NC tools are required to be set up, as outlined in the [documentation](https://regional-mom6.readthedocs.io/en/latest/) of regional-mom6 package. You will also need to ensure that `matplotlib` is installed in your environment. If it's not, you can add a new cell and evaluate `!pip install matplotlib`.\n", + "For this example we need:\n", + "\n", + "- [GEBCO bathymetry](https://www.gebco.net/data_and_products/gridded_bathymetry_data/)\n", + "- [GLORYS ocean reanalysis data](https://data.marine.copernicus.eu/product/GLOBAL_MULTIYEAR_PHY_001_030/description), and\n", + "- [ERA5 surface forcing](https://www.ecmwf.int/en/forecasts/dataset/ecmwf-reanalysis-v5)\n", + "- [TPXO tidal model](https://www.tpxo.net/global)\n", + "\n", + "The example loads the entire ERA5, GEBCO, and TPXO datasets over the whole globe; no need to worry about cutting it down to size.\n", + "\n", + "This example requires you to bring your own MOM6-compatible domain input in netCDF file named `hgrid.nc`. The regional-mom6 package can handle regular, rotated, and curvilinear model domains." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "tags": [ + "nbval-ignore-output" + ] + }, + "outputs": [], + "source": [ + "import warnings\n", + "warnings.filterwarnings(\"ignore\")\n", + "import regional_mom6 as rmom6\n", + "\n", + "import os\n", + "from pathlib import Path\n", + "from dask.distributed import Client\n", + "\n", + "client = Client()\n", + "client\n", + "\n", + "# Currently, only the regional_mom6 module reports logging information to the info level, for more detailed output, uncomment the following:\n", + "# import logging\n", + "# logging.basicConfig(level=logging.INFO) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 1: Choose our domain, define workspace paths\n", + "\n", + "To make sure that things are working we recommend starting with a small domain. If that seems OK, then users can change to the domain of their choice and, hopefully, that runs OK too! You can always check the [README](https://github.com/COSIMA/regional-mom6/blob/main/README.md) and [documentation](https://regional-mom6.readthedocs.io/) for troubleshooting tips." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expt_name = \"rotated-demo\"\n", + "\n", + "date_range = [\"2003-01-01 00:00:00\", \"2003-01-05 00:00:00\"]\n", + "\n", + "## Place where all your input files go \n", + "input_dir = Path(f\"mom6_input_directories/{expt_name}/\")\n", + "\n", + "## Directory where you'll run the experiment from\n", + "run_dir = Path(f\"mom6_run_directories/{expt_name}/\")\n", + "\n", + "## Directory where compiled FRE tools are located (needed for construction of mask tables)\n", + "fre_tools_dir = Path(\"PATH_TO_FRE_TOOLS\")\n", + "\n", + "## Path to where your raw ocean forcing files are stored\n", + "glorys_path = Path(f\"PATH_TO_GLORYS_DATA\" )\n", + "\n", + "## Directory where the ERA raw atmospheric output files are stored\n", + "era_path = Path(\"PATH_TO_ERA5_DATA/era5/single-levels/reanalysis\")\n", + "\n", + "## Location of TPXO raw tidal file\n", + "## Note: users need to swap the ## in the filenames to the version number of the TPXO input files\n", + "tide_h_path = Path(\"PATH_TO_TPXO_H_FILE/h_tpxo##.nc\")\n", + "tide_u_path = Path(\"PATH_TO_TPXO_U_FILE/u_tpxo##.nc\")\n", + "\n", + "## Location of the bring-your-own hgrid file\n", + "byogrid_path = \"PATH_TO_YOUR_HORIZONTAL_GRID/small_curvilinear_hgrid.nc\"\n", + "\n", + "## Location where the bathymetry data is stored\n", + "bathymetry_path = Path(\"PATH_TO_GEBCO_FILE/GEBCO_2022.nc\")\n", + "\n", + "## if directories don't exist, create them\n", + "for path in (run_dir, glorys_path, input_dir):\n", + " os.makedirs(str(path), exist_ok=True)\n", + "\n", + "## Copy hgrid.nc into the experinment folder\n", + "import shutil\n", + "shutil.copy2(byogrid_path, input_dir/\"hgrid.nc\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 2: Make experiment object\n", + "The `regional_mom6.experiment` contains the regional domain basics, and also generates the horizontal and vertical grids, `hgrid` and `vgrid` respectively, and sets up the directory structures. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expt = rmom6.experiment(\n", + " date_range = date_range,\n", + " resolution = 0.5,\n", + " number_vertical_layers = 75,\n", + " layer_thickness_ratio = 100,\n", + " depth = 4500,\n", + " minimum_depth = 5,\n", + " mom_run_dir = run_dir,\n", + " mom_input_dir = input_dir,\n", + " fre_tools_dir = fre_tools_dir,\n", + " hgrid_type = 'from_file',\n", + " boundaries = ['north', 'south', 'east', 'west']\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 3: Prepare ocean forcing data\n", + "\n", + "We need to cut out our ocean forcing. The package expects an initial condition and one time-dependent segment per non-land boundary. Naming convention is `\"east_unprocessed\"` for segments and `\"ic_unprocessed\"` for the initial condition.\n", + "\n", + "In this notebook, we are forcing with the Copernicus Marine \"Glorys\" reanalysis dataset. There's a function in the `mom6-regional` package that generates a bash script to download the correct boundary forcing files for your experiment. First, you will need to create an account with Copernicus, and then call `copernicusmarine login` to set up your login details on your machine. Then you can run the `get_glorys_data.sh` bash script.\n", + "\n", + "This bash script uses the [Copernicus marine toolbox]( https://help.marine.copernicus.eu/en/articles/7970514-copernicus-marine-toolbox-installation) and users should install this before running the bash script.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expt.get_glorys(\n", + " raw_boundaries_path=glorys_path\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 4: Set up bathymetry\n", + "\n", + "Similarly to ocean forcing, we point the experiment's `setup_bathymetry` method at the location of the file of choice and also provide the variable names. We don't need to preprocess the bathymetry since it is simply a two-dimensional field and is easier to deal with. Afterwards you can inspect `expt.bathymetry` to have a look at the regional domain.\n", + "\n", + "After running this cell, your input directory will contain other bathymetry-related things like the ocean mosaic and mask table too. The mask table defaults to a 10x10 layout and can be modified later." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "expt.setup_bathymetry(\n", + " bathymetry_path=bathymetry_path,\n", + " longitude_coordinate_name=\"lon\",\n", + " latitude_coordinate_name=\"lat\",\n", + " vertical_coordinate_name=\"elevation\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check out your domain: \n", + "The `expt.bathymetry` method returns an xarray dataset, which can be plotted as usual. If the user hasn't yet run `setup_bathymetry`, then calling `expt.bathymetry` will return `None` and prompt them to do so!\n", + "\n", + "Here we plot two plots: the first is in $x$-$y$ coordinates and looks rectangular. The second is in latitude-longitude coordinates and shows the shape of the curvilinear/rotated domain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-ignore-output", + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "# Note this is x/y rather than lat/lon coordinates\n", + "expt.bathymetry.depth.plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "#In lat/lon coords\n", + "from regional_mom6 import regridding\n", + "import matplotlib.pyplot as plt\n", + "import xarray as xr\n", + "\n", + "bathymetry = xr.open_dataset(inputdir/\"bathymetry.nc\")\n", + "hgrid = xr.open_dataset(inputdir/\"hgrid.nc\")\n", + "\n", + "t_points = regridding.get_hgrid_arakawa_c_points(hgrid, point_type = \"t\")\n", + "\n", + "plt.pcolormesh(t_points.tlon, t_points.tlat, bathymetry.depth)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 5: Handle the ocean forcing - where the magic happens\n", + "\n", + "This cuts out and interpolates the initial condition as well as all boundaries (unless you don't pass it boundaries).\n", + "\n", + "The dictionary maps the MOM6 variable names to what they're called in your ocean input file. Notice how for GLORYS, the horizontal dimensions are `latitude` and `longitude`, vs `xh`, `yh`, `xq`, `yq` for MOM6. This is because for an 'A' grid type tracers share the grid with velocities so there's no difference.\n", + "\n", + "If one of your segments is land, you can delete its string from the 'boundaries' list. You'll need to update MOM_input to reflect this though so it knows how many segments to look for, and their orientations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define a mapping from the GLORYS variables and dimensions to the MOM6 ones\n", + "ocean_varnames = {\"time\": \"time\",\n", + " \"yh\": \"latitude\",\n", + " \"xh\": \"longitude\",\n", + " \"zl\": \"depth\",\n", + " \"eta\": \"zos\",\n", + " \"u\": \"uo\",\n", + " \"v\": \"vo\",\n", + " \"tracers\": {\"salt\": \"so\", \"temp\": \"thetao\"}\n", + " }\n", + "\n", + "# Set up the initial condition\n", + "expt.setup_initial_condition(\n", + " glorys_path / \"ic_unprocessed.nc\", # directory where the unprocessed initial condition is stored, as defined earlier\n", + " ocean_varnames,\n", + " arakawa_grid=\"A\"\n", + " ) \n", + "\n", + "# Set up the four boundary conditions. Remember that in the glorys_path, we have four boundary files names north_unprocessed.nc etc. \n", + "expt.setup_ocean_state_boundaries(\n", + " glorys_path,\n", + " ocean_varnames,\n", + " arakawa_grid = \"A\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check out your initial condition data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "## Preview the initial temperature at the surface in x/y and lat/lon coordinates\n", + "from matplotlib import pyplot as plt\n", + "\n", + "## Create a new temperature array with lat and lon coords\n", + "templatlon = expt.init_tracers.temp.assign_coords(lon=bathymetry.lon, lat=bathymetry.lat)\n", + "\n", + "#plotting\n", + "fig, axes = plt.subplots(ncols=2, figsize=(16, 4))\n", + "\n", + "templatlon.isel(zl=0).plot(ax=axes[0])\n", + "templatlon.isel(zl=0).plot(x=\"lon\", y=\"lat\", ax=axes[1])\n", + "axes[0].set_title(\"x/y coords\")\n", + "axes[1].set_title(\"lon/lat coords\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "## u boundary forcing for segment 1 (south)\n", + "expt.segment_001.u_segment_001.isel(time = 5).plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 6: Create Tidal forcing\n", + "Note that this step can take a while (like 5min or so). " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "# If you have downloaded the TPXO tidal data and wish to include tidal forcing at the boundary, run this cell\n", + "expt.setup_boundary_tides(\n", + " tide_h_path,\n", + " tide_u_path,\n", + " tidal_constituents=[\"M2\"],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 7: Run the FRE tools\n", + "\n", + "This is just a wrapper for the FRE tools needed to make the mosaics and masks for the experiment. The only thing you need to tell it is the processor layout. In this case we're saying that we want a 10 by 10 grid of 100 processors. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expt.run_FRE_tools(layout=(10, 10)) ##the tiling/no processors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 8: Set up ERA5 forcing:\n", + "\n", + "Here we assume the ERA5 dataset is stored somewhere on the system we are working on. \n", + "\n", + "Below is a table showing ERA5 characteristics and what needs to be done to sort it out.\n", + "\n", + "**Required ERA5 data**:\n", + "\n", + "Name | ERA5 filename | ERA5 variable name | Units\n", + "---|---|---|---\n", + "Surface Pressure | sp | sp | Pa \n", + "Surface Temperature | 2t | t2m | K \n", + "Meridional Wind | 10v | v10 | m/s \n", + "Zonal Wind | 10u | u10 | m/s \n", + "Specific Humidity | - | - | kg/kg, calculated from dewpoint temperature\n", + "Dewpoint Temperature | 2d | d2m | K\n", + "\n", + "\n", + "We calculate specific humidity $q$ from dewpoint temperature $T_d$ and surface pressure $P$ via saturation vapour pressure $P_v$.\n", + "\n", + "$$P_v = 10^{8.07131 - \\frac{1730.63}{233.426 + T}} \\frac{101325}{760} \\; \\textrm{[Pascal]} $$\n", + "\n", + "$$q = 0.001 \\times 0.622 \\frac{P_v}{P}$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "expt.setup_era5(era_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 8: Modify the default input directory to make a (hopefully) runnable configuration out of the box\n", + "\n", + "This step copies the default directory and modifies the `MOM_layout` files to match your experiment by inserting the right number of x, y points and CPU layout.\n", + "\n", + "To run MOM6 using the [payu infrastructure](https://github.com/payu-org/payu), provide the keyword argument `using_payu = True` to the `setup_run_directory` method. Doing so, an example `config.yaml` file is generated in the run directory. The `config.yaml` file needs to be modified manually to add the locations of executables, etc." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expt.setup_run_directory(surface_forcing = \"era5\", with_tides = False)\n", + "# To turn on tides (assuming you ran step 6), set `with_tides = True`" + ] + } + ], + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/demos/premade_run_directories/README.md b/demos/premade_run_directories/README.md index a3488a41..4a1da513 100644 --- a/demos/premade_run_directories/README.md +++ b/demos/premade_run_directories/README.md @@ -1,4 +1,4 @@ -## Premade Run Directories +# Premade Run Directories These directories are used for the demo notebooks, and can be used as templates for setting up a new experiment. The [documentation](https://regional-mom6.readthedocs.io/en/latest/mom6-file-structure-primer.html) explains what all the files are for. diff --git a/demos/premade_run_directories/common_files/MOM_input b/demos/premade_run_directories/common_files/MOM_input index 8b4ccc70..d259b265 100755 --- a/demos/premade_run_directories/common_files/MOM_input +++ b/demos/premade_run_directories/common_files/MOM_input @@ -107,30 +107,6 @@ OBC_ZERO_BIHARMONIC = True ! [Boolean] default = False ! viscosity term. OBC_TIDE_N_CONSTITUENTS = 0 ! default = 0 ! Number of tidal constituents being added to the open boundary. -OBC_SEGMENT_001 = "J=0,I=0:N,FLATHER,ORLANSKI,NUDGED,ORLANSKI_TAN,NUDGED_TAN" ! - ! Documentation needs to be dynamic????? -OBC_SEGMENT_001_VELOCITY_NUDGING_TIMESCALES = 0.3, 360.0 ! [days] default = 0.0 - ! Timescales in days for nudging along a segment, for inflow, then outflow. - ! Setting both to zero should behave like SIMPLE obcs for the baroclinic - ! velocities. -OBC_SEGMENT_002 = "J=N,I=N:0,FLATHER,ORLANSKI,NUDGED,ORLANSKI_TAN,NUDGED_TAN" ! - ! Documentation needs to be dynamic????? -OBC_SEGMENT_002_VELOCITY_NUDGING_TIMESCALES = 0.3, 360.0 ! [days] default = 0.0 - ! Timescales in days for nudging along a segment, for inflow, then outflow. - ! Setting both to zero should behave like SIMPLE obcs for the baroclinic - ! velocities. -OBC_SEGMENT_003 = "I=0,J=N:0,FLATHER,ORLANSKI,NUDGED,ORLANSKI_TAN,NUDGED_TAN" ! - ! Documentation needs to be dynamic????? -OBC_SEGMENT_003_VELOCITY_NUDGING_TIMESCALES = 0.3, 360.0 ! [days] default = 0.0 - ! Timescales in days for nudging along a segment, for inflow, then outflow. - ! Setting both to zero should behave like SIMPLE obcs for the baroclinic - ! velocities. -OBC_SEGMENT_004 = "I=N,J=0:N,FLATHER,ORLANSKI,NUDGED,ORLANSKI_TAN,NUDGED_TAN" ! - ! Documentation needs to be dynamic????? -OBC_SEGMENT_004_VELOCITY_NUDGING_TIMESCALES = 0.3, 360.0 ! [days] default = 0.0 - ! Timescales in days for nudging along a segment, for inflow, then outflow. - ! Setting both to zero should behave like SIMPLE obcs for the baroclinic - ! velocities. OBC_TRACER_RESERVOIR_LENGTH_SCALE_OUT = 3.0E+04 ! [m] default = 0.0 ! An effective length scale for restoring the tracer concentration at the ! boundaries to externally imposed values when the flow is exiting the domain. @@ -232,7 +208,7 @@ INIT_LAYERS_FROM_Z_FILE = True ! [Boolean] default = False ! Z-space file on a latitude-longitude grid. ! === module MOM_initialize_layers_from_Z === -TEMP_SALT_Z_INIT_FILE = "forcing/init_tracers.nc" ! default = "temp_salt_z.nc" +TEMP_SALT_Z_INIT_FILE = "init_tracers.nc" ! default = "temp_salt_z.nc" ! The name of the z-space input file used to initialize temperatures (T) and ! salinities (S). If T and S are not in the same file, TEMP_Z_INIT_FILE and ! SALT_Z_INIT_FILE must be set. @@ -247,7 +223,7 @@ TEMP_SALT_INIT_VERTICAL_REMAP_ONLY = True ! [Boolean] default = False DEPRESS_INITIAL_SURFACE = True ! [Boolean] default = False ! If true, depress the initial surface to avoid huge tsunamis when a large ! surface pressure is applied. -SURFACE_HEIGHT_IC_FILE = "forcing/init_eta.nc" ! +SURFACE_HEIGHT_IC_FILE = "init_eta.nc" ! ! The initial condition file for the surface height. SURFACE_HEIGHT_IC_VAR = "eta_t" ! default = "SSH" ! The initial condition variable for the surface height. @@ -262,17 +238,8 @@ VELOCITY_CONFIG = "file" ! default = "zero" ! rossby_front - a mixed layer front in thermal wind balance. ! soliton - Equatorial Rossby soliton. ! USER - call a user modified routine. -VELOCITY_FILE = "forcing/init_vel.nc" ! +VELOCITY_FILE = "init_vel.nc" ! ! The name of the velocity initial condition file. -OBC_SEGMENT_001_DATA = "U=file:forcing/forcing_obc_segment_001.nc(u),V=file:forcing/forcing_obc_segment_001.nc(v),SSH=file:forcing/forcing_obc_segment_001.nc(eta),TEMP=file:forcing/forcing_obc_segment_001.nc(temp),SALT=file:forcing/forcing_obc_segment_001.nc(salt)" ! - ! OBC segment docs -OBC_SEGMENT_002_DATA = "U=file:forcing/forcing_obc_segment_002.nc(u),V=file:forcing/forcing_obc_segment_002.nc(v),SSH=file:forcing/forcing_obc_segment_002.nc(eta),TEMP=file:forcing/forcing_obc_segment_002.nc(temp),SALT=file:forcing/forcing_obc_segment_002.nc(salt)" ! - ! OBC segment docs -OBC_SEGMENT_003_DATA = "U=file:forcing/forcing_obc_segment_003.nc(u),V=file:forcing/forcing_obc_segment_003.nc(v),SSH=file:forcing/forcing_obc_segment_003.nc(eta),TEMP=file:forcing/forcing_obc_segment_003.nc(temp),SALT=file:forcing/forcing_obc_segment_003.nc(salt)" ! - ! OBC segment docs -OBC_SEGMENT_004_DATA = "U=file:forcing/forcing_obc_segment_004.nc(u),V=file:forcing/forcing_obc_segment_004.nc(v),SSH=file:forcing/forcing_obc_segment_004.nc(eta),TEMP=file:forcing/forcing_obc_segment_004.nc(temp),SALT=file:forcing/forcing_obc_segment_004.nc(salt)" ! - ! OBC segment docs - ! === module MOM_diag_mediator === NUM_DIAG_COORDS = 1 ! default = 1 ! The number of diagnostic vertical coordinates to use. For each coordinate, an diff --git a/demos/premade_run_directories/common_files/MOM_override b/demos/premade_run_directories/common_files/MOM_override index 7b0f9f37..c11872b7 100644 --- a/demos/premade_run_directories/common_files/MOM_override +++ b/demos/premade_run_directories/common_files/MOM_override @@ -1,4 +1,2 @@ -## Add override files here - #override DT=50 #override DT_THERM=300 diff --git a/demos/premade_run_directories/era5_surface/data_table b/demos/premade_run_directories/era5_surface/data_table index 6750c14b..561f729b 100755 --- a/demos/premade_run_directories/era5_surface/data_table +++ b/demos/premade_run_directories/era5_surface/data_table @@ -1,17 +1,17 @@ -"ATM", "p_surf", "sp", "./INPUT/forcing/sp_ERA5.nc", "bilinear", 1.0 -"ATM", "p_bot", "sp", "./INPUT/forcing/sp_ERA5.nc", "bilinear", 1.0 -"ATM", "t_bot", "t2m", "./INPUT/forcing/2t_ERA5.nc", "bilinear", 1.0 -"ATM", "sphum_bot", "q", "./INPUT/forcing/q_ERA5.nc", "bilinear", 1.0 -"ATM", "u_bot", "u10", "./INPUT/forcing/10u_ERA5.nc", "bicubic", 1.0 -"ATM", "v_bot", "v10", "./INPUT/forcing/10v_ERA5.nc", "bicubic", 1.0 +"ATM", "p_surf", "sp", "./INPUT/sp_ERA5.nc", "bilinear", 1.0 +"ATM", "p_bot", "sp", "./INPUT/sp_ERA5.nc", "bilinear", 1.0 +"ATM", "t_bot", "t2m", "./INPUT/2t_ERA5.nc", "bilinear", 1.0 +"ATM", "sphum_bot", "q", "./INPUT/q_ERA5.nc", "bilinear", 1.0 +"ATM", "u_bot", "u10", "./INPUT/10u_ERA5.nc", "bicubic", 1.0 +"ATM", "v_bot", "v10", "./INPUT/10v_ERA5.nc", "bicubic", 1.0 "ATM", "z_bot", "", "", "bilinear", 10.0 "ATM", "gust", "", "", "bilinear", 1.0e-4 "ICE", "lw_flux_dn", "", "", "bilinear", 1.0 -"ICE", "sw_flux_vis_dir_dn", "msdwswrf", "./INPUT/forcing/msdwswrf_ERA5.nc", "bilinear", 0.285 -"ICE", "sw_flux_vis_dif_dn", "msdwswrf", "./INPUT/forcing/msdwswrf_ERA5.nc", "bilinear", 0.285 -"ICE", "sw_flux_nir_dir_dn", "msdwlwrf", "./INPUT/forcing/msdwlwrf_ERA5.nc", "bilinear", 0.215 -"ICE", "sw_flux_nir_dif_dn", "msdwlwrf", "./INPUT/forcing/msdwlwrf_ERA5.nc", "bilinear", 0.215 -"ICE", "lprec", "trr", "./INPUT/forcing/trr_ERA5.nc", "bilinear", 1.0 +"ICE", "sw_flux_vis_dir_dn", "msdwswrf", "./INPUT/msdwswrf_ERA5.nc", "bilinear", 0.285 +"ICE", "sw_flux_vis_dif_dn", "msdwswrf", "./INPUT/msdwswrf_ERA5.nc", "bilinear", 0.285 +"ICE", "sw_flux_nir_dir_dn", "msdwlwrf", "./INPUT/msdwlwrf_ERA5.nc", "bilinear", 0.215 +"ICE", "sw_flux_nir_dif_dn", "msdwlwrf", "./INPUT/msdwlwrf_ERA5.nc", "bilinear", 0.215 +"ICE", "lprec", "trr", "./INPUT/trr_ERA5.nc", "bilinear", 1.0 "ICE", "fprec", "", "", "bilinear", 0.0 "ICE", "runoff", "", "", "none", 0.0 "ICE", "dhdt", "", "", "none", 80.0 diff --git a/demos/reanalysis-forced.ipynb b/demos/reanalysis-forced.ipynb index f66e8333..21d63681 100644 --- a/demos/reanalysis-forced.ipynb +++ b/demos/reanalysis-forced.ipynb @@ -6,13 +6,14 @@ "source": [ "# Regional Tasmanian domain forced by GLORYS and ERA5 reanalysis datasets\n", "\n", - "**Note**: FRE-NC tools are required to be set up, as outlined in the [documentation](https://regional-mom6.readthedocs.io/en/latest/) of regional-mom6 package.\n", + "**Note**: FRE-NC tools are required to be set up, as outlined in the [documentation](https://regional-mom6.readthedocs.io/en/latest/) of regional-mom6 package. You will also need to ensure that `matplotlib` is installed in your environment. If not, you can simply create a new cell and type `pip install matplotlib`\n", "\n", "For this example we need:\n", "\n", "- [GEBCO bathymetry](https://www.gebco.net/data_and_products/gridded_bathymetry_data/)\n", - "- [GLORYS ocean reanalysis data](https://data.marine.copernicus.eu/product/GLOBAL_MULTIYEAR_PHY_001_030/description), and\n", - "- [ERA5 surface forcing](https://www.ecmwf.int/en/forecasts/dataset/ecmwf-reanalysis-v5)\n", + "- [GLORYS ocean reanalysis data](https://data.marine.copernicus.eu/product/GLOBAL_MULTIYEAR_PHY_001_030/description)\n", + "- [ERA5 atmosphere data](https://www.ecmwf.int/en/forecasts/dataset/ecmwf-reanalysis-v5), and\n", + "- [TPXO tidal model data](https://www.tpxo.net/global)\n", "\n", "This example reads in the entire global extent of ERA5 and GEBCO; we don't need to worry about cutting it down to size." ] @@ -45,31 +46,27 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [ + "nbval-ignore-output" + ] + }, "outputs": [], "source": [ + "import warnings\n", + "warnings.filterwarnings(\"ignore\")\n", "import regional_mom6 as rmom6\n", "\n", "import os\n", "from pathlib import Path\n", - "from dask.distributed import Client" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Start a dask client." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ + "from dask.distributed import Client\n", + "\n", "client = Client()\n", - "client" + "client\n", + "\n", + "# Currently, only the regional_mom6 module reports logging information to the info level, for more detailed output, uncomment the following:\n", + "# import logging\n", + "# logging.basicConfig(level=logging.INFO) " ] }, { @@ -85,7 +82,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -103,10 +100,15 @@ "run_dir = Path(f\"mom6_run_directories/{expt_name}/\")\n", "\n", "## Directory where compiled FRE tools are located (needed for construction of mask tables)\n", - "toolpath_dir = Path(\"PATH_TO_FRE_TOOLS\")\n", + "fre_tools_dir = Path(\"PATH_TO_FRE_TOOLS\")\n", "\n", "## Path to where your raw ocean forcing files are stored\n", - "glorys_path = Path(\"PATH_TO_GLORYS_DATA\" )\n", + "glorys_path = Path(\"PATH_TO_GLORYS_DATA\")\n", + "\n", + "#Location of TPXO raw tidal file\n", + "#note that you will need to swap ## to the version number for each of the file names\n", + "tide_h_path = Path(\"PATH_TO_TPXO_H_FILE/h_tpxo##.nc\")\n", + "tide_u_path = Path(\"PATH_TO_TPXO_U_FILE/u_tpxo##.nc\")\n", "\n", "## if directories don't exist, create them\n", "for path in (run_dir, glorys_path, input_dir):\n", @@ -123,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -133,11 +135,13 @@ " date_range = date_range,\n", " resolution = 0.05,\n", " number_vertical_layers = 75,\n", - " layer_thickness_ratio = 10,\n", + " layer_thickness_ratio = 60,\n", " depth = 4500,\n", + " minimum_depth = 5,\n", " mom_run_dir = run_dir,\n", " mom_input_dir = input_dir,\n", - " toolpath_dir = toolpath_dir\n", + " fre_tools_dir = fre_tools_dir,\n", + " boundaries=[\"north\", \"south\", \"east\", \"west\"]\n", ")" ] }, @@ -189,9 +193,8 @@ "metadata": {}, "outputs": [], "source": [ - "expt.get_glorys_rectangular(\n", - " raw_boundaries_path=glorys_path,\n", - " boundaries=[\"north\", \"south\", \"east\", \"west\"],\n", + "expt.get_glorys(\n", + " raw_boundaries_path=glorys_path\n", ")" ] }, @@ -217,7 +220,6 @@ " longitude_coordinate_name='lon',\n", " latitude_coordinate_name='lat',\n", " vertical_coordinate_name='elevation',\n", - " minimum_layers=1\n", " )" ] }, @@ -225,12 +227,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Check out your domain:" + "### Check out your domain!\n", + "\n", + "Calling `expt.bathymetry` returns an xarray dataset, which can be plotted as usual. If you haven't yet run setup_bathymetry, calling `expt.bathymetry` will return `None` and prompt you to do so!" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 12, "metadata": { "tags": [ "nbval-ignore-output", @@ -241,16 +245,16 @@ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 8, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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G5Lf5/I5VqtV+fjHPy7r1q2Tzs5OOf744+VTn/qU1FHMaq6d3w9/+EN561vfKqtWrZJUKiX//u//rn5v53xKpZJ88IMflKVLl0p3d7dcdtll8tJLL83iWewb+zrHSqUiH/3oR+X000+X7u5uWbVqlVxxxRXy8ssvq30c7ecYsIARBUR33313lMvlojvvvDN68skno2uuuSbq7u6OXnzxxSPdtf3Gm970pugrX/lK9Pjjj0cbN26M3vzmN0dr1qyJJiYmkja33npr1NPTE33rW9+KHnvsseid73xntHLlymhsbOwI9vzA8PDDD0fHHXdc9KpXvSq65pprkvVz/Rz37NkTrV27NvqDP/iD6KGHHoo2b94c3XvvvdGzzz6btJnL53jTTTdFS5Ysif7zP/8z2rx5c/Rv//Zv0aJFi6LbbrstaTPXzu973/tedMMNN0Tf+ta3IhGJvvOd76jf2zmfq666KjrmmGOi9evXR4888kj0ute9LjrjjDOiarU6y2fjxr7OcWRkJLr44oujb37zm9Evf/nL6Mc//nF07rnnRmeddZbax9F+jgELF8EgiqLonHPOia666iq17qSTToquv/76I9SjQ4fh4eFIRKL7778/iqIoqtfr0eDgYHTrrbcmbYrFYtTX1xf9wz/8w5Hq5gFhfHw8OuGEE6L169dHF154YWIQzYdz/OhHPxpdcMEF3t/n+jm++c1vjv7oj/5IrXv7298evfe9742iaO6f30xjoZ3zGRkZiXK5XHT33XcnbbZt2xal0+nonnvumbW+twuX0TcTDz/8cCQiyeRyrp1jwMLCgneZlctl2bBhg1xyySVq/SWXXCIPPvjgEerVocPo6KiIiAwMDIiIyObNm2VoaEidb6FQkAsvvHDOne9f/MVfyJvf/Ga5+OKL1fr5cI7f/e535eyzz5bf+73fk+XLl8uZZ54pd955Z/L7XD/HCy64QP7nf/5HnnnmGRER+fnPfy4PPPCA/NZv/ZaIzP3zm4l2zmfDhg1SqVRUm1WrVslpp502J89ZpDH+pFIp6e/vF5H5eY4B8wfzRqn6QLFr1y6p1WqyYsUKtX7FihUyNDR0hHp1aBBFkVx33XVywQUXyGmnnSYikpyT63xffPHFWe/jgeLuu++WRx55RH760582/TYfzvH555+XL33pS3LdddfJX//1X8vDDz8sV199tRQKBbniiivm/Dl+9KMfldHRUTnppJMkk8lIrVaTT3/60/Lud79bRObHPSTaOZ+hoSHJ5/OyePHipjZzcSwqFoty/fXXy3ve856kwOt8O8eA+YUFbxAZpFIp9XcURU3r5ho+8IEPyC9+8Qt54IEHmn6by+e7detWueaaa+T73//+PitBz+VzrNfrcvbZZ8vNN98sIiJnnnmmPPHEE/KlL31JrrjiiqTdXD3Hb37zm3LXXXfJN77xDTn11FNl48aNcu2118qqVavkyiuvTNrN1fPz4UDOZy6ec6VSkXe9611Sr9fl9ttvb9l+Lp5jwPzDgneZLV26VDKZTNPsZHh4uGk2N5fwwQ9+UL773e/KfffdJ8cee2yyfnBwUERkTp/vhg0bZHh4WM466yzJZrOSzWbl/vvvl7/7u7+TbDabnMdcPseVK1fKKaecotadfPLJsmXLFhGZ+/fxr/7qr+T666+Xd73rXXL66afL5ZdfLh/60IfklltuEZG5f34z0c75DA4OSrlclr1793rbzAVUKhV5xzveIZs3b5b169cn7JDI/DnHgPmJBW8Q5fN5Oeuss2T9+vVq/fr16+U1r3nNEerVgSOKIvnABz4g3/72t+V///d/Zd26der3devWyeDgoDrfcrks999//5w53ze84Q3y2GOPycaNG5N/Z599tvz+7/++bNy4UY4//vg5f46//uu/3iSX8Mwzz8jatWtFZO7fx6mpKUmn9fCTyWSStPu5fn4z0c75nHXWWZLL5VSb7du3y+OPPz5nztkYQ5s2bZJ7771XlixZon6fD+cYMI9xpKK5jyaYtPsvf/nL0ZNPPhlde+21UXd3d/TCCy8c6a7tN/78z/886uvri37wgx9E27dvT/5NTU0lbW699daor68v+va3vx099thj0bvf/e6jOp25HTDLLIrm/jk+/PDDUTabjT796U9HmzZtir7+9a9HXV1d0V133ZW0mcvneOWVV0bHHHNMknb/7W9/O1q6dGn0kY98JGkz185vfHw8evTRR6NHH300EpHo85//fPToo48mGVbtnM9VV10VHXvssdG9994bPfLII9HrX//6oyolfV/nWKlUossuuyw69thjo40bN6rxp1QqJfs42s8xYOEiGEQxvvjFL0Zr166N8vl89Gu/9mtJmvpcg4g4/33lK19J2tTr9egTn/hENDg4GBUKheg3fuM3oscee+zIdfoQYKZBNB/O8T/+4z+i0047LSoUCtFJJ50U3XHHHer3uXyOY2Nj0TXXXBOtWbMm6ujoiI4//vjohhtuUB/OuXZ+9913n/Pdu/LKK6Moau98pqenow984APRwMBA1NnZGb3lLW+JtmzZcgTOxo19nePmzZu94899992X7ONoP8eAhYtUFEXR7PFRAQEBAQEBAQFHHxZ8DFFAQEBAQEBAQDCIAgICAgICAhY8gkEUEBAQEBAQsOARDKKAgICAgICABY9gEAUEBAQEBAQseASDKCAgICAgIGDBIxhEAQEBAQEBAQsewSAKCAgICAgIWPAIBlFAQEBAQEDAgkcwiAICAgICAgIWPIJBFBCwwHHRRRfJ1VdfLR/5yEdkYGBABgcH5cYbbxQRkR/84AeSz+flRz/6UdL+c5/7nCxdulS2b99+hHocEBAQcOgRDKKAgAD52te+Jt3d3fLQQw/JZz7zGfnUpz4l69evl4suukiuvfZaufzyy2V0dFR+/vOfyw033CB33nmnrFy58kh3OyAgIOCQIRR3DQhY4LjoooukVqspFuicc86R17/+9XLrrbdKuVyW8847T0444QR54okn5Pzzz5c777zzCPY4ICAg4NAje6Q7EBAQcOTxqle9Sv29cuVKGR4eFhGRfD4vd911l7zqVa+StWvXym233XYEehgQEBBweBFcZgEBAZLL5dTfqVRK6vV68veDDz4oIiJ79uyRPXv2zGrfAgICAmYDwSAKCAjYJ5577jn50Ic+JHfeeaecd955csUVVyhjKSAgIGA+IBhEAQEBXtRqNbn88svlkksukT/8wz+Ur3zlK/L444/L5z73uSPdtYCAgIBDimAQBQQEePHpT39aXnjhBbnjjjtERGRwcFD+6Z/+ST7+8Y/Lxo0bj2znAgICAg4hQpZZQEBAQEBAwIJHYIgCAgICAgICFjyCQRQQEBAQEBCw4BEMooCAgICAgIAFj2AQBQQEBAQEBCx4BIMoICAgICAgYMEjGEQBAQEBAQEBCx7BIAoICAgICAhY8AgGUUBAQEBAQMCCRzCIAgICAgICAhY8gkEUEBAQEBAQsOARDKKAgICAgICABY9gEAUEBAQEBAQsePz/LOUhC/oBD7oAAAAASUVORK5CYII=", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkQAAAGwCAYAAABIC3rIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOz9e7wlVXnnjz9VtW/nfvp+uqFBNEAUMOOQCE1ixFFuryBjzC/EkBBFRnm9NBB+wCRfY/ITMwRGTNT80DhqHEGRkF8yMZHMDAEyEZMgXjo6ojF4CSINNA3dfe5n36rq90fVqvVeZ6/Ve+9zTu8+3b0+r9ehF7WrVq1du2rVs57P83yeIE3TVDw8PDw8PDw8jmOER3oAHh4eHh4eHh5HGt4g8vDw8PDw8Dju4Q0iDw8PDw8Pj+Me3iDy8PDw8PDwOO7hDSIPDw8PDw+P4x7eIPLw8PDw8PA47uENIg8PDw8PD4/jHqUjPYD1gCRJ5JlnnpGxsTEJguBID8fDw8PDYx0jTVOZm5uTHTt2SBgePr9CvV6XZrO56n4qlYrUarU1GNGxDW8QicgzzzwjO3fuPNLD8PDw8PA4ivDUU0/JiSeeeFj6rtfrcsrJo7J3X7zqvqampuSJJ57wRlEXeINIRMbGxkRE5FXRf5RSUF7z/tM4u6GDEN6nwLOVHsuQJv3tz3vIcuxfHfjUiobxHyd+rfv5nEPyHtauWONn33nN4e0OKnpeC4aGREQk2b6p2NbYPFS028NR0W6O6bG2RnV/cSX7N8F0meBtkvIrOoZX7B9hW1kXTmAfAeopBC3dYdjo3Lc9oZ+FdLRdtMuj2tNy9gl7ivaG0pKIiDQSPZB/ndlatC/a/i9Fe3NpXkRElubb8luv/lrx7jgcaDabsndfLE/ufpGMj638npmdS+Tks38ozWbTG0Rd4A0ikYImKwXlw2IQSZQ/aI6JsJ+XSJr4SivHLFy3AY0d18tUHYt9f2HD24r2g/Gf9TwM4xlYg3vWYxnWejFEY8G16IphRKhpf0l/HM3qzxuVit63DWsFIadqKz9O0Y6rOIqMD4bXzvdJqvoLkH1K8XZKyjByOKK5aHm3EtbwvIzrk2/a1CjaL9q0WLTLQbZg3VyeLradue0APtdnDCQzHIMkM7QGEWIxOhbI6NjKz5M4JxaP5fAG0SBgmQD9C8WjZ/TzAsW+QahfDBdEv1S0+zGOzK79Pbsm6NcTaMNqjKqh3EuwVC82hRVtzZSWtEEc1/R5SnVtGLTzlyxfIDG9RWiHLd2mkRPklyFo476igVWipaeblS3akmtGmYESzetxpvAylSuabjp5/KDeHujt1TAzbsJA/y7DgR50i5beEUCcJhKvYh0cr8X9dpzAG0QeHh4eHh7rFImkksjKLaLVHHu8wRtEq4XL+j5MXiH24ekzj0Phgda9RZseogvCXyzaDyZ/3nFcEB3ZFbFHD3DQqJwT6CGk6yV5fr+IiITjOv4laGqPSdjQ7ailXxGlpU6PTdtBxyTwCkVoJxhSlA/bFSvErtMIlF8Iim0so8SSJji6IT3+DWOaGjtl5IWiXQ71PjW6sCygN0mhbdnmcfTDG0Q9ohdDxJiM/DtlbdCHwelh4sLKFUXbvH/9tTum4HhG+DsHghd4bvCmDR1fE6QwMlowiOq6nZT0PaQMngi3UlLWn5fnORDdNEJuUnVu666SBvZ2pawDpU/YMC0iIj+Y26E/R/D06Rv2Fe3RSMcQlUPdx3pHIomshvRa3dHHF/zM6OHh4eHhsU4Rp+mq//rBzTffLEEQGH9TU1PF52mays033yw7duyQoaEhOf/88+Xb3/620Uej0ZBrr71WNm/eLCMjI3LZZZfJnj17jH0OHjwoV155pUxMTMjExIRceeWVMj09veLrtBbwHqIeYbqiucyBKyhw7XN4cNTSZ2pF6/Ly+CDAtYdxrfWq/8Lymzr36ZLOf1TBCDLv75m0PlNH+/UQEcm/F1PxBeJ/QRNZZk2k6yOyN0iC/F/dheF0oVeIHiDSY5ZLGVf0zsw+EwRYN0DjTVbzwPBhffJ2EwHioMYa0AWIcPKyhTKLjYy6pGN7fIz7Es444wx56KGHiv+PQKPffvvt8oEPfEDuvPNOOe200+SWW26RCy64QB5//PFChuD666+X++67T+69917ZtGmT3HjjjXLppZfK7t27i76uuOIK2bNnj9x///0iIvL2t79drrzySrnvvvsG+E1NeIMICMJgVWmUPgvnELC9SI6Fl8tRiOMqRgj3WDqgsI9u19e5eFnr7DN+d9Jn+fCSOc1rhRhz0IRlY1BpnRpBpLKipv17JZF9XiySt1LLNlluSOHcOOmGShYjNLFhodjWghbAyUM6fT5O7UZMorYjLijBORLp/D35+eHGWgVVz87OGtur1apUq1XbIVIqlQyvkEKapvKhD31I3v3ud8sb3/hGERG56667ZNu2bXLPPffINddcIzMzM/LJT35SPvOZz8jrXvc6ERG5++67ZefOnfLQQw/JRRddJN/5znfk/vvvl0cffVTOOeccERH5xCc+Ibt27ZLHH39cTj/99BV/39Xg2DZzPTw8PDw8jmIkkkq8ij9lEO3cubOgpyYmJuS2225znvN73/ue7NixQ0455RR505veJP/2b/8mIiJPPPGE7N27Vy688MJi32q1Kq9+9avlkUceERGR3bt3S6vVMvbZsWOHnHnmmcU+X/rSl2RiYqIwhkREzj33XJmYmCj2ORLwHiKP/mBbxXrq66jFA817ijaDsK1wUWm237+XYHjDg9G5Aj5aPa5Kmf7InHyFz1xT00ZpVdNkYQu/EQOb57Pt7ar+PeMavCp8sxjZYticXyZ6gkKoUMcle7R1gAMW2hm9t2v7D4ttpMZCHMhfJbTwddQbYhYavUGKKkuOQl/CU089JePj48X/u7xD55xzjnz605+W0047TZ577jm55ZZb5LzzzpNvf/vbsnfvXhER2bZtm3HMtm3b5MknnxQRkb1790qlUpENGzZ07KOO37t3r2zdulWWY+vWrcU+RwLeIPLojm6TrDd8jlr0ZQT1st32Oe8Px71ytBo/Rw2M3yC/1sw2rOHliCyzgOnubR1blIcQSRiBygLTRprMlVav7A+KOMZDMMAgsCg1pMlXtPE228xEJs+eeLLYtgiZbKo0M24owaBUDFFtHYkxEmtFmY2PjxsGkQuXXHJJ0T7rrLNk165d8pKXvETuuusuOffcc0WkU6E7TdOu4SbL97Ht30s/hxPeIPLw8Di8OJaCtI8l0AiFQFAwp+NxJBrVu7cRXFyzvDocGkLGLrbtdDYaBpP+n6iqDaKJIa2wPVnNVKvnY12jq4og6VZif8XRQxTlA2egNA2iCF9MbW8kg3tpryRTbPnxq8HIyIicddZZ8r3vfU/e8IY3iEjm4dm+fXuxz759+wqv0dTUlDSbTTl48KDhJdq3b5+cd955xT7PPfdcx7mef/75Du/TIHH0+f08PDw8PDw8BoJGoyHf+c53ZPv27XLKKafI1NSUPPjgg8XnzWZTHn744cLYOfvss6VcLhv7PPvss/Ktb32r2GfXrl0yMzMjX/nKV4p9vvzlL8vMzEyxz5GA9xARQZCtZo/CVawvEOvhcfzALQPSfR+1Pazq6T9taNFCaWnuKxjSnhem3ceVzrR7eoW4nZQZPUTKeRMP2VPt6SGiOjWpr82VLFNuMdZ0HpWlKcBoU5wmmF7PGCKinPOCwQCFHRORVQoz9oebbrpJXv/618tJJ50k+/btk1tuuUVmZ2flzW9+swRBINdff73ceuutcuqpp8qpp54qt956qwwPD8sVV2T0+8TEhFx99dVy4403yqZNm2Tjxo1y0003yVlnnVVknb30pS+Viy++WN72trfJxz72MRHJ0u4vvfTSI5ZhJuINIjv6UUHuxXhS/Q3I0Fpzg8dTHh4eRwzdjJ9ejCNrvwz+RlA1qbQA+5g6RHkfPUyVrnIcip8w+sDOIWiyTeOaxiu0h8SMBVIg3TUMI4jUly2omqgE2uBhYHaSx7ekAzSIVLbYao7vB3v27JFf/uVflhdeeEG2bNki5557rjz66KNy8skni4jIb/7mb8rS0pK84x3vkIMHD8o555wjDzzwQKFBJCLywQ9+UEqlklx++eWytLQkr33ta+XOO+809Iw++9nPynXXXVdko1122WXy4Q9/eMXfcy0QpOkqCcZjALOzszIxMSH/oXq5lIJK9wOI48EgMjs/fH33A1+64+jEerl/jiLYDB7XM+4SazUMpfzZMYQZYyosIpB6u47naE9NFu2lrVngMu2RpIJsLLTbQ7rdGtb7t/L43uY4DI4RGGAj2ujYtllr6Gwf1e0Th6ZFRGQo0sKSw2yHuk0Pkc0gooeI9c0Mgyi36Jbm23Ld2Y/KzMxMT4HKK4F6L33zX7bK2NjK57u5uURe/rJ9h3Wsxwq8h2i16CcV2cPjeEcv3kbbAqKX5+koN7Z6Wch026enxZC6Tm2HlyPAa8HwEOnrG+beosaoXvEbdBiStIyaZPwZVS0zslMpDToYWGiXYMzEluhtM9Ue9dU69sygDCEGVVPEMfSFXI8beINoLeGNIA+P3rFSaroHLSObJ+VIpvavx7g957UhadCGQYR0fJVWX98AbxJYN2atGzFEzGZXp+HPQsos0r9tvaXNmQONoaI9Ws7os+HIkTKP2yZCHFJoSccn/daCOjUNJaVJVB9gltmgY4iOZ3iDyMPDw8PDY50ikcDqCevneI/e4A0ij+44yqkIj8OMw0UV9ynu+GD8Zx3bLoh+CYcN3lu0Hj1DfaGlPS/0ECnKLNLxzVLfguPwtSERZC3oaggw9kCZ1dvaW7TYzmKZtlR0XTYictFr8AbVczItMqg2eIsgYKn6aAywlpnH4OANIiIMstT7tZ7EuhkUa5DFZUy8x4MBo76jpymPC/RizFxYflPHNq+AvQLgWqcNHZQcLOrU/PJcHn80hQryMI5aWs9R2kirT/HGKS3mqfso1yFUqoYR1GhoI6hV02NSwdGjEWQDgNChTh1Z4oKM0h3YTkNK7dMa4BybpKt7JR3tNvkg4Q0iDw8PDw+PdYp4lZTZao493uANIiLIPUQ23QZD5n7AHqRVdd37WP1q2mNFGICX7mi6N9cjTdbVw+b4DVNSZshKS1WtMnbl0BuiDlGCgq1tpOAXqKCkBtq1mh5HrazbW6tzHV1ElrIcIiIth2iS8ga5MtLoOVJeJpv+kcfRD28QAUG5LEFQljTVLtmB+BtXSJm5aLK+qm3j3OslI6cv9FJV3ePoxzoXB12PRtCK4Xr2Id5YmsnmyCDRhVSN+CBWsG/q/qhEnWzM59k66obVtNE1PKTn4YnhpaJ98ujBol0O8wwxGjMYiEGZOWKIbJpENI4Sy77dhB3XEt5DNDh4g8jDw8PDw2OdIkmDIt1/pcd79AZvEAHBpg0ShFWRfS8U21LlJu53BWjLvHGtbNd4xftg8ueH/PyC8Bft5z6WvCrH6vfyWDc4prxCDgQotSABSnoorSI6qfGYMbMsqcArNMS5LuuvvAHB2mXtIRqtYbujtpjKAGsFKNcBdWpSZq5aZrravd0r5HH8wBtEQFouSxqVRcoWpVY+H71MhH24+HuR4bftm7ZbHZ/3AhpMTEvuZUyHGtu6hTeOji0cQfqsLyVowHjmuCA5gvdjT89wiPGVIvd+IoZxFFAEm9WQmuivnF2n1pKeb2kQpfBssH5ZNULB1lBRWPY6ZWxXw0PPl61ERw5FXcp8DBKeMhscvEHk4eHh4eGxThFLaOgi9X+8R6/wBhGwtHNcSuWaDCdYETy9V0R6DFReaUA00HXVttYr4uPNe3K8fV+PVcP57LvuH2xXYpGGJ/YI1D/sJ7OMMLLMWAA2nyMDzGMhdIPK0EmMdaUNI+UsmM9eP2mkty2FVbEhCMas24csXp8yfq+NJQwEl4CFXFu5OJLLExRZso67+MrWFOkqY4hSH0PUM7xBBKSlQNJSIPWdk8W22mz2QKUzs9xz1edyVaV2ZXp1c9V3ixvqCX1Mzr1QBz1V3j6S8OKOHr0A94dxT9NQ6nYP9ZIN2ctiZy3u1b5qyDkWbrlqdQl6iG0YPgzXqcwgNmcRNcJqeewO4o3SWI+tHet9G239qjpY1ydShsJ4WVNqjbL9tTZRWrRuV7AZPh7HF7xB5OHh4eHhsU7hY4gGB28QAWmY/SVVrKACy820xiKN68ZjQqyBK9/lRVLb18339jTa0YsBB1g7vUI4t81b6wyq7nfMg/Bq8rnlMwpvUdDIAptLixj/pPbohAiqpqxbtIR2I+t7cYTPH4YR6/9pw3PUiPVra7FNCUU1ZD3OqeqM7g+ZYwlicuo5ZdaLh0gZF4OMy4nTUOJVZL3F3vHVM7xBBARp9heX8VSOZ0V5glmtiJq22ssP9VgB1iWN5nF0YQBGkEn9rt4QcRpHg0YvCwEuCEFFpZXM+Ikauo9SHXSXwyuR0H5Rth0MnwR1zZIyjJamPrAUQcG6lMUQVZCWP1nW1BhT7eup/XVnS8en8WQoWOf7xkc488zj8MAbRB4eHh4eHusUiQSGR6v/472LqFd4gwhoTETSrkRSXkSQczlbCQUT43rbAS0db7iXB+C+X2sxuJ5Wq4eJUlqXQdeePjuqMIj7xlUih1iTpIY1hvN6FN+hh1wpBlXPa8+LEmYMkoliG2kyI/kLw4ihSaSyz6JFlA8agw4RstYC0GDVEsQbyxkfd8qIFtPdXtE0Gb07ppTc0fNs+xiiwcEbREB5IZFSMzFq8qSV7BIdq7fUkXDZ2yZqT5l5rASGkvIg6DOc74HWvavub93QZ72AC5jxERERKS1q46S0aDewYhg2MSgzNc9SvTqqMUZLG0FRmFjb9fjwv8IYW6TaPiPt2IQ3iDw8PDw8PNYpVh9U7Y23XuENIiCuBBKUAynV9Q3U2Jz5dYf29tDBoAM8B5XqsAbUkfcAeRwLOJz1y9baW9SNTjQ+d7FnRkgAKKz5TPcnqqLcRUvzYQkoM77LIwRNqzKR4RKCsQ+AUwN9Vkfg9UyIMQ1n/zy5uKnYRMqsleovVl5hOQ7uq7PMBjefZTFEqyjueszyG2sPbxABaSmQpBwIM2tVncA0zzYTWZZx1sST7zIcbIbSEazHRBxOl/1RbwT5eKKjC4N4ptBvL8/LSmOLuj2XSgFbxF2PsC/0cK8nc1r1OSxnhpASaBQRCZDfHVAdmTYV5tbSktpXbwvbEGOs6THRLmthn2Yu2DgGYcYfNTYW7c2QzGZwsc0gYlxRN9VqT5kdm/AGkYeHh4eHxzpFsspaZj7LrHd4gwhIosx1HPKq5F6OdEi7hsMt2j2bPt0Dl9aPd2GFq1yuItck48Ux5m6udw+P4wYD8vLanmfDa3QkvJcWwdqoDo8OtNxSzBkxS5UpHSJkpxmSQPQsRfY5RokwjpW0hygKDt98pDxH/VBuq4WPIRocvEEEBInI8vu8Xc0e5va4fpIrTz+vd+hHtboXCqafiXUNJuSV0mQrLk7r4XGsYL2k4PdSJ63rcY5sPVcfzSyWIFjUxcxCFDNLSni1UOGaIox5uBCLvzY32lWrA8QNRRBmHKtmhtCexQ3FtpeMYn52wJZ230uKvvK2DDJtP5HQ6xANCD4wwsPDw8PDw+O4h/cQAe1aIGklkJBSGDZPyOiI/ryuV0gp2lb06dGxemGMFdvK0sycXqE+XO/eE+ThYYc1CHpQXqM1qDtoPNucp1i2JPcAJWMoVW8IWGJzCfQZ3jjtPEMsQWJZWtXno1eIoA6RKtmxpaYTXYZDXTytH2rLFSjNPlTWWmuANFScBhKnK59vV3Ps8QZvEAFhnEoYp0aaaBplNxPr6iTj2scbzmsqratBRKwBZcaJ64HWCifcHiZQb/yIzzg72qB+ozWO7VlpVuaax/j1iRUrervu9UZOmSHLLKk6hBkr+nzNUWzPbam0ROsJY4NBVCrr86R4wSul6q0VbRBFK4zvsRk+IqahdESKu64yqDr2lFnP8DO7h4eHh4eHx3EP7yECklIgQSkwaDLlLYqrEA8bQ4D1ECICoU/UNcDagb4ytrB6oxaJoVFiyUYJSjpjLo0Hudbx8Di60VN21xHUFRuYJzP3MgV1rcNmzJHDrFqP4yzOKXqI0hJKdJTsAdblkp6zhkuZV34/XE9TVS3M6AIDqLtpCh3pWmBJGq4qiDvxWWY9wxtEQFISCUoiApdsVOpyM0GpNRjSfHq6sLSiMbjc2VZDKSXfro8zhNowKRb7OI7z6BGePjuuYD4jmko5WuUm1Lh7mWtcCtZFeMA2Pf+1RvWzUN8IVWuk1dM4UsVgS/v1cQ0m7WLuTWAcDZW1EaYMhXlUjXXFDdGwoYER5bn+xjYYSaTPBplur+Aps8HBz+YeHh4eHh4exz28h8iCqIUVkmVBkEbajozHNGUWHcDqcaX6RP3AJZ7IVd2RdN+vc3RbKXscxThM931PXiHbc+ko+XG4SnscdlhomHYNAozIHON8lFo8ThFyUahTlDKoGh6ircO6HMd0M5t/XzpuF8jthWrqRonZRBEHq0O0ukwx/wboHd4gAoI0+0siuFbzK9SuhcZ+CqVF3KiTE7q9sIieB+yy7PIycGWcrLnY4jqp1+aC+l4rzsDxWL84TFlmfWMNzj8Qg8dFAzu2F+EBRi0z7IrDGlrYXyItKC3t4ey5q0zb656FMII2j2sj6CWjLxTtapDRZ8ORTrV3GSsutWdFg/E40mStBAVi8zT/9gDvq9ULM3oiqFf4K+Xh4eHh4eFx3MN7iABVy0zg7k1U4F/deoi0h3WUYDSDasnIPkvmFzoPpCdiwIlevXhB1sRT0i34+Eiv3nOs6ruq7+CDq49Z9B08jftaUVsuL88RobvWAGpOC7bqyvJh216ig5RYaxSB0uWs3Xylnh/TvcNFu1bTwdNDJd0ejRyTsQWxUXaDpTkQNJ3TANQv4nEMaK5K9kIIBuj1X30tMz839QpvEAFpmHHcQcvcJmJy4gbnDS49rejLGURdbsK1zlBZA+NiTYygdZKKPPBaaz7zbH2hj/ttTShTixEkcvgMnp7O0eWe7Pt7G/1lcx1jKFnQlZQZhKOlxKKw+ZCac1rGZNNLDlhPXYt0qloZ3NxKX/Y246eOFDhSZjxfOU+Ni0Okzh1mJBIYxtxKjvfoDd4g8vDw8PDwWKfwHqLBwRtEQBrqP4XA4mgwSntgxZOWLEGHIiKKMot7qErtWNnaAoDXJdYhDcZr1u36+aDqYwR9BFWvtWe0H6/QWpTxOJIZZynqlIUtPlv2QGluTirZBynotYUl7S166bbnivYrJp4q2vTY2NALTWYzEsxyHfq+4flqSlSpyxg8jk54g4gIpENJVT03TKNnm25iGkRSpjzrytCXS3s9ZnStdEw4Lm23rLvYYjOCyKEi1wd8xpmHwooXH13u+8NZy2xNjCOMOUVBVz4PQSWLIQhiXCPSYXx0HA6KoJWrXY/q81Ur+nmvRbptUFwWCsjlBWGGWBU0VzcaKcRKuBbqcczlBdjqsX1eOhxYvTCj9xD1Cm8QAWmQ/SW4KmH+0NJVZBhBNJRKeCFjclAv6tTlIXKgl5R4x4G63U9sy1obUn2k/xMPxves8HRr6z1bsXHk44mOPFZ4L6+5B3a9pP93Qb/3erfFB2Vz2Obcqkp2lEe0cVGK9HVqJ3aF6FbS+2tLpcmLmEZVC/FCygNkxAqhzXNPlDI5lWppgDFEaSDJanSIfLX7nuFnaw8PDw8PD4/jHt5D1AWKVjbihrA4Sirw4kDQMa3onYLxsWzbgYM4cECxQP14KNaaduunv7U4n6uPNfDSeCrNY1XoM8bIRavZjl0LCq7vezrPog0b2lNiFMWO7PSZOY/mSvHwvs8jhiiZ0Acuxno70S2eqFvckIj2HNGDRK8Q65op8cbBKlWvjjLzwoy9wxtEQFIRCSoi8LIWLl54bw0JIVJjCWKI0hJS8Ks5317RuftFccTlWC+xQA4jIo3j/GPHBOoYfzeDoqcXwDq5Nn0ZR54+8zjMcD4ja32/sb9aZqC0JnTySGuIi0O9a1tn5ktSY8xRflxDz5VpCwViN+vtLtonCQ4dTxQ5irFy+wutUREROamqU/5Ng4jxS2HH54cbq6927+edXuGvlIeHh4eHh8dxD+8hItLsjzF7KsvSyCzD50YbwdbJkA7aC5q5h2hsVJ/K5SFa51gLumjFgasrzFTzOE6wzgOXCzjuzQfjP1vT/tYalBJJJ7MwgLiqz92YZLKJPo4ahmm9kz9LkHb/Ez+m0+tPGtYhBkyJZwZYmAvjujxIkWO6IpW2tTKb96vvn7FQq2GXA/0F5pLM3dUeYNp9LEHXArTdjvfoDd4gIvK0+8BGmSGLnpRaXNU3W6kO/YsK3Lbl/GGuoBMqWfeiTzTg+h7ODLduWTNddJSM/g7nC8xTVR7HCKwxR0fgnlbUv4gOD4iHUK4IU1QLU11jKzK95lESYywzNDZt1oVbm0yThzq1qRHEmJ5sXnHFEjHtnmBMTjnv29VHFHSeb5CZW54yGxz8lfLw8PDw8PA47uE9REBSykr0BKhbVlBmzCyDOiszK9rwFkXwFsXDWYelhtbbCEd0EcNkVq+QXBiEUrWLDrN6d9Y4wLlfEbluRTMNrBdv0XoZx7GKdRJ0v1JcWH5T0bZ6ZYk1yKjsW28IHqL2eBZUzdjiaAnD0zVfpXxQ99HapufAHSdkQcw7RmeLbZsqutBrI9avp1LYRZ0aa3sGQRP0MjHzqq08RLFdh6ieljvajQF6iGJZHe3lNbV7xxGdlW+77Tb5qZ/6KRkbG5OtW7fKG97wBnn88ceNfdI0lZtvvll27NghQ0NDcv7558u3v/1tY59GoyHXXnutbN68WUZGRuSyyy6TPXv29D2epCKSVJeV8MhptLis/xL8cd80DIq/uBbpv5GSxCMlSSv6T0ZG9F8U6j8XglAkCCUIg+LvSOBInntNkCb6b026S9d/OZVjGfw91/i3HTTUvdTT/ZTPBx1/PaCfZzgol4o/qVSKv7gaSVyNpD4ZFn9xVYq/INV/SSUt/oL5qPjb+/yE7H1+Qn44s6H4e3pxovhTsTNrFQMTBmnxZ8NiUin+ZtrD+i8eKv4W42r+V7H2cTigKLPV/Hn0hiN6pR5++GF55zvfKY8++qg8+OCD0m635cILL5SFBb1KuP322+UDH/iAfPjDH5avfvWrMjU1JRdccIHMzc0V+1x//fXyuc99Tu699175x3/8R5mfn5dLL71U4tjbxh4eHh4eRy9UcdfV/Hn0hiNKmd1///3G/3/qU5+SrVu3yu7du+Vnf/ZnJU1T+dCHPiTvfve75Y1vfKOIiNx1112ybds2ueeee+Saa66RmZkZ+eQnPymf+cxn5HWve52IiNx9992yc+dOeeihh+Siiy7qfUAqy4xlyPLFSRQv2y9HgjSGBIuGdgJaLS//EY9qcbFSHfTZxLju48D0oceIVWAQ9rcS7rbyHJT4oOr7gVbv4nMidq2iVdVuUp4ET18dXTgaPUCroLhWXMLH0UcPO+s2KTOUJlKM0dJm3e/SNswfyBxTJTqWo1zL4hEqkSOYWVb2XY2AaVBfLLsWglZTHiMGSjf6KA/icexgXf3qMzMzIiKycWNGQD/xxBOyd+9eufDCC4t9qtWqvPrVr5ZHHnlErrnmGtm9e7e0Wi1jnx07dsiZZ54pjzzyiNUgajQa0mjotPfZ2YzDToZSkVoqAYwZUYkO2OQQTRU6pFJMKmE7e+DClr7cUQ1p+S3dYVCmSJmlXs4qXga2OKQVGz79xsM4RBptWKny7oqNozWIx/BK1kcvDivluVKFdhY4HgQl67rXQeOzeHV7OGsP79NjayLtvrmzqfuYp1HV+V1OHJ0p2puq3eMpYxgusWR9Dwf6fIwVaom9gj3T8QsKDdso3GhTsI7DwdUySyXoWoy22/EevWHdLI3TNJUbbrhBfuZnfkbOPPNMERHZu3eviIhs27bN2Hfbtm3FZ3v37pVKpSIbNmxw7rMct912m0xMTBR/O3fuXOuv4+Hh4eHhsWp4ymxwWDceol//9V+Xb37zm/KP//iPHZ8Fy+TZ0zTt2LYch9rnXe96l9xwww3F/8/OzsrOnTuLavfMKFOLEXqFImgqkiaL4SYO4J9VWWnUJjLosybqAeV1z0RE0oPTONHaZXetuQdjhdlT9OKsRT2mlWJVtNtK0c81O4w12o4aHE00mWWsR+Qe6wbH/cP5IShrT3YC+qw8n7nDG5Og8Pm14RUa3qG9PksLmEjzKe3ZRT3n0UNEoUTSWWWECijqizQZPURViCq6qDQFwxPkoOsUjWdXN/I42rEuDKJrr71WPv/5z8sXv/hFOfHEE4vtU1NTIpJ5gbZv315s37dvX+E1mpqakmazKQcPHjS8RPv27ZPzzjvPer5qtSrVqoX3ilKRKJUUhlSci7NGWri02CYiIkg1DR0K1u1cvMyYMJDKGTZ1hyFEGoO6Pmm6gBOtAzAdN+0zeL2g7g5jzPuavIBWaOj1TZ/ZYpl8iv6awPVb9EVD9ftbdFm09FO4dTXoZ+Hj3DeEwZPiWuZfizGUoQ6LlBA1yRbn9Pw2tVXTY0PljOZ60RhriOlzVEFLMaaHlJkaNj+nsWMYUo7tCpGDMqNhpjLeBpmuk6TBqoQgBykiebTjiM60aZrKr//6r8tf/uVfyv/5P/9HTjnlFOPzU045RaampuTBBx8stjWbTXn44YcLY+fss8+Wcrls7PPss8/Kt771LadB5OHh4eHhcTQgzqvdr+bPozccUQ/RO9/5Trnnnnvkr//6r2VsbKyI+ZmYmJChoSEJgkCuv/56ufXWW+XUU0+VU089VW699VYZHh6WK664otj36quvlhtvvFE2bdokGzdulJtuuknOOuusIuusV6RBpifUHtUrgtK8kqjX+4WgzOg6NbLTjEC2bNXDYO0ggYt3XHuryliFhQlWl3mAddrEMmy9CNG5Vs3dxjQgz8ea0HGD8NgcTbRQP1hFAH5fp6Gn0nKevoOTbePohb7EPv3cez15NQfxzPAcKDfEoGrlLaLXu74FiRMMnkYowb4Dmh4rlbPfa8eIFmakV4jiiS7toG6gVyi0lODgdtJkg6xm77F+cEQNoo9+9KMiInL++ecb2z/1qU/JW97yFhER+c3f/E1ZWlqSd7zjHXLw4EE555xz5IEHHpCxMf1gffCDH5RSqSSXX365LC0tyWtf+1q58847JYr6Y3qToVhkKJZoQR8XD2UPSWmeaQm62UAsd3kBbSQhqKKvCbaxKKIxhrK2vCqYgKJG5l424opix4tmwC/WrnXPlqF4ca1DA6AnOsM27vVCa61Hqm2lBnMP6OV+67PDomm7F5yGyhrfyyulfHuiybpdpx76aI1kc2RzAoc1cBza5ef0fLp0op4EN5yQTZhjJRZStV/HyGEQKaPJ9bnZB/sOO7aXYYy56popxAM0mDxlNjgcUYMoTbvfxEEQyM033yw333yzc59arSZ33HGH3HHHHWs4Og8PDw8PjyOLRELDW7aS4z16w7oIql43yMt0JBW4TusqQ0zvxsUgjW9mp1HZXS08YtQ6M2ujQesDq7MQnYSTo9m/oNGSaR2gKK6V8gC8MMYqfT16KNYA3aiPC6Jfsm5fc80nwvY7r3Vg9lr3sQY4nLo83X7nI5ENafUWGQKtjvuqy+9lHOfat2ynzJQOEZNN+N5Ntum4gnBEt8vNEnbPfsf9jdFi24nDB/E55rouL3Wb0KLIsowzgQcIEeAqLZ1CkLUAwrkWqi0NBqdDdCRx2223yW//9m/Lb/zGb8iHPvQhEckcGe9973vl4x//eMHafOQjH5EzzjijOK7RaMhNN90kf/qnf1qwNn/8x39sJE0dPHhQrrvuOvn85z8vIiKXXXaZ3HHHHTI5OTnIr2jAG0RAUEolKKWSUkQwV5luj3RmWIiIRHUoVZdhzMDgaed1XJmFwX3jCgylUJ8nauhJIBnK4oyiYU2phW3w7a4Csf0YR2thSPVAjzwY/9nK+l7HcH0n0h1p0rtBsebG00rT/A9nzM9aGDb9nPswUneDgr2ocX+hAf3cW2nZ/oqI8/mLGbdxVf+elZqemyaGtdW0eZOOK1AK1VM1HUO0UhxojRTt5+vawNo+pBeNpME2IL6BRpMNNkHHdhdKbS0Rp4GRWbeS41eCr371q/Lxj39cXv7ylxvbVTmtO++8U0477TS55ZZb5IILLpDHH3+8CGW5/vrr5b777pN7771XNm3aJDfeeKNceumlsnv37iKU5YorrpA9e/YUFSve/va3y5VXXin33Xffir/ranHsLOE9PDw8PDyOMagYotX8iWR6e/xjtYblmJ+fl1/5lV+RT3ziE4aczfJyWmeeeabcddddsri4KPfcc4+ISFFO6w//8A/lda97nbziFa+Qu+++Wx577DF56KGHRETkO9/5jtx///3yJ3/yJ7Jr1y7ZtWuXfOITn5C/+Zu/6SjwPkh4D5EFhqNE0WdVvSJIl/SKImzabcqWLk8mlensX2oTUTw0atq3q8BFEZHSYua6DuuaRgviEbQxvpVqFrk8A2sd/HocwRmk7aDYFHqi2lb6u/Rz3KDorjU4T9cgaMc5jqQo6FrAuFcciSTWe4jPOKl6isOCJksqKIPRys5Z30TxHmZp6fZoRb94R8u6vaGymO9LDwzoqR7W6/PtbD58enHC+vkSYxeY9WJBjMzgxURn/lbh2ldepkGmsqerrFif5scur8jwnve8xxmb+853vlN+7ud+Tl73utfJLbfcUmxfq3JaX/rSl2RiYkLOOeecYp9zzz1XJiYm5JFHHpHTTz99xd93NfAGERBGsYSlWBK4oIPR7GFIGpgMSGUh3qit7ROpTIMSU88W5x+Hcc44I1JzrbHsp6KIY6kNEUeBBYbUfGs9tD6xJgUlfaaDAVJstrgQ4misk+aMK3PgcBklR7ux44IRV9TFuO5ANxp0SNPyaQW1FS2xjlTtb7HoNSRGltpQu8aLXRkX5T6LVG8oge7KaejRkl5VtnEOGlvlUC8abTRZCyvWRXxOQ2k4bObnOPoWeE899ZSMj+v3hFWcWETuvfde+ed//mf56le/2vHZocppPfnkk8U+3cpp7d27V7Zu3drR/9atW50ltwYBbxB5eHh4eHisU8QSGEbZSo4XERkfHzcMIhueeuop+Y3f+A154IEHpFarOfdbi3Jatv176edwwhtEFkQVvZII8tVLUtcrhqSK7IdhvVIoHYS8PIxvtfAgNcb7m4KOYdu+XQVexzV9jmBU37BRG2OehPsYmWiFt+gIZ4Ipj8ixunrvF12pHkfl826lKAblTbJ6EI9Remq9gF6hNf+dHRXuW6N67lnaaMm+LTPT1d41vTfKWxQ7vC0TJTv1TwprPNcwatXm9DkSPVcPGZOuBjPKlMFArxFLgVC/SHm1WgP0ECXp6rSE+nHw7969W/bt2ydnn312sS2OY/niF78oH/7wh4v4ntWW05qampLnnnuu4/zPP/98h/dpkPAGERBVY4mqsQTgsRvz2RMfgB8XqLCGS5g8MCHweQnauXsZzybjiZiwEMMIYk21KI9Vao0hfqmNFNamtsCMmkMTWBHMZNkc/dJo3SbcvimdYygd/3ChF4HIbllra0J19tL3CpWZPdYIPRRpte7DIq6gT9IRvdAyFmD4yasz2f+0h3Qfze16hzFklsWO+5RGhx6SvpfqWBEqqkpEZDHupHrGS/WObSJmhpjrPHFuCNkMHxF3oddjEa997WvlscceM7ZdddVV8uM//uPyW7/1W/LiF7+4KKf1ile8QkR0Oa33ve99ImKW07r88stFRJfTuv3220VEZNeuXTIzMyNf+cpX5JWvfKWIiHz5y1+WmZmZI1pyyxtEHh4eHh4e6xTJKoOq+zl2bGxMzjzzTGPbyMiIbNq0qdi+FuW0XvrSl8rFF18sb3vb2+RjH/uYiGRp95deeukRC6gW8QaRgbHhhkTDInOLqD5fyimzJoWFQFUwbrjCVbNuKmkhii6mWOQweNp177bylRirSNOF3R7SEd21Z+GxQR9BkulzpC5BR6KPrJ/+vUKDrBV9bGFNKqV38dCtl4Boj/6xUvosgL4ZvUJpCTprhvBstr2+Fd7yqvY8T8/o+Wh0VFNf0w09t46Xs+0lzlKYAOlBImVkC4iu9lF2Y3kfymCgJ4j91UDRKaotGqDXKJFAklXEEK3mWBvWqpzWZz/7WbnuuuuKbLTLLrtMPvzhD6/pWPtFkPZSP+MYx+zsrExMTMiZ/7//LNFwVeYXtLXSruduW2SWCTIo0shi+YhINA9qS9FqzFBFdgYNIniGhRS62l6dhbET43w4LmrqDoef0MZPMJ+7lRd0lkYyj1TUPl+E/cD2kn2gde+ansOjT8OoB3hjZ31B/b5Gev1KVauZan/SCUW7vUkLGzbHNW3VGtXnnDsx628JNBntlPa4NkqGNuqJbOuEjvXZOTotIiITZf151EOB1X4MIldB12FMmDZKzFXXTI2vPt+W337l38vMzEzXQOWVQr2Xrvz7X5bKaKX7AQ4055vymdf86WEd67EC7yHy8PDw8PBYpzhSStXHI7xBBKSpGQwtorPMUhroLHwfoczHPOr+YJ94JNsnWtIb29pDLSVsZ5whNcXUIqY1TJ0ie8mPFKvBxnbtxqzuyfYJ4P0JEbhteIvodV4Db5GREZX3TW+G90SsDfx19CjQLXnBkd5s0PaObFi1vbTg6IN1z8ZB88fauzOSe2lcHh2C3p0mJsmhnM6aa2sqrgLvznCEeklAbGgVZednULWLElMZaatJg+8Xg4whOt7hDSKgFCUSRYlUKvqBUo5VUj61Ie1uXZiFVgOMkmQYRsdiNgm0R/S20oK+SZk0QQaO29Wc0RrG6WinOFYBRozTUDajBW07xx6gNlq6hKyNNQ75OV5Vqz08Vgtl8F5YftPqO+PqD3MCjZmojnmsjTCA3M4oowxZwvmqBWHall09eylPqSXdxalhpGRXr6WQoxJmHEOWWeQwqow+YIQpesyWii+is9CI1lFU/86jd3iDyMPDw8PDY50ikWB1OkQD9GYd7fAGEVCN2lIqRdJs6ctSLmcribGhxWLbwTntpqFmUTim3bNt0GfJcNZHAHHHuIaAaDhj2vAAkUpT2xlnyOPKWFqV6qDPytRJys6fVvGzl1CmRABoFfWbddQNij7rp/q7h4eHBhMSTG/RoSu3OwHvMJM1kpr9GS2YKIYGUPYI/0NR28Wmnhf3LmV0/hBoLVcgNTO94pQaQdlc5qpYH4pdW8ilOVQANBP7VqKQsWOchwPpKrPMUm8Q9QxvEAG1UktKpVDiqn4YxqqZ1bF3Vkfn0wiqDOsHtbmoH/YI21XKfgqF66AOjh1UGovFtodoNOVp93h2+UwmFaSlklYDhR4PZT93AiOpNAu3dFmPP9gAtesD00VzxWrXFkPqaKnL5eGxnmEWd+3jQMYQ1SDsGjsop9TRVsA0wAzZdEa/Zlqb9ABn6lkg5fNlndVWg3HE+mShoA0DppG/wqhOnRj1yzC84NCCtEbcEPvAPso4GiRlxor1Kz3eozf4JbqHh4eHh4fHcQ/vIQKGSm0pl0LDop5vdsrEDyOoenFJp4KVh/QKxAgkzIOtgzJqoKE/w9ODT0LW/anmfdTtGWnMWgsgHNkegs0bZGud8izGOazHz4yz0EWl5d6iNEbttBKE3NosxsYVF8eRdvThM848PHoHnxdDk6gfMKjaoMXtArMRytmH7fwZhpe3pKMKjEy1lk50lTayzBYa2dyzJ9Xe6Mkh7VraXIFeWsQgZ935Up6KSxFH0m5hYM8yI4osLAcNZpbxyLPMBkiZ+SyzwcEbREAliqUcxSKWZ2i0pqml2SWdWaZijESWzSNIiQ9q2cPTrqNgICk1Gk+YMFhENshvasMI0p5mkXndDGHDLYH+G9qf9RfgHCkmmgiqtILtIWujbcqK9QWMMZrVYmsGSInFnTy9WZzUP7QeHj1jjesBpiW7UUX6LGwgSzan/PmuTSEOm2KeSlj0tc1CxXkYAEIQlspQu27pVR6LtHJ/ZQjRICozrsA2mS+DyijjFWXcUASq7YgoVXvKbGDwbyEPDw8PDw+P4x7eQwTU2yWJ2yUZLjHrIVsJzNa1V6hW0Z9TE2N2SbtmDC2jZnaZa6N6ldPGSimBvoeMYHWDwGu1YIkZaD3DtA7dNDPVsL2W74TVpbHCiyAsGSHwGh6iMM6/bxMrL4fAm7NOmoeHx5EHn1sujY3Y4tTaVjHMxvyBdhteaiaTJC3OaVl/TVB+MTzFsy09526uahd4FR4bW1YaS3G4NIliC41EX5KrHpo6nysb7nBgvdUyO5bhDSKgFCZSCs0bfTjnoFsVpF5G+oHcv4gihjVt8CwhvbRWzfoI0XcM1cXyENL1G6CzyogXyvn70rxd0NEoJoswnhjtIC8Qy2c5qHZOUCLm5JZUtIVVbWYdBkvYgTEMNJTWukCsh4fH4YFrUcOF1ggMlzyrlerVXIi1WDKrap8HlMo/z9yO7aQFs8gIlbLPOJlSaDdmjAKxkCdQBgNjNg0DkSKOeYxnKD7L7FiEp8w8PDw8PDw8jnt4DxEwUV6SSiWW6aYO5mvmK5Oxsg6qnmlqV+5wBTQYgpVrZe0pqeaBgjOLul9SalwVVVDyozGLKtb55vaYXq2U5vX5DJoMJckElUWKpVhgp9qYMVJGUHXtoP4uaTUv/0Hdkrq+Nr2QZFZhRniTLoh+qWg/GP9ZDz16eHh0oItWWFAmRc6sWCQ7cK6wPNxM8mhCuqw1CRHEKtolzF95u4a5cOOwTlXbWNUTGb0+NhpsvKxVahux/bUWi32+UVMdqaUWvlgUkkO0dn1Y4T1Eg4M3iAAlkV7Bw6cotDZe3kOIMWKxQorEjuAhr7eziYdGkslh659haZEVXTXS8by/BWahMQME9BqVxOgFzrto00jCw5LYTy0lKM2GjazzEOMwUu1XCmPC9un4Hh4rgSHS6KKh8+3BhM6HZ7ZpR4VrdZhFsJHv2jIyXY3irkOYGDH3RDllNlTujNkUMWkwvtRtBhErurtS8KuOQq/9QBlVyQDJFW8QDQ6eMvPw8PDw8PA47uE9REApiKUUxgbLpFy1Bxo6eJpZaHWsVkawGmljdRPlXqaRivZ8LDS1OyaBZpEKNBQRCZBRFi9lPxUzNlLWC2JWB37VYAGCZvk+DLqug2qrHdDtqGF3E6uVXxqCzqvA9Q76zPD6WNz3AYLMU0dG2opF5zw8PA4NRyA1vTsptMnicuf+nEtSOGDCJicNzFOYs1QJpKUWSh5hTjgQ6MmpiaDqibJOnR2yeH2oWUQ9oUW4wDfDneWqg6YQk0orSnd4HaJjEd4gAspBIuUgkfGK5qMPNDNDaBQxRPVYP8Djod5ODnqxrfcZKWcPKB98UmasjRaVaCRQlTrbnlK4cRhq0aC1opZdzVo9FzEsPsYbMZGjSNEXs8isqoOWVnTHQQVcG9L1JT50DIOLJnO5+j195uGRw8jgXOGigfIbNIKoCo0s1Pawbiul6ghUPRdijDcyhop4yUaD3H4+JIMys8+nzDjbUstEYZkmT6rNlT5vS7snogGm1XdDKqtLnffiJ73DG0TAWLkh1XIiizB4RkqZwWOkdToelsW2NgxYmFA9zK2E6qe6DwYVEgt13V+Qp8SHNShjtxggxArVejPjjILcwCrNd4834qTYGumcCJMhfaBR5gMendRVGsACQ7XaPoetuTqvh8dxjZqeX6g7lsA44nuY055yZKeYd1jhnmE+ARZ2KSv75OdshSj9AyOImkQxqrTSQ6+MppCBz46UeMYezVP2JDeahuFZqqIqtk2V2itVH5vwbxgPDw8PDw+P4x7eQwSEkkgoiQyDl1YCXOSZR0TTZHNI2Ro2vEJ69aX47woEHaPQvoqZQZ002vXVWjamNlStW1iRCegzrtpknsXPOns2ag5RjJGeI80gFiu/FCs2IWVWRoesX2YzvV1eI0fskRdv9PDIsRpvaR47lJbhzXVQZgliiEIUd1VUfAlzQ3vInqIfUHF/qDMGMgGNFtPTDc/ScFnPrRTPreZBTC5FaheYzab6II02Gen0fypfqzikdrAGmbU9wnuIBgdvEAFhkGZ/iGeJcoOoiuhBuluHQqbSYyKB0aFcvLwx69DKWGxpg6IKnY5KpNuKbqNLOUQpEE4qLRSRNWgwWxgPbBYaQQm3U2tkLOukhGDtZFhfj3ABfB1Uq9MEBuAAAxI9PI5XmCn4XFjkCRo0guwx0EbbLOnReb5SHedzvIQNuyU3eDgdMIao7JgLKw4lagWXcVRyxBOpuZrxRgdQOXuCxlHed9inAbYaeINocPCUmYeHh4eHh8dxD+8hAkajutSi2JqBYHh8Qu2ZaQTarTIfa09PDbRbklM9pNG4wiCVVsbqh6n7qvJgBJdzHfXSWvQcIXWfjhm1qmOWKQOYDfoM+7SGoWC9kI07rkBWoIqdQZ/RKxQgTT+ND73C6wUq48xnm3kcl+g3y4wZZeq5RNq9QYFHDo9C0NlOXarWdAg7apnp8SAYG9tJVbFdgbdehTKEcDO5PET0lHD+Vd73MrxQFHRchKaJ2t72affHJLxBBGRp9/Gybdn/G1oVmDto5JTxEJWRsbCUZ63R1csH0pW1RlpN7U9l7Bgu7xZii5I2BljCg9vOHoyYCtdM0adSNYvFYnitkdy9vAjevwaZ+6o20mgEBSNaUySdnVNfSneMACZTn8juxAzyr+vLfHh4rBAOA8YFo+BzbjQZa0d0V5nT7UYTxlgZBaRzQ8jByslCQ09IcxVtlGyusTZRBqbiR1hgxoYR1HGYE8wqJj94JIq7pmlghEqs5HiP3uApMw8PDw8PD4/jHt5DBGwqzclQqSRzFPLJEcOtGyP6mO5ZpVkkor1CIlrtehj7UnmVniNut8Hl/gwMNzHd2HprmmeiRbP6Z49rdh0R45wQn1YLp3YVwo1GgDVowUld7TGdx6pOrUxX43a2qF17eBzrKMRJ+80yA8UWjmQBwzGpMSZf9OJQUI8w6Xc6VZiE5XrM087PmRyiimIvB4tvq/mQitVVhiAEdq+8DWQBSJkdaa9BIsGqhBlXc+zxBm8QAdWgLbUwNR6MbrLuQ4wnQjpWEnby1TRmyiHO4TCCWFBW9UGxMqalciIJkZ1BqXzJ6bFkyB5jFC2BtortVFqSy/cnkPE34omgYJ1O6kwNmZmVlcAQbLSl6ePF4OkzD4/uSGazshVBG9S0o4yHAUv2GdPyEUIpLV03dtnJLf3RLkP8I6meZw/oxVVrAovJ0TjvFgs0LDA3lHSGWOwwbdR2xiGZlFncsa8v7nps4kgbvx4eHh4eHh4eRxzeQwSMhA0ZDiMjEG8uydyzdL2ORVqNjB4kI4shgvBXrlfPfduJnephkDahvEWGDhFEzMpwL8ct1hajCyg/DvXSklns64hupD6RYgLpIUpQ7ygeQo2zuh6TdY0S2F32hkKkQ5jR5i3i595b5HEsQmVV8v5eKYIGC6MO4QPuZKffrf1xzqAUWpNeJFD0inZzeLq1791k1/cdGC/aKjNs25Au1mp4rRxrflvG2XqqX0b4oOrBwRtEwFDQkOEgkjpS6Ss5Gd4KQHHhGAo6sxaOLXWf1Zb7dWOqh7ZEgTL00Wgi06uMrIiaNkrUg9FcxKhhuBnxRkzB50SXf4UWVGlD1lTDLRXWEUc1Dh96Tp+lDqPQlX1GqNghK40m3jjyOMaxBsVdgzlNJ8kObWSYqfRi3257LJmZikkyQnHoGHaXUqrmsxq37c87F39NKF/v2bdBREQmTtSL1LZjkUqai1liSnyXi162B1m3zAZPmQ0O3iDy8PDw8PBYp/AeosHBG0RAWyJpSSQ1luOwuFzr4JBauIRcVZAeqxuFwTIk1iWWKdLIQEFl5dPab8CNUwFlNjak08Ko5dGOVWYWggfpIYJGiJlwpv+nNZLvi89LDQQ01hmMje84NqJ7U54hZJ4ZYo30jxveokPTZGkPVFuRpSNe1NHjKAazzFZY1yyd1TST6QlCm55io92pQ2ToFIGJZyYrTxSo55kfJ46XNzYHnLPyierpOR10vX1IJ3CYunKdwdEiLMeBzDIHfabmbdf87XF0wxtEQJyGEqeh4U4t55RZFVw63bd1vLyNjDS6baXTmGEmRAkPVylgOj6MozxF1pU6ylXAQlPPRiwiq8QbSxVMDOgvZk2hBiYMUGKpRcWWKfgRqLQINdXiCe0rj1rZ9wraSKtd0i7vw1r3bDVFMT08jiL0UwyZ0wqpsQTPu8v4KfpwMOBGoq5t/mJfHIexLtL/Mza+VLQ3Dme03/YRbQSdWDtYtF1ZwrFlGK7MsiONdJWUmfcQ9Q5vEHl4eHh4eKxTpLK6daEvpd07vEEElIO2VILUqJujAvESeBYqDLgDNTMXdwo6Zv1m+1fh8aEeR+JYyYUBKLHco8SVAkt7sKSHS1KkVsmoQMOb1NKS+AHLfJD6wl2iFoyGSxyBkm2UAglHIXTW1rRhuJAdHMyRd8NJmsgv6ZaJ5sxCs9NnhK+H5nFcg/OOndUynv3UIeSoEOupxCwDFNHVg+2qO0d8OJ/hFBZBCZmzI+Vsrthc0fQ7Qw2M8Ad4gIxg67zNzw3PkiXY2kWpeRzd8AYRUA5iKQfmg6Eosxgv5haIddJrfPjo4m3kMUR8iFwpnmVQXO0WsyWyfxdje1q+MQmU9ThYsHCplY1jsQ41aabg43wcHr3c7eE0/xyZIcgoaY6BMoNdQ/FGpWYdDev6ZtLuU7hRTeY9GD6EYTStH6+4h8fKwfveRQlbtgd4/gw6zKE+zalHGTz0PjQ24XNHoWij6Gses2is30jbU4W+i5uj5YjpqRtVBRAKgZAFJYxrSKhgfotCDmrwk0YigQReqXog8AaRh4eHh4fHOoXPMhscvEEERJJmf1wFqMUBV0qJfTlFqi2yBGZzBeJyz7IGmkHd5Td1DTV72iX7qmi+qX3Xjbb+iZcaWd9taH20Gyi10caDU9PjjyugwXINELrHeblMr5Bum0KO2TnDIXSy3163yADps35I9cDhRfIB1h5HKaindWH5TSvrpKLnGpfGEGkyZpwVNQ1Bl6NKRpGNKiICZ4wkQ/S2LPtXREJoqJEyC0t6fijBc6RqP/ab9WVkn+WHGnMy3Fp1qM2p43yW2bEJbxABGWWWLhNVjPL/glpyPAwuGsyWuk8OmwViy+ijgfMoCq6OWBwWgm0gnqgNtdfYlcaqzo2MsxAiji1kiKUNGHKj+T6YHUuLzErRfcc0gsqWTDUYdIFFuFHkEOKNXdC1BpqHxzoDJSFcRrwt3o33d9CHRmM6gphHlzq1o2Cr2lxCzeYE6xuGSzq0FvVi01V0FdurFXsYQPE5TuiqDckQqLKF+uI2Um2knOK8HQ+QhkrSQAIvzDgQeIPIw8PDw8NjnSJNV5ll5teDPcMbRICizBhRrDxDrVSvGIzgaazeuKqweYW4Ahk2uCXdbDlonEKY0SLW2PE9EAQY4WlQ4o0UcWy24Flq65UVS360sVJLmrmLugKPWRnBiNCgdIu65Zl7VQQ8llZWfsBZ5sMRYG14i3oIwvbwOCLo496kN7Qn7aF8n9YGzXdRRDXu1JE9xMl1k9MRyj1KACo+ZenE3HtNmswYJuaxdmyfHzZWM00iV9aXIcCIudAVbK3AOd6sV+mFGY9leIPIAlsdsl5A6quF964yqnp5aPmg0fgpapmhjxpVrQ0KTu9TKZE+C41/RUzjqc7xw1Cieqya3MK23a3uKhBrTJy57zoFjSZD2n0fTGrVWZmewTgY/6MqQ/aw/CHl4GuZeawjGDTZCrFSyswQYzQoM0fbenLddMUPsrhrgtiiYhuyW8tD2hCJkF5fLmExWdYnUvMes3PN+RTZwRJZt6uMsyoLsAH92IeHAz6oenDwBpGHh4eHh8c6hTeIBgdvEAFBkEoYpNYAam7jOsK1nVArlsSRWeaivkoBS2x0ZpnR48TMizY8QGyrIOwlBGYvwROUYN8kdnjJ1FBR7IyOL9ezZ9RKUnWQ4L1qT2pNlBLKeBinDhGY3U+wNWhIX/ne40hjLbxChJMmc9DvYe6BbTuOM55VR40z5Rmil4lB14aYqy6tKO0mOlG0u5H4qTsMMacZJYhAnykvOufKXoKIjYzf5NDhDUdahNEHVQ8O3iACKhJLRdJlbuLsKW/iASrjyW+mOrXCKOiKmKOZXMp5vl2z7tvA7NFK7fSZyj4LkU1RDWlgaUNptqVjA6hmrTLRFlHrrNHU42Q6PpmoFNuDXInaNUdwgrQVgxTRmWgJDKJSA7NpRJXYNUi1F6/A6HFsgUZVUOqP1EkbmYWS8plE252C39kXjR2jhrWDjouWkLGV728UdDVqmdlf5G2L4nTbkD/BgpYxRJgHEoNWy/6tc07D964GpONUlpnHsQhvEHl4eHh4eKxT+CyzwcEbRECoKLOUK4xsRVBxaFQYx2NlUoEXaTjMgwBxtRtJp9iXyLLgQAb+WXQzZuFxqre1p4o0Gd2lNtcwAxeN+j7USeQDZVm1OWPQHcGZajVqiL6RDqsiIpNPs6tImw2uGmd+aeexntCLOKgt42wVoqLB1s0iYnpoxUGNGW3L82yU+XC0ibTSKcwYxPbnOnDpEwFqzqIO2xCjuwF6kapBZ5klJqPUHfPzkaDPMoNoNTFEaziYYxzeIAKSNJAkDYwsBZsAl5HFRTesi7PPeXE+WK1QP7SLqIQ4Kvb4mZl2FmPTdsw0FcjBJsg+M+KJ8u1NpNeTm29j/PwqgVGcMWsbhR6NDDLr8KwwDCnGM1CwEdlnyQKkcFeIntKSPTzWEQJQyDZV6n5S7UW03EUCBfrWCEVU9WGGkYO3hZoCXTFG3FccRpVqRyOIvjQYcv0/lAcZqei5s4iLxKBHSuDxYEyyvqQhi1Lso7eNQTfAlnXs0+6PTXiDyMPDw8PDY53CZ5kNDt4g6gIVzBxjpVFmSB3vNS4aunhWSakZmWpYWtXRVrQbvUks87HEU+MBYABiM3crU9reEGaEHkhCnSFmlKlFlkGjoenQIWIZj5LSISKV5aDPgvIaq4D4+mUeRxo93IPdvD70GvXUN8txVLNj+UyaZXbE3sbboprLg1FviPUN6UBJynoiSNEO8iwzMuEJ55qAbX3cUrNTVJGUGRE6aDdjjsyVhkZD7RVqGUk0yPbNv9hKtepWglTM6XYlx3v0Bm8QAbEEEktgGChRfjsleDgTw92KDvBgx13iXWj48KFlHFJNOosHlfGg0jVMbptGUNjGjNUNmCRYWDGgMGM+YRkhTQwLoHHkuLvUV0gdmS2kzKSGWdboxPKY96k8rTJ1bPWhPDwGjX7S5/ulfsPNG4t2Ky+u3B5CrKGLJqPdhWGwqGuxDaKLhhHEPqLOycJ4bB3zZosq+hBpVIu8RVhmkWM1akid4Mu08rmuHuiLMIyQhpajgLfHsQdvEHl4eHh4eKxTeMpscDii/MEXv/hFef3rXy87duyQIAjkr/7qr4zP3/KWt0gQBMbfueeea+zTaDTk2muvlc2bN8vIyIhcdtllsmfPnhWNR9Uy45/KPCsHMf7axV8UJMVfWeLiLwrS4q8bKkG7+ON5wiAp/oox4XwqCDxJA2mlUfHH7e0kLP7i/C9JguJPuWM7R6k/SQMp/qTLX+r6i/RfEgWSRIGk+EvKIf6i4k8i/ReUy8VfgSTVf0Go/zw8PDTCqPhrjZakNVqS5nhQ/MVVKf6SCH9l/JX0nyTZX3Nc/6Wh/otrqf4bSYq/NEqLPzU5pPjjpJEm+MM+zVap+FNYbJeLv9n2UPEXS1j8JfiL06D4U2gkpeIvkaD4O+JI1+DPoyccUQ/RwsKC/MRP/IRcddVV8gu/8AvWfS6++GL51Kc+Vfx/pWJSQNdff73cd999cu+998qmTZvkxhtvlEsvvVR2794tkYtnd2A4jGU4TIX1P5uilKpRMNXRrov9fKpQIAvBsuiqoZrqqGWmYKaAdr/TqWCteHgWTTRCfhzp9UamaWrZ5lKzdalW5/sYYnCMIUKNs3QIv3dkMXSM4q59PvnecPI4yrDSLMlk42jRbo1k841LdDGp2Ldz/4Ie60XVGvONK/ZQISrr+Y1xQ6FlHiOYTWtknAnCCoQZZ/pYlR3MOKQZcIKkzxSa/c41q8EqPUTO8gEeHTiiBtEll1wil1xyySH3qVarMjU1Zf1sZmZGPvnJT8pnPvMZed3rXiciInfffbfs3LlTHnroIbnooousxzUaDWk09IMyOzu7wm/g4eHh4eHhcSxg3ccQfeELX5CtW7fK5OSkvPrVr5bf//3fl61bt4qIyO7du6XVasmFF15Y7L9jxw4588wz5ZFHHnEaRLfddpu8973vdZ6T2kMqG4HbjCDoHrLPVAC1EeyHLDO6balxZMt0sI1tebuNLDJuV5pDHL+xzuH/JI5VhU2QDV+bgdQM1DSqX7ct26oYZ8PuOQpBlaWOemc2pINczXl4WGDUL+vFM9mP99Kxb1DWD2Nzg9bzao7lcxryFWL9sfFsx46cjLjW+UwZ2wK7VyiweJADx76srWjMuWHnuY2q9o75j30Y27ukBMeWyBLbtsMFr1Q9OKxrg+iSSy6RX/zFX5STTz5ZnnjiCfnd3/1d+Q//4T/I7t27pVqtyt69e6VSqciGDRuM47Zt2yZ79+519vuud71LbrjhhuL/Z2dnZefOnRLmcTrTqZ4FarnhEjvcji6RRlv2WUjBR/iUI8eEQChDKDEoNXvdM6IU2IXJrOBXRDaIkQWihBmZMu+wnTjJ8ntFeT20BHpsNHziCq5NBbcoM87m5vMDuz/tTpohHzhfVj7jzGOgwMNlZHaGXDyt8OX74p1FMwYNrQQZjcwypslzUVO1z01q4ZPCODGmIAfVRpHXIFfJ5zZSQ2ahV4Qp4NrUStkkMlrWtNZ4yZ4+X8UilHOhErutRpTnl47PzW2DU6z2QdWDw7o2iH7pl3Rl8jPPPFN+8id/Uk4++WT5n//zf8ob3/hG53FpmhoaFstRrValWnWkc3t4eHh4eHgcd1jXBtFybN++XU4++WT53ve+JyIiU1NT0mw25eDBg4aXaN++fXLeeeet+DyThgZFZljBmWG4Wwmzlhk+UIsRbGO9NPZNnQuuYlQQNlc8LdYsQ+eGGCPcx6046hg/zxFYXNHLx104pbgrjmOgdIgFFwM1lRs+bHEbjmtxNQsNkAkdGBq2M29ccuCgfcy9oFh5+wJnHgMEnn2XR9JWosOAy2sEb2iwqOMk28PjRVs9f86g6pJ9O71BBXXOuaGEzyusJcg5Bh7rUtZmPcXUQvGLiFTLELJ1UF8KRrklzH88ruWg42z7HnEUKb6rON6jJxxVBtH+/fvlqaeeku3bt4uIyNlnny3lclkefPBBufzyy0VE5Nlnn5Vvfetbcvvtt/fdfzsNCgNIQT1c5IyNYqzcGYdSZbppcbn2QpNRzVoJQzLjYSbQmRBLsR6JK7ZIwcXHG4VeDZc9xq8mQkx+NMYCw4VOQUfdhXLVJ1TKhcMubEM0bVx/r6Clx1R6Pm8HNsuzNygqjUd5+sxjvaGfzLJwVKsj1k/RYozNMSwylDCqS4CRpzPocuyvnnNDuNFOsxu1ENG3mnviGBR5ZKeiGkixFxhH9XY2P1QiiDXCoith4nFxAirmshR2XxipRW+3uKO1hI8hGhyOaN7x/Py8fOMb35BvfOMbIiLyxBNPyDe+8Q350Y9+JPPz83LTTTfJl770JfnhD38oX/jCF+T1r3+9bN68WX7+539eREQmJibk6quvlhtvvFH+7u/+Tr7+9a/Lr/7qr8pZZ51VZJ15eHh4eHh49IaPfvSj8vKXv1zGx8dlfHxcdu3aJf/7f//v4vM0TeXmm2+WHTt2yNDQkJx//vny7W9/2+ijF33AgwcPypVXXikTExMyMTEhV155pUxPTw/iKzpxRD1EX/va1+Q1r3lN8f8q0PnNb36zfPSjH5XHHntMPv3pT8v09LRs375dXvOa18if/dmfydjYWHHMBz/4QSmVSnL55ZfL0tKSvPa1r5U777yzbw0iwlbhngHTts+z7VjpwO9QyVcprR5KwRtZZoh6nEuyCOX9Lf3dF9p6zdOMTZGyYkxJp81r6Hs4vEWlqv6+KGtWfCsGgKZYAYZNBIYyRpFe7Hx4zTGx7kCqrbSI5Y0hHqLKba9++cO6UD4jzeNIgd7JoLTCGn5DOpMhobaXRWeIGWSJ4S2ye3QMFinPQuW+dEYbXiF6kDG/JSqTlSWDnG3QXSjjMZxXvm+09fzHLLMWXFhVTCyciyOLZ9nULDo0RXfYsVpxxT6PPfHEE+W//tf/Kj/2Yz8mIiJ33XWX/Mf/+B/l61//upxxxhly++23ywc+8AG588475bTTTpNbbrlFLrjgAnn88ceLd3Mv+oBXXHGF7NmzR+6//34REXn7298uV155pdx3332r+LKrQ5Cm3qE2OzsrExMT8rVvb5PRMdOA0JSZnYbidhpErZTt7GGtG4Vb9WxUh+Fjo9dERL4y9xIREdnX0FYE44NoBDVjxhnpdjvfTv68HYcdn4tgshKRFoq+thvZd6BRlc7qc4cNGIVIn6dxpDzTESrSlud1uzat+64e0AfWnlvQffzouWyci4v6QBozfWSBpI7jHmjd23MfHh6rxYWVK4p2V5oMMUThJmTZIhNz6dQtRXv2JP2M1jdn/zKurz3MOEC9ndQ429Y1Yc0uOxKU7PFEtm2kzEqoWVbC9lq5M1usBMrslLEDRZv0WQUG0VCkAxhVHUgWyyZ9Vg46qbTGfEv+vz/z1zIzMyPj4+Mdn68F1HvppI//fyQcrnU/wIFksS4/evvvyVNPPWWMtZ/koo0bN8r73/9+eetb3yo7duyQ66+/Xn7rt35LRDJv0LZt2+R973ufXHPNNTIzMyNbtmyRz3zmM0Vi1DPPPCM7d+6U//W//pdcdNFF8p3vfEde9rKXyaOPPirnnHOOiIg8+uijsmvXLvnXf/1XOf3001f8fVeDoyqG6EhArR5cOkSudHxCHesqDMjCrJFhVGlD5MyRzN341eSUYtvTixNFu23xBImYafepZZJ1BQ9yImGYTqmaTSrtOlawjgKQLPBohCHV89VlL3IsxkKTK0aLwWN4kBydW47jyyd1HefhsQpcEOmMWd6DK/YEEQ0dVxifuLloN8eggM9irN2mrB4egcI4MgKmeQ54jeEtYjV7FVQdWoK1RUwPUckIvMbuKg4Jz+10U3/ZGlLp64izZOKJmiMNIyjR5xuK9PVV8ibN+Ah4ilaJnTt3Gv//nve8R26++eZDHhPHsfz5n/+5LCwsyK5du+SJJ56QvXv3Gtp/1WpVXv3qV8sjjzwi11xzTU/6gF/60pdkYmKiMIZERM4991yZmJiQRx55xBtEHh4eHh4eHhasAY9j8xC58Nhjj8muXbukXq/L6OiofO5zn5OXvexl8sgjj4hIpvVHbNu2TZ588kkRkZ70Affu3VsILBNbt249pIbg4YY3iHoEeeaWw7VhUGlpZzwRHa/kqJMUMT+uPvJVzI+PPFtse76u09Dr7e4/ZTlfAZWxEqqDaosYQ4QVGemxRl3l7KJjcuxleGCQgh8twQujaplRGI5icA5RtzQETZA/zGm9gR1c8UYOqdwu3iKfceaxEhiq1Aq474JVxDdaMaI9Iq1x/ZKLof5Ox6eKHWJmp/mcgSZjLJBl2jOEFo3MVN1MGIRoJIXmnmI8tyk8L9SSY2wls1pV7BDnqAP14aI9NTJXtDlHViKLhwgXoW1UDGCGcba9mfROya8WayXMqIKke8Hpp58u3/jGN2R6elr+x//4H/LmN79ZHn744eLz5Tp/3bT/bPvY9u+ln8MJbxABYZD9LU+9FzEpsyY4Ilc8kevYbmjBMuCDr4yjLaW5jmNERGbqelIcKmt+vAKXsUpNJb2mlF5FzEmF7fklPXMWcxe5rCrc2QjkDBBPlMI4UnOJkYpvTMjYjtT8pIZASJVePHP46tCt+YvLw0NkdUWFLcemkzqu0CjAWsP8gRAU9a4HE2TOY8Nc1FBGw0KPuaY2huVR9yy0UF98+B0JH4bOGuIeVYA1F3AMA9i/pI2jiapWsK7HTM3PqTusxFgUu5LqObSZ990anD008KBqkayIugqq/smf/En56le/Kn/0R39UxA3t3bu3kL8RybT/lNeoF33Aqakpee655zrO+/zzz3d4nwYJHzDh4eHh4eHh4USaptJoNOSUU06RqakpefDBB4vPms2mPPzww4WxQ31ABaUPqPbZtWuXzMzMyFe+8pViny9/+csyMzOzKlHl1cJ7iLrARo/1knqZWFLwW314ipZDZbAx0PrlE08X7ZmGXgJOw1tUG6YOdr4NXiOm5rpWYVSMTSt5kVl8lbjp8KTw0tlUbkFPMePFVM0F1VaCuNxo5rUKh/R3NTLOjHE4rrtamfaQkebpM49VwbjH7M9LPwKMvKeTIVDuNaq8o296CfJ2SSdtSls7UgzpjITjZqFXNScEnc+1iEjqKA5t1CpTA7HQaCJmoDSPY9q92seVrs8QBM5vrFvWzieqikOYsUZZkXzMwVoE9fSMQLpHwnc7vnf89m//tlxyySWyc+dOmZubk3vvvVe+8IUvyP333y9BEMj1118vt956q5x66qly6qmnyq233irDw8NyxRVZliT1ATdt2iQbN26Um266ydAHfOlLXyoXX3yxvO1tb5OPfexjIpKl3V966aVHLKBaxBtEBlq5UjWNIBvdxTTMXrSF+qHMDK7c0jfjiraVZ4r2Kzc/WbQfelrfUDTelCFEVzRT9Hlu0riVMjSY+snCwlxKG9J6yTC/mArWbKOMRzV7CQRbN+ltL2Dym8ds74J6qRh8nauopi/v4dEbuhnMTK/vCRaaLEBArCEPhCKulLpgvFBrNC/QjMVGe8gRN2QoWPMhDTq3cdceSl8ow4XGBeOQ2lxoIUvOMJSSQ8uiMI1/qQk1/3LnnNxCKuxYRccmsj9V6LU1wBiiQVNmzz33nFx55ZXy7LPPysTEhLz85S+X+++/Xy644AIREfnN3/xNWVpakne84x1y8OBBOeecc+SBBx7oWx/ws5/9rFx33XVFNtpll10mH/7wh1fxRVcPbxB5eHh4eHh4iIjIJz/5yUN+HgSB3HzzzYdM2a/VanLHHXfIHXfc4dxn48aNcvfdd690mIcF3iDqEXEP4VaxI/vMtj1x9MfsM8sixuiLnp7RSK9oNgwtWvcZLmVRlNQY4uesB9QqwaWcdNJnMVZyhqsf2RtpBSu/OlzayjHDgq8I+kzg3OFKrj2E1W+uKRK0EUx5YA1C4pgNxKwZ6MV4+sxjoLB4LYMpLbrYnNAPkqtgq0Fn5Y9/Y5PD61mye4tM9enOfo06hqDMnEWjLYgg4hhDEHahju9ISizufObp6W6iD3qAqGy9cTibLxsItI7a9NRbvEmdkQiHD0cgqPp4hTeIgEhSiSQ1qs/bDKHvNXUU/Bze5D9efbZjXxeM9HrGGxlFXyEfn+/jIm7GIp1B8ZKx/UW7AeNHpdsnqCbfhgFAEUem5jPjQmVzJCVmi5Cn5/BhBJX5vfJ/8GWYncaSAkamTBmT22g2boQ+SBBrUbqwhGy9F7RyrTWeqFuMkZjGUbqaLCEPD6CnuCHeb/mCo71B3/lGLB4WEKlDvqKI4atRINJBffFtiqEqUUV+XAK13m454qQMAyrp2Ma5pDaMNDiARk6iCkEbMVL2a0o1a1J6C81K/rm+HostPQk1LBlp7dYArQxf7X5g8DO7h4eHh4eHx3EP7yECZtOKJGloFeIiXlR+vmi3SvZLaAukbqb2fSP4VVzUnMqQ4OcuDaQdtWk9Pmhr7G9l2j21yO7vreN2qIEyI03XrVQJNZxSBB4aWSc5+5S27avZ5qRut7X2pFH7LFnIjo02wM3d0JGjQVMfGECrKG1i1alW3n2u0qlPVJRkgDfP02gey3Fh+U36f1bhYQwnMmG9GBmXKZMQIHbaBg1teIhUcheevwDFnKOy3Q+dWoKVDcFAB33WD+i5occmMbSMWGw1Hxu8uUlsT4wIDZ01fN+8v8manmD2Lej5IwQtF+djaseDS7JIU1lVDWtfrbR3eIMIqEgsFUmN9EwbfxwbBpPdcKDzbaXp9qTPyjlZxnMkSAGhkvZwiNpGeNmrCUEZRsvBmmo1xioJJ6CgY2zM+kgwmTL0gdc0za8NabTWRCelJiISLdlfHmo+a4yD8lvSb4OgrdNSSuM6+0EWkJqfT2qpK2OEp4batSHYmH9JTsg+xmj9w6omvQxH9Lej0USDfSK7l9tDoI+H8cKmOjWr2SOeL1FUWQULFuhoMPuMNJiRHV9scwgpsu6gg3oObYVe0aaIIxh1I24oyQ3DBDE/RsZqW+/b5pwFg1K9BSlXQnBRWSxMk+7ZxWsGH0M0MHjKzMPDw8PDw+O4h/cQWUCdIRuFVUFoczPl6sGuX2Trgx4WxueRPmtaBHt60UAyxg+aTm0fBmVGzxIDsBcQ2cyg6qFSJ91Gl+yiod6mwXJGqreEpQAQ6B20GCTKOmm4pvlijgvDxS36egQYfzQ/obejMniaB6gGLe3lS+kKZ7SnIUnEffI+GHTdj1aTx8Dg9AoNIEg+NTyMfR6M+1CJMCYVPWZ6SVvIMoi7UGYMto2q+hlgppfTY5M/uxRwNUv/YPisixjaPUq2PtrQSOO+xjiUBwu/oeHtAlXfbuj5bZECkXnftXJnmSMRkUVSZvmz3Zce22rhg6oPienpafnKV74i+/btk2SZt//Xfu3X+urLG0QW0EhQj0UvNctcKOguGkzkxA0xxi4ZZ3xHB3aaiYZSI2Hh2KzvEo0qTCSJ43sZytb5uA2xMkxcVUwqhgsdk5RyY7uK+DFsy/iKLFCZhwuxHhof/KXN+tYOYh0PMNTU4wtm57PDYBCZdBjTiO1xCcoQctECnj5bR+jT8FnL+LAH4z8r2k5hRgdNFpT1M9way278pU1Qa4boImmy1pg9fV5R1YGjgDPnkjIoM1v4AGkvLoxo+LjiglTWl0uFuoVsMkPhGn0XKvp4k3E+SuqYB7DQasOgXMzHl1qMpOXbFWzp/ocLQerUv+z5+GMV9913n/zKr/yKLCwsyNjYWEfx2H4NIr+U9fDw8PDwWK9I1+DvGMWNN94ob33rW2Vubk6mp6fl4MGDxd+BAwe6d7AM3kMEPBuPy3AcyVigNX1qYeY9oFfI5kFaDpdIY9EHKbOEVBtroHV6JZI+b26DYssDAV212Og5KsGv30bwtnIlh46gan4X052uzxMqLSNmnvWgIwJnl6gkOEPcEZerOY6VAg6MmuP6u+SeIZ4tQUYaV+ZGQCmXwkknZeaqVeW9RUcXlEbQWlOgvWkP4f4d0x7O1nh2T7ZG9eeNjfowg0Wn92YMXtD834iZZSV6buxJBlHYuT0yKC57/UN6kaoWWipxeIioZUQaLIRmUlDpnBANT08Tx4G3Z3iDotKaJVKC0GQrIUSile0bxz38hh6HHU8//bRcd911Mjw83H3nHuANIuCE0oyMlszJby5/47YQi8MomlDsk4cNfAhnQfBXmALqSMG3pbtz32qoR9WKDx2kkBip+/Z2NdQTF0Ual/K83iZunTL49rJjIqGLWYm6MQPEAF3s89iH9lMxq+ttjJkwDKwJTopQvA2yOmjVf9unP98wWbSTg9P61CHHYYktcr40O+ONPA4PbDFChuHpqFPXzUDpq+jqauA6D9Tf42rWbkziMExIbSwakiHEteFZi/KCz8wgs8XziJjxOoSN7Y6wUODCzaDOLfMY1xeu2BxDnRrUV9xUz7N9cUXxSQrSGsWm82aCOYrna8NIU4u4xCE8eVjgY4icuOiii+RrX/uavPjFL16T/rxB5OHh4eHhsV7h0+4NfP7zny/aP/dzPyf/+T//Z/mXf/kXOeuss6QMr75IVjC2H3iDCGgtE2UUAT3G0tGAixpjPR21Ty3QGU7NEKsOoz4Zy3XAhVuU7rBnWzRSfSMMh7qu2T9N/1jRnqpldFAbGhpVBEyXQjsByFWdotXmRLtjGHQtVU03xqDEGi2U0ihWV1i5GHWS7GJvROGwY/kP7muXFJH6BlzrfDkdLWnOofSMLnsSjmg3bEL9orblXojsK0YjSBuD9fTZ4MHrbAgluqC8SPAs8bgHWvfa+7N4Ah9o3nPoc8jyewWoQXA0d73QoVPfRsEvPARN3OuTeu6Jytn+oSPYmfOK4Qw1ssg6A5FTepMc1DmhMlk5T7gy1UKMzzhn7vkipeY0AHjRsL8K0g4sXiORZQHU6eGhUT16xxve8IaObb/3e7/XsS0IAon7FND0BlEXqNR30ky90GSMM1JpU5zuaoH2cy+mSBMx+qAwWT6JGTSaNoIYK0QK6/wNjxftR2czt+IQ0u5Dg3azu9BpEClKjCn6BPd1Za3pS4MYB85nmGuak5ioG5jE8gnNKNFk1EbDmHB529hnaWN2dNjSOwwv6RijkHEcS9rQYy2zoJxdB2aqOakPviiP5dSPdYS+DU8bremg1y6q/YreTmPG0sdFQ1fq/8G+AZTuU9fkXe40lFC60Hgu4hoMChhBqRHPl92rjO2JaBBZDB8RU6BVPRop5znSykaRavu9rgybyMhUw/kYy0RqHPSfZSqRgDUUudAyFkyd15rfNYHBk1piHdPeIyVWD+8hMrA8tX4t4c1cDw8PDw+P9QqfZebEpz/9aWk0Gh3bm82mfPrTn+67P+8h6oLFNHPrjoV16+cuyswQZsz3oceElBopLoL7LORuDpdOkSv7rIaIy5ePPi0iIs+1tBekHNhXpdzeQEC5Cu5m0DVFzGaamkrjirKCAOs0Ly/Q4soLGR6Gw4wia1zs1XPXNVd9DqaN+9iy0lLUBWhu0TRZBdtDeojm5nXbtqqnr5/eAJuulEdPKDSBRJzXzuYB4nFOmswR7G4NpnYFxq8w8Nq4f3CDu/SwklLhmtEf04ExCi8vPC/lmvYWqWQHJj0YWWEWT5CIPfDamNPgFQoiPrfwGlv010iZiUPo0aVDVJzelnAhpuCrLZCafdv0hvre12OguOqqq+Tiiy+WrVu3Gtvn5ubkqquu8sKMq0EsocQSyhw4li3RfPGZgpEp4RBV7AcuOo6ZbcVkY7zpdZPGUz01A8sUNpdm88/ZLyUEEPODVHVT6LHzluEEOlFhDBHpPcv1Q1ZYCwJqxmTDDHcWNMrF5UJOsGCtHDUnzWu21LktQR2n9ri+D8pbdZxROKQHnh6Yzv510R0OtWu+8NSLOrUoYIuYon7HE4yssbXO0FsLI2gt4Kq8CSotGdX3m1JrJyUc1bH4WkRsIqUx8LVU6juzR7sZPtk+acc+JPMM8drETg9bv25oN4KIyIgh6pTd5k9kUFw8d5fQxMRQuLZTZqptnONww2eZOZGmqVXgd8+ePTIxMdF3f94g8vDw8PDwWKfwStWdeMUrXiFBEEgQBPLa175WSlhAxHEsTzzxhFx88cV997sig+jOO++Uyy+/fM3EkNYLorx+/BgoLOUZMgKLQSfV6GFBJhq9Ks18HaXoNxE31ZZ00R6iF8qlU+SiwRROruhMqjmI98zE+vek12c4grs979tVR22hrb0qbY7VknXSwvqSbnCjzACzQSDIVrAm0CTh5TLkU+wLRinVs/9hhXAGZFKQUjaPFM1oGHXS8iVvsLBUbEvBaZslPziQzhU0a1w5PU7HE3rwzHQLlDZKZvSSWbZOEIzq+62xGR7J/JIYjzinicj+9mOAsvK2dMsg62W74S13eCKMPowA6lzTh3XeHBS4kYPKxyjqzHYLIodXyOLpycaU/Rs7tIXMoOrA/NfjiEBlmn3jG9+Qiy66SEZHtXhppVKRF73oRfILv/ALffe7IoPoXe96l1x33XXyi7/4i3L11VfLeeedt5Ju1h0iSfM/FnfNMyECcz8FVz2xGNtH8nT7eqxpqBEYXaS4SJMRtgKxLtBYYVsZYb0UheUEauvDRQ/SCDJjEezxAHYwRsCejq+MpgRKtSFUaZkIGGp7Tipz2CW/7Jwok7I9UybmNeOQtmdUWrikY7WCvS/ozxl7RCMHYnuFIjIz1Y7FZV2PUFQZaUUWR+1HpoAxRM609pVijQUbjfGBlm3DYFdTyNKUvh7tcXvxvwBxeYZBlK8WmI1qjMNhEBGKbnOp3hOMTzIEFlOVKWqn1FzGWNrl2XCxkOZOaMcqLsgxx9r6G+Tj6bPMOvCe97xHRERe9KIXyS/90i9JrVbrckRvWBE5vmfPHrn77rvl4MGD8prXvEZ+/Md/XN73vvfJ3r1712RQHh4eHh4eHh6Hwpvf/Gap1Wryta99TT7zmc/I3XffLbt3715xfyvyEEVRJJdddplcdtllsm/fPrn77rvlzjvvlN/93d+Viy++WK6++mp5/etfL2F4GIMRDwPCIO1cEeX/20uF+zICm8vwLizkHqDJSNMqi0x3MvpAtXiDEjv0tUz62Jff0eUtIugRU16kBr5fG31Q9LEb0m5RjrKMNeFvE6jgUmTgVJDxgsQ90gusDK7d31iJJpbPRSQ0+mAEZ9TRRwS6w9CZmZ6RQ4EBvSnORy/H8RpgvdLv3UvZDec+hyuYmvpWzELcurloN06aLNopxqfuceoQtfXtJtEmuEMB1hAbqdj3sYHJGiVHGQ+FsAcvjqFTlrdtZUBE3GVDusLhEUlt2WmiH93AFSjtyE4bFAJZZQzRmo1k/eHpp5+WN73pTfJP//RPMjk5KSIi09PTct5558mf/umfys6dO/vqb9VB1Vu3bpWf/umflscff1y++93vymOPPSZvectbZHJyUj71qU/J+eefv9pTDAwVSaQipvHjFBfsAhoRlZyCWwA11nTRVqDrbLFAdUEGGSk6pvnDODJosPwAnuMbcycV7fGynmUXQe/trHVWDV6KtUG3gPpg00i7X0JhpaWWbse2iYcPvMMNT+On2AMxRkkZ8Vw1xgXpPgybSg2JkzQuL2tEcTJlVkOaU19JFY/SxrGiGc3p7RR6ZJ204o2Al6ORR+PjiY5+oxC/fTgEGfWNk0WzNaXlMFojoAtxa6n1BqeGsIHFUEPvPL5hoWhTiVoZIqXAbnCQnqIR1K0mmQsuQ8l2V3OcbUdtsa5w7erIPtPnwMcO46now8cQrQtcddVV0mq15Dvf+Y6cfvrpIiLy+OOPy1vf+la5+uqr5YEHHuirvxUvgZ577jn5gz/4AznjjDPk/PPPl9nZWfmbv/kbeeKJJ+SZZ56RN77xjfLmN795pd17eHh4eHh4qLT71fwdo/iHf/gH+ehHP1oYQyIip59+utxxxx3yD//wD333tyIP0etf/3r527/9WznttNPkbW97m/zar/2abNyodVqGhobkxhtvlA9+8IMr6f6IIQyyv9gW2NeDyzJy7FSzeHoWBBo31rWS6a4eCTIOiJXsGYxdwTkSh50bWVaEr5rQpT3+1/6XF+35lr2cyNY8Knm8pOm/Ay2dneZaUVLzRK1427GDXnO4qA1KSX0Ar1BAbxGCrWNXnaO0cxu9VyFYzcTZh9qOa17j6h702Zj2DBj6Lcpb5MhCSxNNdxz1nhIHbJXqnfsyUJr3hEWd1BVI3RdNtprg6fw3DSq4mUpIUpjQz059s96nPaTH0RqC99dS3J2ZZSEq2NPDMj6kvb+2QOleAqmbeF7Tgu7CcXgwkh68Seo8rR7qghn1y5hRpmqqGZlsOM5Bg7loOiswbarsVl+6Y33gpJNOklar1bG93W7LCSec0Hd/KzKItm7dKg8//LDs2rXLuc/27dvliSeeWEn3RwxJ2qn43I9rmLDNoZwwaJy4DCnz2LweWsA+6H7ur9aaAg2pk4c1NfbY9I6i/bV9mlY7YSyLgzl1dF+xbaykJ1tm0hk0GYUZ8wnQmHhpC9DF7pgri9RaI0PMXlwStqcZI5QfymFQ3BFfxTC2jHGorDujE91MQd2FLZx8+6aiGeWp+cnMLPrAcSjumTbt8R/9GBQu0cfC0Ohhtj+sBWnV+IzCp70ctsK31JqLPuKFnf92jCUTUGaNbbrNWCGoVwiUMYo2Y+FIFZeRWVaBccQizja4FjKEIbyYt62Cq9IfxcV5kZQZpTrMtHvLvNEDTeaMw7F9YHwX7Jr354w38hgobr/9drn22mvlIx/5iJx99tkSBIF87Wtfk9/4jd+QP/iDP+i7vxUZRJ/85Cfl7/7u7+S3f/u3Zd++fR3F1v77f//vEgSBnHzyySvp3sPDw8PDw0PEe4gOgbe85S2yuLgo55xzTiHO2G63pVQqyVvf+lZ561vfWux74EBnLOxyrMgg+r3f+z1573vfKz/5kz8p27dvt0pnH42IJSj+FFyrJYVevDtqH+7LavfGGBwuEeVRmoZ4oiEQGWjPQQs/azf9otARWMlg8jZWansXxjr23T6ks6cqcLFQ54T1zhQtFWJFXKnq49qoZp3E9vEneY0iI1HNUGbEzqDgjGDrfEj0BIV4IugVQgy52C4ZEyoTVCcPW/B2sTQA9Y5yzZmANdK4yMASlbQQhQYLasjh7eglMFvTSC6BOn3uvqvIdzu3hdrimMOyfaoyaLIunh6DJuvFK9QPVeaaA5v5cz6mheOSDZpGNUrF4N5kfT1bvT56hWTErh9Gmjq0UGKuua2C45rIGjWCqotQAvtcSaFYenpsXiZXrTOCWkaGNzz/vkZ5Dcwfhvenm5dxncbaeKVqNz70oQ+taX8rMog++tGPyp133ilXXnnlmg5mvaAXI2cl+5ZxZ45BLbBFRWdM1NyuzvOishb9Y02yZuowgvp4GF4x/GTR/t68LpY3VNbG2+xS9vLe53jKhktNtPVxjRjjyycvV0ZJGCKNv402lWRtLmsoWZs2i94XygdamJEp9TR8UnvbliXHOmth25GhwtgHZBmmVbsEgw1hxbFvql4Mace2Q8FQb+5mUPCFgu9iM45cFB6NpwsrV6DvzrdVLzSZC4XYpVEfzl7jb8UxQr0sBCv5OfH9mpv1ooZGUOIYHrcryiypIot1RD9zLKLMNo0VlV1mM5JE+swgY9yQg7cyixofum+XqGKrhfqLmDfUT2AoYPPcJXuHqRET2EfWqyXu0OPIYa0Tt1ZEnjebzWNGndrDw8PDw2PdIl2Dv2MYP/jBD+R3fud35Jd/+Zdl374stvX++++Xb3/72333tSIP0X/6T/9J7rnnHvnd3/3dlRx+zIILTZvnyNQmgi6IoSF06D4o3GhUrQePUxPtmTF0i7qAfb9k5PmivX9Jr2jV6mx6UQeDckW5sbZYtLnqNII6cydHHUHX1PlpWyiCDhRB1Y6VIffFRU14x6tMGeoUod12eHfM1LegY5M4xp86PDDRWBYhG55yoj7siT36ONJnrCFjLKejfDi4Hm19nFHTC54ZohcRQz0mBDyXdFt5nIKS/b67qPYrKzqfAeM6omK7zctUWoOA6VWEBKhg6nRER0ZTY4iUGb2MDJqmZJm6f9MxCLjiNx+q6Gd/vKqTHWqWoOqVJozwnLZ6iyLLs880OL+VcxqMWWYsn8HbuwRvV2IJeDY8PhHpZkd2KLHeDQYfQ+TEww8/LJdccon89E//tHzxi1+U3//935etW7fKN7/5TfmTP/kT+Yu/+Iu++luRQVSv1+XjH/+4PPTQQ/Lyl79cymVz8vvABz6wkm7XJWwK1f3QZCJ2N1yTytJ9iD+WHTE/Ruo+ulPp+iIidYtP3hVj9FOj/1a0G7AivvD0j2XbIAA3K3qyd6XaByt0yRN0ixdtFnxlWBZZQ754ST/kRlXgGg9pMmT6BDbjiKwAzsdsFFJpRs20/IVbRiBSxEwlbHcWi7VwDaTPVmyIOIw4kz7jPXnoWKa1RsDYItKFa1FnbIWGkK0mWWsDFhBlGEEYPgUYGddGJeq4lscj1qA8PaSfcT5/o6CvuehSz1/iiP+xqUkfDijquZeMtK77OBYvaVe5DPZhn9cD23HrNN7oeMP/8//8P3LLLbfIDTfcIGNjOr71Na95jfzRH/1R3/2tyCD65je/Kf/u3/07ERH51re+ZXx2rARYe3h4eHh4HGn4oGo3HnvsMbnnnns6tm/ZskX279/fd38rMoj+/u//fiWHrXsszzAT0Ssks5wHsilwt1WwUiazoba6PEH00nRbkUWg2sZC7RJfSKrWfRj02AosP3cPgbc/M/7dov3duSzY+l9npvS54S2io2K0duiaSWYmin21Gjjaoap2z/GjgjzF6owFHnVJWvlKuWX5sUQksGtTGohyTwTLfFBvMmqCCgQ9Up1FYGiuBBotoACbkVnWg75OsRDBNao5vgBpRgQdF54jend68bT0IKzXF1bq3VknXqFgGKU58t+xNa5dPmYgNbPMcBgdX/QcTWSeoeGKXVdo09CCdTuh5pgZlNlptvVJJmpLHfsubysYzyQeNJtHygU++y4BxsRBfaW2e4/JhJgHpOnIwAyWN5bvYGkP0shYrdr0MezNmpyclGeffVZOOeUUY/vXv/71wQkzHqtI0kCSNLCmo8YGxaURGUYQn9TO/uMeJgmX67rg7DGO7zW1UTJVmrb2x4nJKtiIl5+rvhpxzsYfiojId/5NCzdKQx+3mOpJlhNauWSnz4pxYmKz1jqTZQyR2sbsEmNGDqzbAxg/0UKeuk+16waPw/kczIxq0gA2CsFWuk9GKo4kHtEGTIkv1SVt+HZNn496ME6MrGTGXqwwrWulhshaU1wrxVp4tXntUNy3cVKm4E/laT5mzGo0DB8KL1a4KMj+rVbsxVqZ2dktc2wI++6d1nXUKiVIZ4T2+031ZxgtPVD/XDApiRFefte8aMTGGRZPMROgExxo1GHGdSxzQZJ/Fy6WGECYWCaegRpEqzzfMewhuuKKK+S3fuu35M///M8lCAJJkkT+6Z/+SW666Sb5tV/7tb77O7rK0Xt4eHh4eHh4iMjv//7vy0knnSQnnHCCzM/Py8te9jJ51ateJeedd578zu/8Tt/9eQ+RBYZ4mGXVw8/pGTD1hDrN8parDoUD3UQhif2xDijbEukSEFy12WqZtSC8lnD8sJVJwZ0xlGU/TW2fLrbt/f5m3eGCvqWWKKo4qd3wNg8RYdQqcu2U98EAYcNbxHM7BBvV4jdowitkBAvrppmdppsqoYU/bQur/gisYXUGK3bqFuW0SXtM0yrRpg1FO5jVgo2C8h49UWk2cEleWuEUYNQzOHRwt7sPSzC2SGf9nEPBEFscrJfJRZPFG7QIY3s028egySi6iPuGgfuNjbzJdDsazrw61AYzSl+4PDp4zpXYIgVXh6r6Rt0/rz1cJ05O6z4s3htXlpmL+rLva287qbZuwdGh/f4xNIm69UGvED9Wt+wAvS4+hsiNcrksn/3sZ+W//Jf/Iv/8z/8sSZLIK17xCjn11FNX1J83iFaAsqVYq4hIE5N6JYUys+W13k1BWsScENQ55xI9a05GOsV9LITiIGEYYZ0v0EfmTyva/37kh3p8hlGov1eUj/v//ZKHim0fr7yqaP/bt8DbzuvjlgI97uHcOEoctYpsxRtdcIZA0T3edkys+bElfRmlzfAPvKMZI2Sk0udfgRQHjaBSnYYDjiMFl7vsA8QYxRtQMHf/QX1cFyPImZG21nAZH4UMQQ8GE42xbobUkaTUHAigPi3jut3cqG+G5lh2E/FeMowggxrDPqBxk5r+HTeMZvQpn5ENiPnhIqptLHY6rx/33To63/G56zgXWo5izYmDVrPRboRhh7BmoRFzpBqOQdGwYTxR3NmHUa/QZgSJHJksM0+ZGbjhhhsO+fmjjz5atPvNePcGkYeHh4eHh8dRga9//evG/+/evVviOJbTTz9dRES++93vShRFcvbZZ/fdtzeILKBHR9chQ30fw2OSWNtr6RXK2lnfk/AE9aNfJKJd61yl/dSI1hvaH+tVrqvWmkgecIlg7Kt3/lPR/p1v/FLRjhCg3EKRsMUw8xbVRrUrxXCxcwXo+o5qf37s2pXeIqwCWxN5CYOW/i4lONpa0H+hRydgMpjqjotjXDoK7wWgggIj6DvflxlHIxDdnNKUZPg0BD2XOr2Ch9Ur1A9cHiQGhZdWqCF0BKU9ApZOgTcuGdJ0Z2tMfy/lpGFwfVs7/wyvkKFJBNqnNNaZrTlS0Tchy+UQbUcl+m5en16q3as2z2HUMusj87AXHaLAkTBRyIDZCr6JmJ4c16Ohuma/JAHosU7MfweCVVJmx5qHiFnuH/jAB2RsbEzuuusu2bAhCzM4ePCgXHXVVfKqV73K1YUT3iCygOKH/biMXenz3WKBuhlBIjr+iNsMMUagniIWxfbkYhIbDvXE+mRTv3hryEBpWbLPIofB9NKzf1i0v/+wToWs7kc2Wy4Q2USmRxnFXWkEGfEFtknWlhK7DIFrrsxjCurb9HUszaGYJS8v2gb9kbejulhhZKo52kWmEWnKKq7XJv0GrcSb9PgOzulOWtnvkSyA/+sBpNiKsR1OowpGkEHvGQNQHMbKDR/V92q+i4oRMowgSBmkk3oBsXiSjuGj/mmhLM3iv7h/SNG2NuibLMWzMTykDR4VOzQJFWrGEPVjBPUTo7i8D1sR6sRFdTvm0DgOO/d1rGpMGh1758PgYsMwjkiTUcA6ppGjaDCesNMIOmLwlJkTf/iHfygPPPBAYQyJiGzYsEFuueUWufDCC+XGG2/sqz9vEAFhkDonCdNrZK+8vLyv5fu7FK7jgH3b91HbOek8j0Bqpvwznoj9WVW38bTTOIoMYyzqaFNugEbcm7Z/pWi/5yVaFqDyuJ75Kweza9YI9culMQ4vTdWusSLdJlnD8GFQKrZX8dLJq2LTa8SimSmHkdgnZBVbZMQEYQJN8MLjeRjgGeYDN8o1MFgcX6W1SbutKtQtUn1N6PTpdB6aNA5do4F4lNr6Qgau4rSArQQHx2kz4px99RlTZQRKK+MHAdPJpH7m6ieigj3jv+DpU78jNYZi3BP0EBlxbxVoiaHSuyrHMYxANSNuKLbHDdlS4ktc+DkkQboZValj4edaSHJ/VQaolzh8V7X7YqFiGEm4v9v8/S1GkIiOJ4rtz5zH+sXs7Kw899xzcsYZZxjb9+3bJ3Nzc46j3PBp9x4eHh4eHusV6Rr8HaP4+Z//ebnqqqvkL/7iL2TPnj2yZ88e+Yu/+Au5+uqr5Y1vfGPf/XkPERBJKpGkhielWxFDd1+MLTr0HemqT2Ycl5+eqfs7yzr76LG6Lgw6WUGBVZtKWcCx6faWkraoqXxN2DxEPAc9VW95uY72v/uHryna5Zns38os3PuRPl9rTLfjH0O6Pld+ff0e9viUoKTSzPTHcQnfawn0GTLVIBBeUCEGJYL+IjCLVK1mvFCqJASo4cDQB4hJsh5aOq6ptEBl4ycQwByCW4Jelzl7RlHR72poJhtV1UNqfzfqrh+vUC8w+mPdOGSOpRsyb1A8oa9zc0LzYUZckKE+rbtWqfSkWZvj8NqO4J6GhyhEzMzEkL7hRsuZZ4jemCY4OFJmTKsnrdYPVdYtZCBwxA3FRsFW+7FqO7NN6X2NUKSVHqIWnks1DdH7Y4iyOrYLKElxZMetF/i0ezf+23/7b3LTTTfJr/7qr0orDxsolUpy9dVXy/vf//6++/MGkQU2monbmmJ/gGhcuIycbudzUVwFZcZSHJisJiNNjzAgmurT2nDRExAr3D/T2mDdbqMFm+CIONlWEHF8eu3Zoj11zjNF+/mHM5XrEO9lzHdSmdHt+f0wzMb194rKh76+hrKta1JXLx0obRtK1ov6e3NMjPtQMBR1ONeCEmlM0rDR21UgtysAmy/bJkpAlLB/qZx9h3AaNJlDzycYQVQvCzMrY3EGrma+odoOKtN2DpcBU8H5WujP8tZ09eEy2KxGDoq/BjhfAGrRUPfG9WhuzQ2iYX1/GEYQ1KeNuCEYu+r3byNDP4XytEGToT06Zo8RquUWNg0VV3q9y2iq2LSKjFCb/mgwG4wAa6f6tPoX85/DwHLJbyRKb8xV1d6gybC9Tk0NZZmhC4cemVPCw+OIYHh4WP74j/9Y3v/+98sPfvADSdNUfuzHfkxGRka6H2yBN4g8PDw8PDw8jlqMjIzIy1/+8lX34w0iC2zBx1zxUHTRtY9tpdZP5pmI3VvEsdXgxTnBUcusn3MQLXqALN4ufpcWPGbMcGOw9a+cqIOtb3/ZRSIiEv8AgdbwwPB0lWm9SmxU4SpX1BZZJnqFGCBJBWtbVhq9TUYqmG62sMI3Vowq7ZdCy3iqwpZ9O8fdzq+leZk70/JFRMoL2F6Gh6KSCwBu0gNVRWNFREIGYNeRpk3vSH5xAqhkG3XUXFSbTWCRNJSjRlrK7Sv1PjEImt6nau5ZHIE7b0HTr4oOExGJR7UXsj0KSqyWnccImK6CGuPXZowuKbO86/Yw7kE6vhyJAJWyvh5V1Bar5K5FwyvkyMziHFOLer++9Eh18wq5vK+JKyuM1J3qg88C6Cs+q6223j46ou/laVVYmo+wyytkC6QWu9cn7UXYdVDwWWYDgzeIABVDRPSj9bNSfQ/X+TiWev7Gfbo9WWzbGmlqg8YHs8Jq4GYW85QWnqNpySBbvk9NLJMpM60MGs/+8mMG23X/7v+IiMgHGxcU29rQbhn5kb0QJktsKAMgRNFYV5VrwziyFYlkam5N99ceRfmSOoxZ0GqKnTRiiPBCdIiaGwrbilZxZx/D+BzBmBrIvKmV8m36hMxgam6o4Ti9T9jQv200kxsMDVhxiEMyYpJoHI1r46LQ5mnAAKPBBAOLLxqjaK0t7R5vRxfll45pN3lzKhtTCmMmDbWhZzAs3AdxXCpbLKlwmz6O1Bh/c2YcqhgiGkRSSaxt3rMbh3Qc4GSlU9Oh7SgD1Msco/ZpO7SCwjV+gzL+R3DOZt6mUdWOHTSpo1C0tFUf3NkxEC5kbGokLO3hqqEcLPt3APAxRIODzzLz8PDw8PDwOO7hPUQWlBnkly89DE8RExcchWBdgdLdEBnZIHr7WE6PkRqbhshNhCVS2EU92yXoyPGz0KvhDepCn8VGwDa9VvpWmypl/NhZL95TbPv2U9uL9jz0iYyVPIJRC0+PQZl1DK2jD2OVWGR3UaPHHpxp1JYy+svpLpcniE8YHG2GF0ldUlxaBm4z+awBiits687Lc+28XwQRY/xtBgbX6PkCRZH3HdbJ8+G7lBGgP2RXbE4r2fmDRXget2kar7JXezXTEu6xZ/bpdh78zIKpMoTiqVt1QHR7hOPAsPOLRlqxje9NOpH3EIOmVbtbwLSIqSHVgsOsNZqdJx1C9h8o3AAR+KWK3mfcUKLu1JsiDIrLERBtQwmeG3qLXN6nflABzeeiwVRNsmYL96x0fr4chqq9qgPIaanFuctxDSxzQti0H2fMQZYY7oHAe3kGAm8QAbEEEktgdRl3EzgUEanhrdgtU83VB7dzzlbp9j9obcH59ItrMrQrFDN9XoktLqZ6Jh8OdDzJRmSqsYgsoQwsGj6t1H4bsdhjDcE0Ks7o/zW1u9hWif5d0d7dPLloB3NUPETnigYz4nLss0bI+J640+DhCypC2n0LRlDKtHv8jiqcLHBUxzbsSpdqta0cAL8KBRt5ORirMpSrKjsyyygWmIB2w/tfwjxOIynbX4hxjSre+h6iiKQyRKIGZBTGUcqiPFG0y7P63gtetEP3vZhvx9uztQUiiGVmCGF8GHeq6C5WlufvUu68D0QcBhEMH0NgkYVZaRAhrT6pqrxw6YpKRRsRXGREPWRsKZT6yG51iTGuFDTAXMZYK6FxlBut+JwLkhj0WalsX3EUp4ER5IrFc9Fcqo+E9CWe9yDptJ4GXbrDxxANBp4y8/Dw8PDw8Dju4T1EwEJaliANjSBiXdwVGSCkoRw8TdNia7ootV6gdI1mYh1QuqmiaQaW2rDVGeI5Y8e5z6o9VbQfWTy1aL+AFKvN5SyY1kadZX2DjhH7mJSHhWPeteEHRfuxMU2fpc/q5TmTPZI8AJIB01xFGm51BuRiHKnFJW8EXSP7LMBqNWA5ANulJtXmqGFlnFPt46DdYsPDpdvzO3Tn1YPZScf2oAbdCGirEWZHwdsFmiBs5l4mB53EgON2ldegMxC5jXPPb9f7jj6LfUFhKcpPRCSdyNwwAX63GBmGRoA1g9NJBeYB5/GIfZytYbvniF43VR2jhRhult1oTuBeoeeummD7oZ9zeiddHhZb0kLiKKoaGnUYD73edWa9OobcTQw1cIw5xnPGbLFWK2vHjkBq9sczLyzSZWo5jl/FNWTbM+p4bvmBhak/7PBB1YODN4iARlKSUhLKCOSFtRHR/RGoIyXKJszYixHUTZjxVUM/6DhmORYwO28KdKrxdO7Xr+NzoxAsDJjTq1pU8aG6rhOjDKIZlOweQ2VTTsIJjKPY0q6hLDzpuk1juj3/vDbGGpg4m3ncD9NjjVgnh6p1GCGLLBdkpFFFzc3quI7daMaaK0kR0hHlmW/GBOr6mV23kLIFSK8xdqdkbwuy51ujuSHCWCGkiJMKYh+NCRglS9lJGSdjDB/fqzGB8xjKzJ3Xg+drjsGArZPmoEWhflvXBWN2VyddJ6INKKMmHAy9iNduhEYaxpqHKhmUGYwjwwiqOTiULnFqjBuqlfXzUAntafLKiHEtSEzjCPe6yxq39eG4gbsVbHXRZKTmXMaPrd8Q9LVLmFHvAJoS96MR8BfY5wp9bnt/vIfUPgONIfKU2cDgKTMPDw8PDw+P4x5H1EP0xS9+Ud7//vfL7t275dlnn5XPfe5z8oY3vKH4PE1Tee973ysf//jH5eDBg3LOOefIRz7yEaOybaPRkJtuukn+9E//VJaWluS1r32t/PEf/7GceOKJljMeGhujJRmNTBvRWiHeYXKPGOUuDk2PGcHTaJedrvJDL0lMwUY79zIWNvO+6CGi+8Hu3VlCAO1i0lmtnKtVlw5RbHjPXCIfGS7f+c9F+2MTl+jzYNGsymrEyN7hyrtWQ/kSZLHwlyjXsg6bS3pJ2W5GHZ+LiAxt1kHrS4IaYonyROh+Q+gluZgI4xJEnfu6vEk8D+kb9TMubsb4l3AvwTvSGrJ3vrglO7Y8T0pKt1mqghlWzXF4n/J/rVl0skzYEB4d0nhRXQWu2qkxw/uE1bspjhl0jJOUGvtjRl9s8Qbxlk+q8ETQK2RkJHZqCwXYVqnq+6pW1ffp1KjOwJsoa89u2/FMKfSmPdTpUQp7cHM4vT4qu9Iou6HPUW+jBAqeP9J0RRaZYxxGhXtqJtn2ZwIEnUJ0tPEwUJWFF8mV1GB4i/J/o8G5XTxlNjgcUYNoYWFBfuInfkKuuuoq+YVf+IWOz2+//Xb5wAc+IHfeeaecdtppcsstt8gFF1wgjz/+uIyNZbmt119/vdx3331y7733yqZNm+TGG2+USy+9VHbv3i2RQyG3H3SjuULHnNK0pOOzMKvLaGGSEI0cdSy30ZhhjM44RBDrlgywZg/Gyd6mzgZawFvi6cakiIhsrejJ22UEEQaVll8bKlxzHBtLWvTvlNf8sGh/5wmdiVRcBmShBaOaB2FxTKr+UvhNFZWk4dNa0v21W3p8Vby4Khs1RdisZRN/tA9ZV4gbYW00gu+nKP+5+OJ1UnCODDaV8bS4HftSLZg/M46jQriqtUZ6rXYQqdkwpGg4GErDoJSKczNbkjVfoTfYtliA5QUYHyW74cNYoFJd71/f1EndGVIGdft2Zo7FQzl1R8kFxgSxyd+c++T3YWVI3z80MsZq+lmda+qTL1X1BS6j9piin5hN5lLI76cmWTfDx7V/YsTqYWEXObLCjBqDhyYoDHqNrDZiBWNlpHOceOYcCbCGgSqNUA3Oej57B10+X0t4ymxgOKIG0SWXXCKXXHKJ9bM0TeVDH/qQvPvd75Y3vvGNIiJy1113ybZt2+See+6Ra665RmZmZuSTn/ykfOYzn5HXve51IiJy9913y86dO+Whhx6Siy66aGDfxcPDw8PDw+PoxboNqn7iiSdk7969cuGFFxbbqtWqvPrVr5ZHHnlErrnmGtm9e7e0Wi1jnx07dsiZZ54pjzzyiNMgajQa0kBpgdnZWRHJ6KryspVSLf//OlYgY1ytYFURI/slQsqQWue0jAwQ51e3QgVpT8e6PAF1iFpY9v+ovaFoj8BbpLxIiUHnCdp6UPTSLLb1anUkj0YddQRSE90y0Tj+xOH6eNP2rxbt+jbthv/CwdNFRGTfkg66fvL5jboLXN8SxO/oOWrmp0+QxhWW7fvSZT86pK9pu5J1Mjurx2YUE+dqFW72NmmYPDC4hEL1BpPpqLxtLN7zNj03rKPmDnLG/rmjjHXbUlDIhicIXhUDin0gZQbagnIyZvkM3VaZdCxTwphgXg96rVRgOWF4f2r2tuFFYs0xlcnI25u/RdjpCRKRZd6M7H6it9Ggc5F1NT6in6kRiDEyIFrR6C6PjitbjNvb+fNXwo1Kz2kvekI2z5GznAior0As3mTSbnhWjRqErE+G7UOj2XVq4frGrtp5SJ5IQY0XWx2/odgEIr2H6JjEujWI9u7dKyIi27ZtM7Zv27ZNnnzyyWKfSqUiGzZs6NhHHW/DbbfdJu9973s7trfSIP/TD/ZcfuePIYClDIW9yBD+0g8zmYNiK4XmHHWaCBtdtwXZWBzn/kQbSpEjpie2xNBTYoB03KZIG0SbqvqcQ7lBZIyth1RfWzpwE2/BXowjiju+duN3RESkjjfv31d/vGh//Yc6hmxoRFNpI1XdVpedxo5rQq6UDh33FDVgZC4x2wmTOutdMd1aHYuvbRg2rjgIGxyGjyulmHFISbvzfFRdLmuW1GlQqPPTIOLHTCYjq8LtKnUfyZ5GXFMTNFlL3/ZiuyVpPJkUo/3lR+qr2D9c+RtF3WMlZEzxcY/Qt0F3GSnxULPOjZhuKfXcd/n+yqjqR9V6OWz78zkyhCV5r8M4ihQNynuTNK/jTR5D9qJQ2GaKPunBNn90BvrZY46KPmAEGYVeVXMV90S/8DFEg8O6zzILlun8pGnasW05uu3zrne9S2ZmZoq/p556yrmvh4eHh4fHEUO6Bn8ePWHdeoimpqZEJPMCbd+uI0X37dtXeI2mpqak2WzKwYMHDS/Rvn375LzzznP2Xa1WpVqtOj8nbF6aBkqVG6tfRx/l3DhrGpQaVjE9+F+V94ZenAW4HMYC7W5nsDKDrYfzfeZSvbwvg88YxkqU2WSTyHixlQ7g6tMsPWIPmtZB5vpzaiDRw+XyFqlVLvv92Y3fLdrfeOqEol1f0t+FQaxD5U6tl8SxyuWqc7iivUzzqkQFbpPyrG5XsNJc2obffASrzqL8hz6OXhoG+tJLY82U4uWid8RCr4mIJKgPF+b0npFIiH3zePqOc3MFqjxbXFVTvBSx+gZFaHh38ja9RkZANwOfWWGGRdXVdzC8buSQcGoGQRvXKe3cxiE7vQSdVA/rctEL0sL9toTMLGZ2jiP6vF1cbD4vDk9Klywyl/ijUyDSKCGS/WsEfDPA2vkc6fOrLDLDQxvaZ1F+wwSeHnV9Q6cAJj34eOawXW01nPYO6lF9Ffdvf/Tjtttuk7/8y7+Uf/3Xf5WhoSE577zz5H3ve5+cfvrpxT5rlQF+8OBBue666+Tzn/+8iIhcdtllcscdd8jk5OTAvi+xbg2iU045RaampuTBBx+UV7ziFSIi0mw25eGHH5b3ve99IiJy9tlnS7lclgcffFAuv/xyERF59tln5Vvf+pbcfvvtKz43RRVtStUkT5p4LlwGkVKGbjlmVmaqdYstokp2DcZMHT8laSSDPssNJdJT5nfV7elEk35VI1YpV5c13O32nGgaPA1sV0YMGBEDLD5bwXekcaTotshRyHbLpKb89v5wU9E+UNLfa2pDZrmUwN0stRAL5Fha2TJ8QsQK0aAoaVtSai/AmMULvrkhjzNp8m1hodREpA26yKbdZyhjO14SxlzPVHW1nYfZDAQRZwabTkvGcaSFqFoMOs5Avjspv9Bxs5CaM2uVHfpBMlP37X0URpPrGnBzlxdk6sjGojHQRLFep/BiUYDPsk2WxQcaY2V/6kfClh7ihghlCLE2mSuTzaQISR2GHce5BBi5UDEMF/V5m5+jP57PWAkI9u88n7HNYlgGg+RWBhxD9PDDD8s73/lO+amf+ilpt9vy7ne/Wy688EL5l3/5FxkZyTjqtcoAv+KKK2TPnj1y//33i4jI29/+drnyyivlvvvuW8UXXjmOqEE0Pz8v3//+94v/f+KJJ+Qb3/iGbNy4UU466SS5/vrr5dZbb5VTTz1VTj31VLn11ltleHhYrrjiChERmZiYkKuvvlpuvPFG2bRpk2zcuFFuuukmOeuss4qsMw8PDw8Pj6MVaxVDpJKHFFxMiTJOFD71qU/J1q1bZffu3fKzP/uza5YB/p3vfEfuv/9+efTRR+Wcc84REZFPfOITsmvXLnn88ccNj9SgcEQNoq997Wvymte8pvj/G264QURE3vzmN8udd94pv/mbvylLS0vyjne8o3DLPfDAA4UFKiLywQ9+UEqlklx++eWFW+7OO+9ckQZRKw2llYaG10RlnXFBUDeCH/V2V3mPMF+O0MtEoUUjsy2w920rIcJxziX2AOWWJauj7CqaBdDLdNqQDlD/fn1bPv5D02EiJl1nBHfnyyt6rxqiz+fSRrJ5vqohvV36uMWm3jeA56W5qN03ByuZt2h8SFMSkzXt0qG4HFe2bG8YygQbD4xpyjZE5W00DY/O6JMI3D8t+4CepaABWsAhj2LzZpCqMrw0llV1B1Q5FHpXbBk2IuaynxSbzVMS2/swHIsWqo90HoO/mbXmksAqroNBgzjO3Q/90Wd2kfJWhI7AYnpHKiX9xQ40dLT46LCmaEth57Nhziukquw6Pso9kqT07jDpAZ4qB5WmgpkND7RRyR7jMwLHMaT80MDhIUodVJvhwOxa0sPRjiz3uOu3NQad/3sUUmY7d+40/v8973mP3HzzzV2Pm5mZERGRjRuzLN61ygD/0pe+JBMTE4UxJCJy7rnnysTEhDzyyCPHn0F0/vnnG4U3lyMIArn55psP+aPVajW544475I477lj1eBbz4q4tGBdjYfayrDle+t2Ey4xtjvPWuxRjdcHIRHESdhrKKHEZHLYsNBHTsFGZXg0YJy3cRnTZ04AxMmjy2Y3xBy6jypzs9YQ7m78hSedtKOuglLOndKD81zF5zUxrykwZQuNVbRC5BO+IEl5ozTxl/yUve7rYdnBJn+PAfuSwz0NEEpVqi1OyKCja0Yy2OAyKiO87FdMxy3gdvIhqjnuJLFg+PMNwwLVzGTBWGEYcxmGMv0uMC6hCM07JEd/BDLHcqDMEE+2HmbB8YLvOIsvE/fCFA0t9PSNVHCKfQ6hfNlLWhk8TxsW8I55IoRdhVIP+zceU0Bhj3TOL0SViPtvqeXbNf4Hj9zcUDIrniGKp3edWIxYov4dS3pvOMdljxQ7xClo+PH1gn4bxqrBGlNlTTz0l4+PjxeZe4mjTNJUbbrhBfuZnfkbOPPNMEVm7DPC9e/fK1q1bO865devWQ2aJH06s2xgiDw8PDw+P4x1rRZmNj48bBlEv+PVf/3X55je/Kf/4j//Y2e8aZIDb9u+ln8MFbxABrTSSVhrJfogfqtIXylMkYq9kL2IG9dKifyoe6dh3U7TUse1QUF4Tl/4PXdf06JAeUx4g1imrwxvGkh90ob/Q1hTlTJ7ONIxy4a4VKq9HDYHLanyLWPk2MI6yI9OkhFWsavPcM6gbccrQ/qK9badOzfrH6ouL9mIzO38l0lTFJLxF1Ghyic6NV7JrNt3Q6U6jVX0dK1v1mBcm9PedexoRxfmzH0K1kEGbrZP1mFII0EmjkxJpbaIrBYGtFegrOSgstbAmxUhXkCnu6HC3qDapwgUEvHJMpPfo9cm9BEZ5k0V9XAnt9ij6sFAigaPmFL0CRkC0LYCW/2P058hgQn+qmv0Q9K9qoMa2DGmv5nBJ77OxrGvnEb3oDym4ArPVD0kPLemukqVUiAg0f8ThAXcEZruutfYAWQK+RQwhRR7HYPHCo8SXLG8l3utscif11V1OVIO6S/LxdPfIH+249tpr5fOf/7x88YtfNDLD1ioDfGpqSp577rmO8z7//PMd3qdBwRtEFpj0TfaA1pHiHqf6863RIvbVD850ot2RKo5nJNATXi+wxSSRZahjgmo5ivawblnFQpUlDpqME+++ll5VzFNiOYdhHGFi5fZ9kEReyPOmn5jTytL75vTnS3V9rSlod/rWfUX7hOFpEREZjbTxQaNqSTrHKSLyU5t/VLR/tJidv4LgHucLxzH/1ePsnKTRQkMmG00Yha1t+jrV57PrES9S3hl0xri+jgloGkORt8gHxqaIEzkGbaSZdxoi0RLivUYdX9xWHNPxeQy6LsQjUIKAZQtCiTZzzTB8aEjh56I4ZpH+zxci6T8LrZUd0Lk9hCinQcc4XvTKCBIRqebSDhX89luHdQbkZEXPH6NRf/ODDa7FmjmXKNVKl4gqvoshCtkph2EYSbggZvq8PQW/yFQTxh7xt4UR75DAaOeUdWp8bVo2TNHHZt4W6rejEcd72shISzvGcNgx4CyzNE3l2muvlc997nPyhS98QU455RTj87XKAN+1a5fMzMzIV77yFXnlK18pIiJf/vKXZWZm5pCyOYcT3iDy8PDw8PBYrxiwQfTOd75T7rnnHvnrv/5rGRsbK+J5JiYmZGhoSIIgWJMM8Je+9KVy8cUXy9ve9jb52Mc+JiJZ2v2ll156RAKqRbxBZCCUVEJJrPW/xrCtIvYAYMJcqbXyPvQKsA7PTc0R5GwDEx54jo3wVC0m1NLhqk6VzNDnngR1Z/anV7FPL00U7alalrr51JJ2g54+qt2eXF2SzvrWtHatTtcz2m3jkB7zjokZ/cX06WQvPEdPHNQeJYWThg8W7WpkEeYRkcW4bN1+4lB27Gxb012sG2UErcOj0GTtM0ttKR7HMT2xT+shjY7o+6ma10Nz6dPQadFG7augxhVt2LEvV7nGiteghUj15OfYYL+ORqaPQ5ix+JzeGNB1DKpulUClIci8yHbrgR3iYxaP4jnKPUNG+Ydq0vF5vlOBEN6dMOr0toSO7CJ6iKoQ/FRCoLwnSK8SEbxkQw7hJRsN1hOJZsk441xilAfBYQl+9Ioj2LovULDR5gF3epb0VrNOYTamOODzQu8O3XiOBJhI0WB4hkntWkSHBqpDNGB89KMfFZEs6Yn41Kc+JW95y1tERNYsA/yzn/2sXHfddUU22mWXXSYf/vCHD+8XPASC9FBpXscJZmdnZWJiQv75X7bJ6FhoTaVn7E6TMTigqkaQ8bQ3RnZRjslQGx/9GEEiOjWfGWmudFuOaSGtYB8lzMi6bIifgdFHyu9jz73mkGNj5ss4lAj31LXRNN/W/SmDoukwPjjxMnbnmRltKc3l2WLVUT3m7RNaZ+NlG3SWAmm16ZaOM1rIeRWzhpR9pnONVVEGrlgLV6bM3llke+Qv0Fbbfg5m3sSGQB1oqbYyiHAc6zgZLxQaep0vWGf9Jyel0EcAJGNtcJ5ovvO6M+3eoQlp0Ge0DAwDS31cx3WcYCE17Dukt0fV7HeJQNu6RATZttUncykw12A8nb5BU8IbKwu23buC8Xct4z7sVJN33fe8l0mB81ms54sM3utsKyp5eR+JxeiPHX3EDnVvm7I1t8W4Z9u4x2LE39H4Kee/s0EqOs5dfL5Yl397y+/LzMxM34HKvUK9l172jlslqtqN6F4QN+ryL3/824d1rMcKvIfIw8PDw8NjvWLAlNnxDG8QAUma/ZEGm8vV8ky6y37ZeNwUKCeFlsO7Q4+TWSIEq6J8lcLSHWb5jLRjXxEzy0xlZxjijtZvIrIJWXXba5rOejIPRH7x8Av4Xnrl9UxDe3H+7/M79Lmxcm3nK7ito/oaceW4CEFErs7aWPmpQNfGfq3Y98S0XkXt2T9ZtCfGtNfqZRs1vTeWe7ZYN6qJhXw9dugodRHhYfApg1L5vWxZOq5yByV4cXg9Itt2BqXS7U+dHOoCtS0ZggZrYe/PCChmJXdHBluxLz06YIXo0UmGcgqDmjRlu4fF6Bt9KMqOWW3UYgoXQHuSnZqBR2QsL1MzDG8Svl6pBlFQZAjSw7yUC4EaGVMsyzJuzzZ1UbBrgaIcEelt7sAsVdJk+AlqUXZEE68QV5ZZPcZ5QDfbuD6Drwjh6XHcV4rCDDFO0xvX+yvO1CmyB3GrdmrxrB4u+Gr3g4M3iIBYgo6YIBpCCqTGaOQYsTtdXngszFoz6nUd+u6tIyPDJRzoSs3vJ2WXOLFyoGir2CFOlM8gxugHs5v1+fhCY82jfBKbqWtjxqxxBPoMKcoTw9pIW8wNongEGW5wibebELZb0nTd96a36P5yVerxsqbUbOJzh2or0PAhtcD2NL5vo6kfvbmZXMpgTH+/0Zo946gCiqXZ0n2o68cYI4PWcr1TkVEW5enx7fHudC6NILGwaqn93WLyXTVk3VFAMZcTCByF/WjkGEYTs+eUcrcjoY5Um/F78qWe16dLZzFNYtc2jKq2TflYRMI8Q7A8pH83vmB5H3x/Rj87G7doyqybceRaDJn7HPoFzoVRbChSQ5HeZhwhRi5MLMa1mPIVHGuk6GakzrZC3Qdru5E+sxlelB3h/cjFBCnpuAvN66I41dzlknPwOLrhDSIPDw8PD4/1Ck+ZDQzeIALqaSSlNJQFFJVSAoquMhp0Nbs8NmpV56rzxUr1zPRiNpvazj5In9VTu+fIWrcMlB/1i2LRXgl+39Orzxbtv22eke07rMc/29KeD3NVZ8+UKuXjjimqxKrfcKuzJhkzfBq5d8RYHTMDC6vENjxHL8xokcy9z06KiEh1XHuITtqos9ZqEfWJDr2idAk3EpuH9aqfGXa2c/B7LTkoRFsQdgmaOa066AyslBNub/A3yLctOb4LGTPqE/G2V4KIrkmYzhjqzMDjlAT593IJSFJ+yeFFSnOKLYAWE4UsWa+NbYN2s9RDM64BvASGx4CaVPn3YuZZDeU6uL0dd/f+9vr58n2iLl6kEEkeIWlZPHP0hisvTJh2p44MXSNL2RvXsxOWOz1BIqZ3R40vcNB1CcbHc8cGPd0ZZO6C6jsu2zMxDxu8UTMQeIMIaKeRtNLQEFtUGDYmBr29STEyx+RQzMkscMrP0QeNINukV3EoBBpZa5YsOZ4nAuXHz0n5RaAKSSPNNTP6yTV5tBxGUMJMkvxfTmKLoH9SBz3F/Zu5iKGh3Ezw2jlSpSuj2XfkdZ5vanotKdsNFKJkca27DBsX9bHY6lTMZmHZ/XPaiKuhDla92RkBxpcFKbhGA/vipU/jp9CndNl2zFov4boP8+WQ9+1KT3coOjOzrTSSF7ulccJsN9IdlrghDkMQe5QyDskwchgnZeH/HErWQROxf8OoSTasDWyVdl8r6c+phj5e1jFEvQgz9mIIFWNyUepd+jCNJz7ElvEYkuT6PnBSyKDVVDYpY+tcx0UOgUiVlcYFplnjkYOFsj8359/XNafZ5qOgCwXpcXTCG0QeHh4eHh7rFD6oenDwBhEwGjZlNAwNb1A5X0qSGms5PBiuavGqphdXdyzjwePosakZlFnnXc19OSZDFNKg5g7tEnZVnN9ZmunYt4GgcFJcc4s60ys1gqrp6cnGRK9FjCBog96BByi1aMsEZV6X7k8+vRKKYuO2RrszUFlkWUApYKv67fIE2bxJItprQq/QaAVCoJN65f3UCxt033Hn/WYEMKPNjLQYwcftjVjVT2fXI4JeT2scHhYGLSMgOqQXJv+dKWTpKpnA686gX7U/+w2ruDdb8AZQ3NESRM6yG2YtK44D57F4trhNiWiKmF7P0Zr+vegNGs7bw8Y2/ewPRXp7qQfhwyJT1OHN6Ob9IUKHt5nlfIz+QtJq2bHMMCV9xgSOMkMFLGVyWDqHemUl0l0Oz5G6rvQyxYmdtidszza38bltWYLF26UBUmY+hmhg8AYRUA5SKQepRMw0yv+do+gYJoGWI3aH1JdK06dCNF3ANGBcafdjgdqGdFYK9jlii5gxEuXub9ZlI+h2nipp2pBhGq/c/KSImKnqnIw4qTRbmKTqndlPRqFP0ieYgII6KB167/PUbGbRGSKDRmaT2GEzMh0iiISZ1ZOPpwd3e8sR71KoWWPeJXXHF+zJW3TGH+u/zU2rOC6MH5ROddROxwSgu9pqePwqLAqLOB8aM4Zhk/8GhjxAmb8tDEf+5hxUfiypJ1JtS6G+92KsVIw4tVxxugyDiPE6rmLI3B5ZjKMRGKqMMWPB1hqMHPWyr+Klz/ZK0Y/hI+I2fvra1yLPzBhFGlJcQJYw1mFcG2XUqZqCIua1o1HVDu2UmKLMeP1dQpAETRx1bxn1CDmXo3ZlsWDylNkxCW8QeXh4eHh4rFN4ymxw8AYRUA1SqQWpcIlcz5edJq2FjChWk8dqaTbtrHZfQzAzPUGR2L1FhBoHqTGzDwQcO0qLqDIeHAdBPSSep4YxqdUtPWNbh7TAIrV2luZAn7Ut3hZ4iCIE97pKM7CUQ1jLxlGuoQwJxPGMDCx6oixB2gbFBa/QEjxcrFZuo8ScujuAax/liXIFYHPMJYxj04jOWjtxclpEdNC7iMjMInSPELQuLEXB6zvS6blgkHFtWHuZbOUMCENkkllBDi9ee057fZTHKR3WO4wP6UDkjcPae1ly0BzWhARQPvw9u9Gd3Ea6i9XdR0rac2RkeeY0dC9Ci/16fbrB5enpppHWU3/WYl6Yx7DVJjBLbKjo39P07rC+mj1MIck9R2YgNbzoUXf6TF0P0nK8P1iGZCjPEGyX7XPoYYGnzAYGbxABZQmkLIF1GpnEZDqNHeYEhg+MhE2hfsib0slB1xOm2ttjd2yTlFPJ2hEfRGNLjclldPVyntNqWQr+sy0dy7KvoambJWYzge4y0pnzIpvlTfolEjmUX1mLiBTL8FD2YnLV+YocRSK7ZQm76om5jBm13aBXSO05XrZUi47zGCyXKnfgeFEuQnCymRsUE1u0cTpShWglvtf4pL43u9WFcqU7E9bxsY4WS6oZKdOg4NB1eSR/6VhipERMiivED0MKS73QSkZ2EgwixsNYDP5s+6ENBz5HrsLCesz2+2AtjKB+6DBnHz2MwzQ6lAyIPWTAlcbPLLNGcujXD/vj78JraRObJe1GtXnGHjUtEgfGogfP52ipM+O2NcgYIo+BwRtEHh4eHh4e6xSeMhscvEEElINQykFolM9o5ivQRaxsSUPRE2T2RfexysiwizGyvzKyz2yenN68QggIBA2mqDQGhY/gc2ffXIXnhZ/q0CzaOXSwaH+7PFW0F5GJRB5MBfiS/nGhxKoJBrUVdGwz+qN4n6NSdmLxeLA/eihYQTu0aQ8xyNjwqti9LaSwhnJPjouGYokOI2sNAcPN/LvMHtCaRekGfW9Sv4jfhZ4vNVbjumABbgYZ22dZ5UWKHd4dZsaxXYE4pgJLsdDTw+vbLbB5xKHtQ28Rn5duJS5ciZqurK/iHGv0VuorOLqb3pCjL1e2rI32o3c7cQpYsQ8EKOceom7XTsT02Niy8Vxliei5a4D6aoadr77hUuc96Oq72YNm1JrBU2YDgzeIgEaaSCU1xbwquS+fRtI4FJ0NsWXceEyTV/3NOLJZGLtD2AweV9wQ27YUfRGdlcYJbzrRtMtwyAwPUBuYxDblRWt/VNeZIWeN7ina4zXUGxvWcSGkxNQLjRlANhoqa9tfhGkRu6MPXKrr87UO6PglVU9KRGQMhV7budXkijciSNe1kZqvYnDamKNdLyKmgMegAltRnu6Oc6j6ZiIi0fOIrwH12EYafLg1m8xJSbUdRlxsSCDo8anrzvpPBm3leN8ZNevSTkPVyDgr2Y1g2zWLkHbP2JLhMp8/GP+gVVSbL09XPTqXpEI3g8LV31pQYmtp+Ii4jR8baOQQNoqLRpBRVJp9WOONRMbL2Vwx39b3N89BmsxF83c1YIEhzG/zyJLtJohpm4fLJR9DdCzCG0RALKnEkkoTN9Bc7k2hivNk2EBbPywHWNUZk4PyyLCgK1PfXWVBbJNA2Vilub6HPfBabaeniqU7xmDotbqs9liI8oyRZ4r2S8ZfKNrPzejYoiaKWMaNXP9nVl8Do2An52OqI6NcRLQh+w0iBAg3Z2E4cD5+VhtH888g0DtPB6+dNFdsa2FCZoFYVts2FJZVqQpu428Eg6KFaxBZjMEmDLPSM9pQjbBwZcZ2G0HHyiMzMqkNPleByloFq2Z4n1qqjfT0xpL+jfhdQiMwG8ZWfs0MBXFcmwrS/02dKuye7z8ErxarpLMA6GjZ/jJThghjVlxeIRdsQdVrgdXE/KzU67PafkVMI4fxkgo0CpdQ/ogB57a4yPGSXkRNt4ZxPnuMVmyJSTJ+W+d36T3my4XF2C5Z4nFswBtEHh4eHh4e6xQ+hmhw8AaRBVxjTceZR+GZts6q2hjpTJ56qtvDWKU8H9ewT7aqiF0FQB0Uus0Nb6xsA7rsxdo+kOhx2Fzhw6hZVres+pZDKWyTwni2OVG0zxjV3qIvySlFO35Bj0MpIcM5JeVZeDv04tJAaQ5CbbmsQTJOZT6IUx6AZwBhXsZXzK9fPK3H33qRvh6Bw8OSsl6b2oUUKTwmLrVuqi2r4rPxor4gIzP6fPQQ8V6JtRNJ0rw/xlGRDjOz8fT2soXCIoXIoqUpsgY5fvZQePqoas04JXiOonJs3cc2DtJnzBZiSjRT4hX69Qr1g168KqX8meslrX2l6NcrZKUnAzs9adKJ8BCqawlKO8QNV16h+KQhYAkvDr1q9GorLEDhWlFxy49bqafvOWTRKnptre+lQ8JTZgODN4gAlXY/R3XhPM6EFNfetn6Bvqis31w0RIwq8vkEziKpLp6ebmJOopUiMLv7xGooXIedL4ma4fpGKioikSkLUMNLVtGFG2vayniuMV60T6ru1/uOaPpmb0m7whOLwdMa1e0IFdhpQwaW+J6UtNsoAsi34rjnEJeg47+LeYLjCb+HeIYtMGxQPoMlRNQ7gIZPWoURwQBlRzBzESBO4wnGTlnLDRloDyOQOy9t4TKCXEhsBhvGRkoyBvWV8rfgaZQh5NAboiHlKplhS+N3LSbaLBqMF3loiQvpJ94k299mOICCNuLs7G+ddm6B90KTuV7YNoOnl8DnlcIVUxVZrl/iWs3xOId+kc1IHIqYVGLX/jKSE/pI3Y9WaBzxt1UGdtxDmRWPow/eIPLw8PDw8FinCNJUgnTlhu5qjj3e4A0iYDbJgjtrlpXQ9+vbivYrR35QtOkVWoBXiCvCcZWq7qghxtUKBSBZP82VYq/QiwtXUWI1x8qL3gKj1pMlSHvniHa1PF/XLmWu6n5qy4+K9v/8zhZ9njyY2bVgj+FhcdUkC/M6XUYNNNTuoreFnhR2WMmde3TWMXN/eA88Os9qz9HCiyyrQyo+1/FY0fMBGsn47o3sPAHGX6JXiOwTacY5/V0amzqH5Er5J5gBptqthj4JvTWsZSaoLZVi3Or3CKgIHtq9RYbMgCWlmx6EwOEh6CcTrAdnRtf+ekkR7we9eIVs+4TSuxen7zE55hJ6g/R5LDRar+fpcq3NbD2q+ccdbQba9+IJYn9q3K5r95LhfUV7Meepy5HPMjsW4Q0iYChMZThM5fm4Mxtsc1lnIm1CDNG+WFNBFQcNZjNmxsK6ZU/TCFopaBwxLki52RdSu9vaKEOC78IMO8mNu60VfT2eXpzsOIeIyFQVdOIkJpBFdR57ZhmpsbK+1NLWl7owqlIdmiQBy4O4Kqxju/paoWNuoxpCgDiese8i+ywf09J2e1X1FOVG0lYXmolxHGP2+6A1Zt1sZH0V2xwq00FAI0jvb6PMEmR3cfzGtUZ8j4o5ChzK44aB5TLS8nEkGCfT/5lxxjiTtpE9mbWHjLT7Xp6t3mmVXlLqbVTZSo0g9zh6oOPwo3ajuXqhwYowAIeBaDNaRMzstH7iqhjryPlUFVt1hSDYDJ/l2xWqmAhc/U1EWRjAUsUrVR+L8AaRh4eHh4fHOoXPMhscvEFkwRa4Q/+5nmWXLSLylh6YsUh7eqg4vRUK1kqq6IctHYw9nWjhvclQBx8zyNlaoNIoBGu/0+tdAqVb2DYGTSUjGwirMJtw5Ci+N9WCG/AmccVlaNFM54GmiHs1klIY1AtHGrOt6puCzp3JzDh0jSKLYw6xuAYlZQzf4UVS/VX3o0bTRqxKF+FhYeYV20rRuwTtqu0IEJ+ER28YWWSgqibGs3vIFS6QuApbUrAxz+piFp1xTRmk7fLuqIBzemPw24fwJjGQOrUEgCcWOk/E9BYZ6sOxvmZR7plLHIHPLgradpXWuugq4fJEdIPL89EL+t3fBltGKr9LDQ8M54HFuLPotUHPO8Rr55C1a5xTBTk7jiO4nR4nW7C9WXCbGkd5DTeHmO5hgafMBgZvEAFxmv3x8Thn6AkRETkAaoyGCo0gPkRmhefs35NKmkKiwvVi0jm5iIiMGQ9i9q8RV9SDy3kEle1rFjGyaUw0romENFgtj134iZqOD/oq0usJTiQbN2vua/6pbFLku8CocM9yHRhSW9uQBcImXpqgWIx3GF+2lskhRr9GBhxjlmAQWceEUzBLTlF7y8eRsrCpZUyM1wlwf1QntFWoCtyKiEz/KDO2h6bsKWmMDzPihrCPSoNnAdykZb83ndl/JduXwTlcVFp46Fmb9BoVvcfK+nqwOKdKHa84inC66BouFqr5S6/fuCEaUErJmdQZ5wmXwrVrrN1pPLtx4dqn274u1CwrBBo+XESNRXrBt7N8oGh/v7Gt49yhw0B0bVco49zsj+Ok4TMR6QWruh4LSO00DenVx2V5HB3wBpGHh4eHh8c6hafMBgdvEAGJSEcI5Ei+Mhkr6SDiObiLmRWGyh3SsKwqm/C0VLAMn2ANJng5pkldKHkXSymOXmHLRBsHZcbSIq7aQeqcU7getcjuHucq64xNe4v2V5IsJcqmRyRieo4YSM3MKzW8kIKO0O5hHDgnBHrey7P5OXQ9VNMrBOcCF9DsQ43VWGC7FpTMOKNXJb8ORjYWHTNb7QH49UZn1uLSPATqJvUq2FVstY1yIqHNe8OLR+8PdrUmcuG7UlTRmTXIzLH8OkSGNhFOjRNON7R7L6nr7SrY+oRR7ZXdWNbXwxVgbSuH4yr+ait22nFsvo8R4I55wOUt6gZXkDRvm348G/16QdR5XMHTnAdIT9Fjc1IlK/Ozp6XrIvYL25zGcbAI9Y6KzoydjPRkon4PBnwzI7gJl3VlkFSZgqfMBgZvEAGNNJRyGhoP2TcaJ4iIORFujbQxkKTaHUz6zKTMsgduJ97oRtY1JsJFumotxo+rTlkvmE0r+XH2yc8lCjnsCqDJsa06W7Q5YXDiP2lIu8q/bJn3WxMQQayRk0IW3CSog5yWomGBkkhmCAtilZi1VmjAMcufmeX42iWHOOLCCUpCwJ5BFjgEDI33cZ6xlZImY3FU9N1c1BN1ZUQPMMgVu4MXtEHUHtMXpMr6ZTCCbDFHZi1O0Gu8bZgSX2GWWdZOmYVGo8qugGDEMtUsGTyMG+K1e35WK3qm39Pt9onZdx85Sf/4JcOY4b2uO6QoYSH0aCx6oOLsSH3vhl6UpWlA2WJY+KK30VdZH/bvuJag4RM5aEFSjhy3ohN7iaPqNtfxuzKOkdnBpMl4zUiV6f7s51Nzeb8U42rgPUSDw+B+VQ8PDw8PDw+PdQrvIQIW0rIEaSj/2pgqtqkSHHQp7+s4MsNGrkAoJJavbhaxqujX07PS2jnTWP2oVY/LNczAzwS2cjmlW7xzdXvW8FNFu4H+Npa0O+Z7dX1Nm5vz/iL7d0qx3VjdsGRG7jXh4pg10DhMLuao9N9Wnnp6bphx5qDJ2EfthaDjc1JwZn/4MhXSSPl2R7AzvSfBAf17xlX9u6hSGuV59PHPOqtRfnIa/YHOgldKeYtMIUWumejS4Qg7tYVCjM3IJsN3ZN01QnknFxYR5AoPEZ11o6PaQzv8758r2ooyayIgfbalfyTSvPQczWGfDZUFYzwiy2kyBgOvLPC2F+FAG2qOIGIiNjxfnV63XsbfzbPE7NsJBE/TO7yIOahhCfruZW7rdn1rSB6ZBDXKazCObF7SYLbaaOyvZugTZddx0XHvHhZ4ymxg8AYRMBk2ZTQM5SRkQijQgKERMYviqRQ2ZIyNIi744LsmgZUaPoxPInXHsQ7nhVmbhkGk96VYpC3VXkS/HHg9ppA993w8jn31mM4Z/X7R/ouRV2QNVyaYUf8LhiNiRNQcxfcJ5jAjPokGDIUN1Xaj7JUj3oixTIEltojvm6Hngo7Ps/Po6z5zGvrIKcKgSz0vEZEEdGI6r3/baLjdeT49/0vjm5NFu3Qmsh1h/LRzwcMYdBfjipLITv8ZUNsd4y+X9YVySQEs1rMfrzWPHxGGG8e0VNf7sL92OWuPVPSPuxjA+Of4HIVIn8+Lem6pkiJ3XIMeMqWs5wZ6ERHsZhjQAOgmsNiLEdePoWRm2Yb2dkpDSVH49hgtF2yUo5HRCuHcEcRIci7korBlkRDgccNoq5CAaMC1zDztNRh4yszDw8PDw8PjuIf3EHWB8qAw8C4yAh716pKrijm4KJQWkEvgjWKM5Hq6eYtctBtXsXT9qvMspnpsroBGjsnQWsrHZ+gbBXTf63OPRJ2uZhEpvDAMvDV0d1ARnSZ7whpnuReJ3h22K9oJYmSfEa4yGMU4cGmoX9keBQWUe01SlvngJTUCkXVz5Em9Kl08Me9jwu6pMGp+1UBFzevfJaln/cEBIy3trDOux9K/6Q9KL9Kr6Sj3FqUQyTI8IrxN4aVR+kWuMVMDqR3bdY2MJD1F/43qH7QN71rSRjka0KuNlr4e5VI2Jgo30us2Dc8u9YuGS51U2kJb30BDRg0re/Zct0mV15RB3GZ1994DosM+PEiEK2PVNe9wH9t5DsSaK94CDzm9QnO47uo8rjH3EnyuQOru+wh5OL32TNF+qqkL/k0ivEGFCpT5mIEmY6KI+o1WKqi5IqSpW3G11+M9eoI3iIBWGkgrDWRfrN+UM7kgozFZubK0SnqfrXDbqomESdKulHlORk0jPTft+Nw1oY0hrWoMlMje3DIgHRYa2SAOCgMG1GSQ8TCMJWLqPjFmKHDrl9irTs/os3/4v6frnXFx+A6OlliwVW8vLXZuM95PmANs6tQimilpTjg+d2SZlZZAn+ZzLGm5pW365JUZ0GcsCUfjbTr7jo1RxhDhe8P4CJDCniIOSSlit2CscZxMpKnt09sXRjQXOLwtu2cNus7RDo2MOLHAHjeUGjXVsA8Z09xQpuFjaicgg7MBJXBsn25m36tU0c/k2LC+EYbKdnkIxhMluWHIFzYXCnyeafC3EbeU5MeSmowMG1N/Lz4jVYfAYhF34zCCjIw0x/ygDKzQFWgHGMYWtqu+bf2KmDE6M7FFUVVEkmJlpL+3MSYH42ej5nhuZr4xPmhLSWfD2hBiYRc6lKrV4i8eoFijzzIbHDxl5uHh4eHh4XHcw3uIgGqQSC0QOaOiRQSVWOHzsdY44YqN7lSu2lhDrJLrlbjqlHHfaaymSEVtzAt5UTiuF2HGAzGzKcKO41wCjNOJ9hxQO0St/MbC/cW2Ybj9SQtyhUqi4ScnfigiIo9ueFGxrY2VvplNpjcH2K6CnEuL+BzXhmU+yvDuMI5XeYjoQWIgNbPWKPRo1DjL+0gcT1JzgsG7CJrGd0nyultSh9YOtX0MqgpelSouTn5stAjPErz6rvbQHtRgm8y+ZIkUGH8LR+2xOD70fcjxxy30h+/CZ0d5dZrwEKUNO9UWMIsPnp5KrdUxTmoZtUPoCeH+ZVaaekbp8WmT0o7o3XHUIFRV4YWfI7DceBb1OFjzq5/SHYkRjK37owdFeaKGDX2j7hSQjdoy9UjtY6MwI6HGwbG9rPa0HhO8NP936eSiTXpMzcVG1h2u6SweaOM3QN/qWM63xrxOT1uhQ2T9SocHPstsYPAGEbA/rkk9Dg3KaTzPzDqhojPPnkccBI2ZExDEMo2JWBlVdcdbM3FkiDHrS9U7Cx0Gh5P3x/41aefn6FQ4Xo6pSLuX66Ee09PtDSIi8jziBU5GvABpMleB2J3lzJiKESuUsmYW0+BJn1nqiRkGk+OlTyotYY1IlWbO9xeGYdQhI3NU6cw04r6lRRgLFb09xPdlodq4GnT0EbP2GBSiA8S7hKCDkmo+cMzUrPMWOjLpeJ2SfdnFSXdA0bnd+V1FRJKWg2LJqTQaIknsMKpgHLHGmUrTH4KwJI0Cml9txKHFuIdajeyeLVf1fWfENfWgCt1OFLWkx9w2tBggxIq4Ky4KSvkFDmGJVwOOA/FQsBwbjrlCiUEm5Cld6fPs2yIUS/QSe9QtbiYKGDPYSTP1gr2tyaJNY3HUwXurcbsUswlSkiHm3BHJHkaXCnXTyELL2vV0cDFEQbIsNGAFx3v0Bk+ZeXh4eHh4eBz38B4i4Jn2hAy3I9lZPlhsUyvJCQQOb+Eq3SHfX8eqQvXBStquAGaubriiqTnczkV/PQRp25YK1A2qBfoc+w3hMj0OlUlnijhqTCFwka5tBp1uyusIJdDRCUEX0S0UkmKxXepeRBURUGxosKWd+xqLRFBm3IfCkcX56fnA6r06TR0le3+FXhCOi2so1wFPRILMsYgZZ2PZbxfOstAavguDzKnXRGdhvn/s8NYZcPRtBEJbkBreIlDMS7gXci9TaPEaiSyrRI7g7pKl9IlLz4kwtHtQn0R5Ydrw7jQD3EDUL6IX0tA4yv9Bpg+fi2rIDCYEejvoHRvoSWnBs5Ss0DVQNqg217zS2Tdpz8ThkVJJKiJmKQ2F51o6w4G1x+hlGinruVjNTS4PEbNelWdaxK7z5PKcc9pR36UxwNIdnjIbHLxBBJxWeV5GK6FhzPxz/RQREXkUD8tZNa3MPIVsMqbak3b7QWuLiIhUDDey/tzl4qWRoxSnJx0ZXS7KbBYZYgfyyWgnhBQ5/rpFoCwbh374J/PvVaP0AOMgwAU9hUnDFk9kKFLT8CENxnmX2TmHtg8NGPXJOAfnwzOEG8ft19ESFmKClI4jw43xTlaDDcexLlsIWsiYtIcQi5LTuFHb/gIzDEFcO77TVfxRe1rfM8GofhGRBjPTwkirpZ2fBxYDUpbVOwOSnB5OWKrUIVoZwWg1FLjze4tijWHZ/qJsxaRSKBKY94FB0zgKMb4EdFcJMUlhbmAxDokgvTbTLlm3E8Wz6LB1ehF9dNU+U3DFLNmMIM4NzzYni/bugycV7WfmtRXP7D4Vu7XQ1CuW/dM6VpMq5Gdu0XGdPz2pRV4VRT+X6KDBL8+8uGgzJmyshEVtRdP8rx3/toiIjGBOdlGMrfyV6YqXOhzwWWaDgzeIPDw8PDw81iu8DtHA4A0iC/YjYFiJjTFTYj8yzljxmm7uYeRVbY30akSBWVxNuOkNkUMG/vXhEuHq5gBc1NP5d6FH6sWguMpYSoxhJV+nu99Sf4i6Ks+0NWVD8UYGnxfBzAYN5fo2oKJAtyiqx4ghdTz3RgAzGKVCywjjKC3AG0D5FFJidGzkmxnATM0ijq/lqHGmap+1RxAA/3xnRp2ISDKB1T3ECmUhDyLGrUY6jN/byJJDu5w7C5MqKKQq6TN7lpkR35tvN7YZNJnebixdGaSt+nZ5lhBk3nZ4gFTwdimyu1LoCWKwdQsehShJ1M76ONxk9D6UWP+NHkmlHwZvKD0wFI50BTbHeHaK+Sawe9eY/USvEB+vldZd43ykvsP/3HdWse1fvn9C0a4+o28+/oxzNschx4w30tyIvmn/6aB+eF44SbfHc/qMwe4nDesEmE1IMf2xmq51Nxnp7TbvuivUYDgPwE4HKczoMTB4gwgoB6mUg9QQVfz3Qz/MP9MPwCQyqYgFUGYs7qr2X3Bw1HT3JqG9FpFy/bccGRukUjg+ZqrVc/qMRtc/IJ2V2ITCrHOQAlCTIicU9sdx7CxN6w4xvyzk4wjm7ZRIaRbXgHE8nNXVpYntn3O+YlgLKaLmhrwLKGAHNLpq9heHoZidj5uKya2NyK57Vj9ijU0oxorsMxvLtACjREYpg41z10H15DFYfNdRuduIgbJID4ho4yhs4BowtgvXg9fJiKlKjX/yMVFwki8aO82o6FPD8CzRgMG+YkcR2oWO49huRCQO/qnloLmKIbkMC8OAyjPVmM6Pe51Pszk72JWqlWHlil2ksUWqxyoAaYjNatDwESzWeC33NDeKiMgP9m3W439Bf4MKNBCNMCTrYgLjZ7wfFdNx2FJbn+eVG5+U5WCG3snVF4r2JixMeT3UArKX+pJHwgzylNng4A0iDw8PDw+P9QofVD0weIMImE4q0k5C2YmldVMyXmWTI5j56bZ2386l2sU7mWrPjKKLSCFFkQ5sng1QV8nhilVeH67SehFs2wQPkQrI/sKiLrXOjJeLRr9t7aMFTSIbRlz6HVgOGrXRci4npc4PgqpbE/TYiLVdLHKDoGObiEgyZL8epFv0cYxm7m/2KI41XCL6fxo79b1kBCXTa2LLVIPoYtCE2GIDbQRQR/U8Iwr0mkHdGePDMOCWUD9jCQ5Qgz5zXBuOo/iZ6TQiTeISceT2Lj+B0QeuTUKKM9cfasE9yGBsltlx6RPFSofINSBTldCBQ0+xFIW0CTpm27tkmXH8GBQ9JdR5Uh6nyPHcEi5v0Ym5LtvZJ+oEkx+Obyzazz6t26UXQAs2O39nlweDdG4Eza1XbNxTtLdXpkVE5EcNXafshKrOTjNKE+G7MKPPVobE6S3Kf4vIi/sck/AGEZCmgSRpII+3dIyQysIaA5W1kOiH4SVlnTo0ndhFCZW440LKeAH9wNEIcmU3KMFGJa4osiwuB6C4I9s/aG0VEZFXDX+v2MbMOIIGzFNtPblN5mlapMlmjZpr+trQUCKVtiV3Xb/oVJ058sM9W4p22nAYALhbC1oF9JVBsThifmhoqPcIC8sy3sXJxzB+Ru3vyO6igeU0BtTpQ4dRwCHhPKS21MvDyPhmVjivnWMuL25DxsDUeXIaH0aeud7F9nbjptT+Ha3XxsFYhSP63jPivyrIuktVLJPdMqOhRGOB2WfiKERrA4USDaq7BwFIG0oGnYXfOU07txnf0U5xEYXashGY5RDaDOwGhXrOz538t2LbK3MFehGR56Z0ZhmL43JeUdsfP7i12LbUROwRxn/mJk19nT6s5w0Fs4bb6ovFuqCVqn2W2bEIbxB5eHh4eHisV/gss4HBG0TA8/GoLMSRtZTGbKo9QSxDYWRIuMpn5CuxGlYxdcbGpvafgQHRNYt7uyLsz+59Yg22F5WfFxGRRfAk7Ne1mqWoopKx5+pyBMI21I6JHfL9qn7apiF9TX/EMhRcuIJWSxnga6NvXHSXQz6n29LJyJRyeTNiyzb2ASowcXiLVNBx6vBqgVVxlghRPxFpBiMI3a57adV5ImXG49r4H8Prxuuuvldo98wQ9HYZFJvqz6BLUaIDqUgRtJjarU6vT2q41xAci5sMzt+CJss+yAUisc3wODnEGA0KK/f68ZmkfpFBgfMewm9XsoTymsKNdtrNqAqPH6xwBBqKpA7viUuA0PKT0pt0IkodxRVmp3X2d86E9jJRuJH9TUT2RBbb+egtGo8OPYcSzBiuGHN1uWN7y2eZHZPwBhEQBYlEQWA8tN3q99AFTLEuW3FX8zik0vbwcM3m6RdMv2+5c9ULbAoXDvk5+9iPQl9UsJ5CtpgybFowwPYnIx2fi5gvnRFLdtwpI1o59pulHUWbtFXKl3DZblAUSBwv2HJ3Q6nYRAOs1Wm0iMiyF3XQ8blr3qVoohl3k+bD6U7XQVvOyM5R0gKkyfjCNt5DLgMx7NyXcUimEQRqlzFYiWPgFri0G9VvF8EAjjeCJmMKO8QdA8tKmBldPI5ogxqLmD4vKtbGnqLfNowS7gPjJz+22SVjTcQUdGSdNBpHjby68zDkxtuOeaCNA2lUqfmGz37LQZ27aoipm4FGywjiLA+09UKM56nCYp/MlaopabIRN1zsiI1if5r+w5yN7zoc2GM/bWAlAZvhdqTgKbPBwRtEHh4eHh4e6xU+y2xg8AYR0EpL0kojY2Wi3KXlRK86NmGZPsesFLF7RMbyVeciVs/UJDKl4R0S//ldPY1UGq6UXgQvztPxmLUPm0epjtIe03BX09NDnSRVkZvjpGveqHsWMFuv02PGwFGDkjJW8gh4Duk5yvelpyh0eYLswjWBzZnhmjwcdEbhDXKUGBH7V7FmzBGBo8q8kXVnKXFieHwcTgkGWBseJeWZ4aKal5dZP3V6uODFU3RX2ukBW45uK9d4xBHsTrqxzH0wjrzz1HESenoCg0ojPZZdbIo/EvQmGefB9pYlMNuZtcZ98AzEliy4VmL3mJCuGy01rdtV0DfnHXpuGqDUkz6y3Th/1NkHS/t0qRLP79rAHNmER9pG7bsCyI2aal2yyFwhD9R1mzZSGT2ONXiDCAglkVACmYSbWKVt0mX7PGR/WbOMmR+sC9bKJ+qNkX77LKRUxNPNBSiT2Xh/c7z6Af5uSwukMSWUfajtPAc5e1J3rHdkTMi5FcE+6Crn9mEYROTv1cR0UlVTZuOj+pofPKApuARqzIYBk2eGpVarxo3A9nJ2GDA0tox0YW5XtJojmymhAKMruys3fsiYGJSfw3sfs45X/nOxkC0NGJd8gVUAnZQaBcZpE7JQbcQXdmd3hrimK36JUNeXnxuxPegPuxjGUZfsLiPVPrFvx4DQhtFFtQYqYlvikGyG0XJQ7ZovfdZBU/QdFbP5OYvF0miqom+b8WAYPj0YbIVxgeMWY2aT2UMCzMKr2bGU/uD8we0sWsv5TRlyYwFihTh34fdihm4/oBGk3ge9XKO1gqfMBgdvEHl4eHh4eKxXJKl9pdHP8R49wRtEQD0tS5hGUkv1CmMkX3ExMJreDur4GJXoLQvNOlZ9LjHDFsR2url4mYU2h4DoJlZn3Ed5uRZEr8K2ofI9aTKXQKTKZuPnP2xqDSEVKJnti2w2rM7U6vHHq8/ocYxqWf0DL2jKz/DSsPK62s5CagY9BcrGqMaOfVLLNsKgffRmUkrqMlDg0CiZwbIhCNI2yoyoBS8pMEuQcdaJvU1BRgXOgxE9RC4hPPVdXPo/Di9TSf/kEue/SwxhTCetmdi3q/HR0WKUCoF3hMKcgkDvIL+oZqagPYrb5U1SpT5CY18EdIPCjTB+w7GVe4aMYG0HaxSiEBk9EAn1nyw3q1mWg8HFGAdulqV8zooMN1+nJ3k5bPQZaTRXkgc9NmXDU5z1R3ptHt73RbhA6S2il2kiny45z5kUPuZTZro6alB2w2IeYrDYhfpbU/gYooHBG0TAWLgkI2FkTAgqRbwOly0NIj6cs4jHGTGKtGaT2CQm0HpKFzuoNDzMO/CmUTRd2TEB0ZjZgjpjNNhUFlnLkeZviC3CwGJsgHLZj4FXP6F8UB+HCe3fmlpw7WXVp/V5ciOzhkpOFbxtK8OMPdLjD0FLFPFENFr4rkWxUINVs7ZT+w41xDjxpQT6Q8U7kRozap05KCIaR9YJy95F12JKgcvwcbSNd5g61jE0I1GQtgxrUeXvNqMeGrP8yg7r05KdFlFYsuy4IDRmLH0YiWcuw9gBdShFHEMYNiU8q03cE5Wo80dibFLoKPRaR2YZ6TPDOMoNQ25jdlrk+mKWIrKtwJ7+T9DgsS3KaCTxu5C6c8Ueqf1dGV2ku0gLMntuOOrkfLkgLKedCzGR3jJ7bVBhAKlXqj4m4Q0iDw8PDw+PdYpAVhlDtGYjOfbhDSKgkVYkSiNDNFGtilgThyKIXGmw3lmLZQLyFdACMtVauE2p/0Pv1DPQ8tD0WafA4XI81Z4o2nQlq6yvWqmzjo95DnPVRnpsfy70uOjQLanCjcAV2ZeXXlK0f6L2o2wc2He0rK9dc57RwqARmHmTByIb2WnYN6r2sAJUK9S23cuU0svEbMIxvepUdcYowEjwJ0ocZUbK88rbpbcx+8vQ/+kSm2vLPMs6dB2A8dmy3dgFBSIZbM2sNfWT8ncxsqRwDbrM1AataKuXJmKWaCGtlnuDEmSe8f5I6PVB6RZr6RGejjQl+jbaEWirvGYaPTqmSCOfP415eEYN72nufWrCY00abcihT8TnuZV2UoHV0BFwbIhP0muVnbNh0Gh4/hxzUyvt9FSRRpuI7N53Q2TSqEkWd5yPFBiDtI1sWYz7JZV91rHqc4DmOxL6RF6pemBY1wbRzTffLO9973uNbdu2bZO9e7NaNmmaynvf+175+Mc/LgcPHpRzzjlHPvKRj8gZZ5yxovPFaZD94YHaH2cZT8ykajGeSJierm88m7HCcJeWxehajk4pQ5HpRNNXnFy2oAArJxLGFinMYmIYDw+tALscamLixLCxNF+0OfGOIUZhpqnHfSA3qqYQv8QXQ2UMlNl+xEbhpVOdyPp2pU+HjlRqgy7Kj03xOV+qRkYaDKygZe+v+NxB0/CW4Mu+NZYdQC9+eU4fxxgdGiI2m7QXmsywcmxyAS7ZAJeqgUtywHIOUmmGcWdktuUp80YMkf18rqk+LQQbQbNSnRrGNbdT8sGWwEgRR0Nl2iFIqbLPDF1Ph/I1t7fwQ4cVPfckFkHStoO2qsE4shk/3HcpRpo8qH3SaoSaY4YRUOfKJiMMkcb8h2SMERdUFGx0yQKo88zFek7bVtbzCs/3ZENn4v7E8I+KtppTKeLIRaAtxCDxgTnHJNaPHKcDZ5xxhjz77LPF32OPPVZ8dvvtt8sHPvAB+fCHPyxf/epXZWpqSi644AKZm5s7RI8eHh4eHh5HB1Ta/Wr+PHrDuvYQiYiUSiWZmprq2J6mqXzoQx+Sd7/73fLGN75RRETuuusu2bZtm9xzzz1yzTXX9H0uJczo0uBRcHl0SKXFhlR+kh8HgTL0MYzzcdXGVZbq26C4sJqi56hskennsTG8XYZnxqiwjfFhFTicH2vUe8OKjZllcwiwpkfp+XaWRbajpIOx6eo36JYmvDfYJRnN3f4ItKYWjCGax3piQlolPweFIElVcTVOT5QteJf1vFiig/u4NHjUOHCcTWNIZFm5DmxXEjCucxgL9j4mSENeib+Ly0uTn9+g/OgdgcOSYzIC0dXnDtrQAMdkiDdG+ZgpnmQXUkS8vEmx2Zw+vCDoLwYFR2+ROn+1YqekEkdSALEQ6JthKKe765i6a6CZSKUZHizSXV0Cgl1ijGZ/2biNxI6wM5FERKTFFEwgzB9ANR9k+yIcATcRx2QrJ7Ix0l5qjum5lg4f+N6CTvL4+32n6nGX8iQPXMddG3R9tZMrLxRterUHBp9lNjCse4Poe9/7nuzYsUOq1aqcc845cuutt8qLX/xieeKJJ2Tv3r1y4YUXFvtWq1V59atfLY888sghDaJGoyGNhn7Jz85mdFMtbEktTAzXaT1PXiWNRuOD+44jXof7b8wNlzJm3jnMSZOIEZimq9xIp82NGSOWyR7Hs5hq3ryMN3wknRMh9z0At7mZTqtvE5VdxmwyToQbw/mOfUXs1J3J+zticGjMjCNzJX8ZuYwgUhEqjkNEpIkXl0rZjpt825Iyw2YKMxrijkHnNkfRUlMcsbO/wNKtiJlSH+LdYqS+55caP6Ep9Oig69hWCTvOGmPi2G5rM8uc4r4GNYZ2H75qQ8Wbp2Yfysil1AGpJV5+DJa10bpFoyaBfdABAo3Uk8H7sYLfqM3MSBeVhnErA2u47FCBR4bbfEs/28xaI5WmwHptrqwvZrO1LTLos6Kf8bZDu8H2nHPRualCDQfdpBHE8AVFsUWG5a6/61P1jUX7e9NaHmT/17VxpKYhZjJ+9zS971WnfaloT+YZvPVuAXAeRyXWNWV2zjnnyKc//Wn527/9W/nEJz4he/fulfPOO0/2799fxBFt27bNOIYxRi7cdtttMjExUfzt3LnzsH0HDw8PDw+PlSJI01X/9YMvfvGL8vrXv1527NghQRDIX/3VXxmfp2kqN998s+zYsUOGhobk/PPPl29/+9vGPo1GQ6699lrZvHmzjIyMyGWXXSZ79uwx9jl48KBceeWVxXv4yiuvlOnp6ZVcojXDuvYQXXLJJUX7rLPOkl27dslLXvISueuuu+Tcc88VkWXCbJL9WMu3Lce73vUuueGGG4r/n52dlZ07d8pCUpU0iWQSUayKRmo6NCy44qF2z1a4cA/kLmOKedWwoqFXyBBWs7irKRBZZ1VtbB+x1mPQ2RIGvUZNJbiMjTpk+O7Ko8Q6Q4ttvRI1Rdg66Tp+F3qeXjXx3aL9xUBnpLFSfQhdoGo5Gyu9PwxKNTSJsJqjF6mgR1xBxswcc3hYbFJGpM8CSxCsyDIqSrkrHB6ixPGU/v/b+/IgO6rr/PNev23erJrRMhJaSYTZBCbCGBww2CYQB0ycpGIbYiCOkxQhGGTsAAmuH4RiS1J2qDiBBMUFqeAU/FImLpPyj1gkmNjBhlggsxokLLSh0UgazT5v7fv74/Xt+5159+i90TLSzJyvSjWtfrdv39vr6fOd8x2Md7Vx3oxNwGBmnBewN0hh+T56mbcIu/azifGxwRIi6HDAr3A8Nuj1SUe3ThlK8iUgYYE5MNjxxZMerU8IJxcyHKpFdKvhibE7Jz9wfcI/Pntui3BtVqrw/EDhUdw3erCgb6uJhJ7O1gzULINUDKZfBCcpE1FRBXAnotcIKSfmKa7Wfz+jN6kieJZwHEiNn9Ra+3BFL06L8OxamhmIl9lzxVeGBL7zezLuOTw84S5Kdo6i5fzJg/G6jy1zzyPMhrU11crT6SEKiTzO/altPwWMjY3RmWeeSZ/73Ofot37rt+p+t7G7jz76KJ100kl0991306/8yq/QW2+9Re3ttZt23bp19NRTT9Hjjz9OPT099KUvfYkuv/xy2rhxIwVB7fq66qqraOfOnfT0008TEdEf/uEf0tVXX01PPfXUYUz28HBcG0ST0draSmvWrKHNmzfTJz/5SSIi6uvro8WLF8dt+vv767xGk5HNZimbzdatDyikgBLMsLE3F1JjvSkXtI0PGuTNO5H/jv6OwJstDw+aBfC2GoAHPxoRYWTwlOAtyDLfBLFFhG3Tk3TCjVinxxezNHl9d6L2gFmQdVltNhV/MjDN9ZTcrrr1uI8T0y71NZeBjJI8xEOlsRhs7VgjRVBlNANmn3mHF2cMsXR+SeYemRR8wPhemlMUALQhWlLcDZ5a9hzG90/UhiljY9iKoILtTQYS4pBY6JRAffnGiUZQahwMAIyHYrXRan9ze926Sh6oU2CKURATs8VsH0YwMgzGeQEdmvAUcmXxYU0A21sBUYMGnVA7rYpDReVuTPWPKD1M88eMtELFGTktQKv56qTZ2JnJSDWh1xCLKsJBlep7pZK+i4zo5eHlRES0bWRevK5/0FnBeL9fuGxLvHx227uujecCxnWrsu4iOn/p1nj5h7QqXrYq4z2tIGhbce8ANEi3FGvxrIVShYje8E3ruIUNDbGQ3oMf//jHmTMC0Uzs7tDQEH3jG9+gf/7nf6aLL76YiIgee+wxWrZsGT3zzDN06aWX0ptvvklPP/00/fjHP6YPfvCDRES0fv16Ou+88+itt96i973vfUdy6k1jRhlExWKR3nzzTbrgggto1apV1NvbSxs2bKCzzjqLiIhKpRI999xz9Bd/8ReH1H86UaF0wrDYFhswPFx1wXn4EOirdMXLa7LcJWjRmaw9sLrh2TLOgqf9XiH0IhU8zxQ0mAL4isHAZqzUPBxpckjeLgncMKuNFQMh0yxFFQpRwlt4R7knXrZfXGMJ8CyBd2pRuzM4R0fBOIX4jmr08gukopWQHh14lIOJiHJtNU/geAkCwYecEReipwddLBgIG3XNPEGoRIxSABgjgh/C1kGEXgF8V6FiMxZK9XzlMuMJ9sHCXaRT3sh4k9LxPe9MVvwd48BgfD4jiMgZiHg80u5dRQXwarE0fug7Pnd4vHB8RQgcRhkFj+HI9I0wAF/M+ccdRduCtVMVYsyYIYqGHNaKjS7VIhhEVTSO0uBthuutJQ1xQ/Y44TWGbwK4+FKCe0GK+Yu7YJpEbnmo7O6vn2yrGUSVMbfz7B53LxbBkP6Pwinx8hvzXZLNOfO3ERHRyS27vWPDoGrEaQv3xMvWYJsH8UsLM/AMqqJxFMmOTKPc4aHQXpO3J6K60JA77riD7rzzzin11Uzs7saNG6lcLrM2S5YsodNPP52ef/55uvTSS+lHP/oRdXZ2xsYQEdG5555LnZ2d9Pzzz6tB5MOXv/xl+sQnPkHLly+n/v5+uvvuu2l4eJiuvfZaSiQStG7dOrr33ntp9erVtHr1arr33nspn8/TVVdddayHrlAoFArF4eMIZZnt2LGDOjo64tU+71AjHCx2d9u2bXGbTCZD8+bNq2tjt+/r66OFCxfSZCxcuLBhDPDRxHFtEO3cuZOuvPJK2rdvHy1YsIDOPfdc+vGPf0wrVqwgIqJbbrmFJiYm6Prrr4+FGb/3ve/FPOZU0R2MUWsQsKwT+3W2POU4bKTUkOp5p+wyE96FPpZFtb5WQ7zLGDozCGNtHEaw/lH0lRWAv71VcEW3k3MNYEySr2BrwLLW3NdZSaDgbGYbZtGNVf1qsBmITxqCVKN3yzWBtHPbnBscj/nS1sF4eWvgPEuVAfAW5Wp9Y9xQGjxBjMr0HEcil8mDmWqMqkiD9wnUjMNyUN++7OGNJgM9Oh5WjXk4BG8Mo9KS9W0wuSeJp7BY33YyYvYPQ3E8+5gMlj5va5mhdyqs/52IqNLqlkFLL54jc8rB/nL73fLEImlQnlUFiDFj6t/gzSigO8YeVKFfjIHyxYSRo+wkwU9WtFag98ij0I5SEWXoA1P+cRkptmqmttwGgo9YWBYxlXR9pOXGK6C0Dd7fF1518YGZvbULNIeycZhd2eL+Uyy4i7mnBT05NRpIKv6Kgo6LgObvSDv3ZMqKTMJF2+5J7SeaXs9QjCOkVN3R0cEMosPBocTuTm7ja99MP0cTx7VB9Pjjjx/090QiQXfeeeeU3X4Sxk2mLiCiPVG7MfAmwxgixAkp59fPwUm1wc+vllphnV+bA/vOecReUCF1RHgIVJlGEOiV2KKqYKgMgjsYqTGUEEBjpTeojQ8NC+xjIHTxRF1J9+BaAgVg/6dyEhFxWf0eKEjbkXL7XtDlgiL7+p1RVZyIAtUhh7k7D3pOoLaLcRpM9yV6YWCKc0urP6gTaQlsYdP/K8KLkiYw+AjiSAIcX/QzGBYsJV16Pgh0S/wz7BprYEqlQBKekJKEYIyxWFa0s6PLjcVDSRQdKhVAGFravrekMiSwXX53wreaSl3R0LJ+usunJVW/HxuYDatgLgHSdSyGDI3uKIYI6B+mjM2i02ERDVFsHw3QCOOv4nkWrvu4LVq7OUet471dgWeJVHDWt10bGByv73cxnnijWGqUGdRAcVZbwFAFpfjhkntu/HS4RgOd2v6eawtjQ4NocWYwXu4vO8PAzgV1j6QyRnZ92RzcOJytsJqAB4vd7e3tpVKpRAcOHGBeov7+fvrQhz4Ut9mzZw9Nxt69exvGAB9NHNdp9wqFQqFQzGUcT0rVGLtrYWN3rbGzdu1aSqfTrM3u3bvptddei9ucd955NDQ0RC+++GLc5oUXXqChoaG4zbHAce0hmm6MVFuoWuUeIhv4e3LgrNlW5o1xXxKDwAfgV0o+orbOhPTYPaHznvSB8l479D3u+TLB/Y2BMCN+7Z2Qcq7hrlS9xwNVslvBq4XAtNJdVUdBjkWeLaTJMI0fKThcv6vsvhTS0fHALDnE2W0uG+SVA0viZSbSGAViTmTdMTAt7iu3UvVTWExtNzqWeK4wjZ8VeoXlTNZ9SdrVVcziKbnbSnT+orcoUe+JYJlggpeGtbfB3fDhCo427n1qQINJniDG4uF6zGa3AdFCthsuI30GSZwxdWigLY6fZcajtwv6s8oZqPJtUuCdQP0/1AzF+Go7B5wLZqSh0CZ0gR5CeyyRMsPMOOwPe0H6jLHXETUbZlF12596KCgtkL0s0INkDHhfM26HLVAIOhW6HvOpenFHnxeKiN9zLYvd86Y0UXuuBDmgt0GxvNLpDnBnq5/CQs+QBXqFkEpj0h+eCx9VslF001fQtSxlox4NTHNx19HRUdqyxYUzbN26lTZt2kTd3d20fPnyhrG7nZ2d9PnPf56+9KUvUU9PD3V3d9OXv/xlWrNmTZx1dsopp9Cv/uqv0h/8wR/QP/zDPxBRLe3+8ssvP2YB1URqEHkxWHUv8vGI1hmCdRfm34mX0XDwae0QERWiG2pPCJlUEOARwtPZZwTVxlF72u8PHe2G+hhIOSGVhhll5ejJ3gNUFqrcojGTg6d9OxguloJDnSVcRozBG8pXAgXjjbrgGHQI/D2mM6cGa+Motbh9lDuhjAA8sItVKKkS4oOuNiapEjnTAsJK6Z60aRYXgplIgknECpcm6puyHgTjiDzrWVs0KOABHgJd5yvMKpX8YC9maRyhZx22rQ/Pq2tvQ+MSgtElFYXFNvadmKx/b9f6gJ2nJmA9Gj+J+nW4jAadtJ84gxBDkyp+o4qND84Ru96i6yyJaYP4oYAlUFr9CtxWnqIIj38j8rLQHapjR9Yi0mhYNgRT91d3udT3fS3u+bUzopvHxtzHFdp2WUi7b8+B7EkLZIBF6fGdeBIBGEpQFEqIWGCGbNmnJUFOXd8ci1iiacJPfvIT+shHPhL/32r2XXvttfToo482Fbv713/915RKpehTn/oUTUxM0Mc+9jF69NFHYw0iIqJvfvObdOONN8bZaFdccQX97d/+7TTN0g81iBQKhUKhOE6RCCd9uBzC9lPBRRddROYgXqVmYndzuRx9/etfp69//etim+7ubnrsscemNrijDDWIAJ1RlhnW3WoPal8ei6Co3yBzw0KBRwxmBq9EV+TxQF2hIaxUCl8bGEhd8Lhq0SuEwDFjtgSOzwYHoucmzWqWOet9DOeI2kgR57ELdJmwuCtqjuyHSFl0Xe+LNIwWpwfjdeiWxmBs9NgYoAly22vtRxf5A0dRiyQt6BCVyrZOnYP0HMAsHV8ToawVo1uMQLHEU5doMkFUERFPHQOVsQYa09IRxurxMonaQ54sOYQobyV4sNi2Hi+TOA6hTSyILPzOPHSC98mj0ciCfplXqNF+cH/CvCUBTlbcN/IuYfFfyE2gJGaZwX2eaIOEg4qHAoJl6T7C9fOyE3XrEOgtQhXs7qy7t9vm155TA+3OU4we3HkQ6F0CCrw747zh89L1lL9Uiw2BzzpvwHmD8FofjXbUMM2U2VyGGkSAdKJK6QRRu6dIK9JoPVhZGW4cVGxG+fgRUzNWCrDdSqB0cvAQHoAXCabM28ywAjNmsHArUCIN3N/MeAKFQJ/hQ8TLhVhjKg3rygmgpGDfCyCWCekxS0PiQ6fMLAe3+IGe7fHylp87QbY4SaTofzDhMUgJn0hW1JGX/IDtAjQmIYUZUuy9ZTcQaARNISuMGQ64Wvjai+0hNHYwfibpaTxpfaziIMylKfrMtm0mO036cvUZZh5KjUjOmLNGhJS5JxlYaLTaWxQNSxTUDIX+2Hyj8TG2Bs8tjk8wFvFYWzY5AIaoCunpuB/MjKwm3A8mX6kbM9poLFuv7HaO1PJosmaRdWXds5LdIwY/Dv0lQirRCe7OguEDBzUP8Y9tQJe/O+akOIqR4XVii6tIjxYuPhfRiMGx+ugxfH6z4r/RQWv0jFXMTKhBpFAoFArF8QpD8gdXs9srmoIaRICVqRFqTyVZEPFI5M1gZTJgeXvFFSbEwOssUFu2hhgTQQzd18/q9Dhsh8HYbmzWM9MNwcf4lYJ1wTAY2+faRR0i/BJCTxD2/U5lPvSdZHOqLUMtJfhERQ8QBjTaNjhO3K4VRHNOaXFZJMtWuK/AnenacTfg/kdaixVxFQIg7RevYXUm3GIZCmiWxoF+gKBp6yFiYnwY3IuCfFgstsFDSswmkzLEomUWAIw1sFCUVuo75H8PNiYx0NsDMYZhKtsJbQVt0nheKDjIsgZBpypZwYy/+j5SE+CBgSdmUjjW2MauR9aW0WGowcOCp2HZQ+kF/hhi7lmCCGUDelhhVA/R5NGrDGVl0HOE9QFT9ZlX41A7TfLEhtAh1jXLp2rPWfQgSXXPxoEjRC/S5uGaGC5S6+/LO6VjfOZ2p5yHHj3tu4q1DFh85mF/KUiYsBmyoXjhHXkcqdIdisZQgwiwq9JKrZUk9cDTpjddu2lRyPWloqNuXp9YGi93wnbVJFBmEUWFaebVAFzKxvHg4wI3bY0wFEFEY8aXTVbbDjPHrDBj2bsdpvEjxcXHUesvAO6gDCm7vMI9xCdBUdp8lJvNjCSDIpMuXguzz9L4MO2oueonRt2bPpPyP6TwQYfxRJYeK1f8D0KsQ9beiSn98HKJ6LYy0GgsJglOZ3UczkuhPtOLKToLL1sWm+OhvrAPVILOSPQZjrU++1+m7hrF9Ei0W4MsOT4g4XchpoqFilkDUTAgedYX9Oc1SvwGE7YtQ/HZhKfenPEzwuyYMkkCFMz0CFQyo6sJiQNTxD1FqfuYdp/HgwB9AG3MCsp6ZC0wCw37RgMGjaZKWN8Hon/CfWBif+++4aQ4wqj48/Bi91x8K+dKQvTmXUbaOZ1b42Uu3lib+xh8NSThRkt7lqtN1IBUzDyoQaRQKBQKxfEKDaqeNqhB5AHq+BSiKMt2+Nx6f9a5ZF+bcBWEJe0K647GwGykk/YknYcIPRRlz6e8DdAmIuoNXNAyfvH0s+Bu+FKLxodeIfx9AQR9Y3/7q87VYLPIMKAb54JeIcw4W5I4EC9begyP3QiWEIEyB91Jv8aR9czg1+xo0Z23zhZ/sCcGUNv1RvhkxwBrLO+BlEIyouYSyGVVGefgtmPBtPXifezLHNN+kD5pEHgteW7KUN6PaXFOwTMj1jXzLE/JE0QCPSZtx/SJjL/NFIDHLCjVdxKUwKvR4q+HhiKYmFhgbzVGqTWhoyR5s2K9KWjKpKTQYwa0GlJpYUTdYuBzNcBngkMFeMFs2nUyXqrdw3nwhhUguQL1ifD+GyW3gaWsS4Kn6AB4iIoQ3G0yru+WbbVxjOxwdSSHILB8S6+7kfpWuZvg8t7X6saHdF0WnvfoIbL13BrVdTuiMCQnIDS7vaIpqEEEKFOSyhSwl/qSKCsiD5RPZ9K9vC9udzfW/xs+09tvZ0T7oOGws9Ttbbs6U1/fhYioK6LbWoHuysMNjFIAWMQVabCxyBDBGxxT3NGgY3FIMO50lLqEdcgw/keKLcJ95qK3PXL6CCyeizXVVra7ArvWWHl31D0IWUYM1EFCow8Nm2psEEHGSaXeYKo1gpccvpBtkpmnRhoRURKy4BJY8MyXcoa7a0CZEE0yjnwefCGbTEo5923nFV0kmlLRn6aMI88cWexDU8ZR/b7F49hM9l8cl+VWosFUzfjXM9rSqjAjRYe7EI6jpMYdCz1KlxIA69f5RC4TrKaaO1CVTtg3FDXG+ysbcbDWMCLi90AnpMxLwqi+LM+xkntejU64ZwwaY4lS/cFkDBYYRLku9/zIBX69A5uphnFUaBBJMYjTBY0hmj5oLTOFQqFQKBRzHuohAswPxqktSLJaZUH0dTAS4joXHH1u1gUUt3b+JF7+t+FfipfzkXdn84Sr4ovU2HyocI/6RCOQdrIripBFfSAUf0QgJYZZZpbCwuBu1B5CrxBSZgsDNz6bzYZZGkiNjcOXJuodoYfIrkcPEh6PceO+DLsS7kvzV+c5b9zL2RVERDRcdPsYHXfbsSwzJlbnljNRFC5+oTIPkVBRnKM27qRQugOrnLOtMPsson0Y44oeJ+GzhWn9BPXreOP6trV9e8aG3gfsgpUs8fftFVWUvDjCens8RHpN8u74vEhC7GuiiVpUtg+WFQYZaeiBkYKt7X7Qm4T6UGFKOM/Q3BdgjwwtngsMtvaVMiFy9Bk/jvVB10RE1TTUTIMaftZbhB5X1O0aKztPz0QZtNPgvvR5iBCVIowD7svkAuf1KUcO4uqQ218CvLKLWt3z4wPd2+JlpOiLYf1zFAOsA/CS2edYM+KPRwyGDjOG6IiNZNZDDSLArkon5SsBfSDr4l06ouKuE6AsvaeKxV0d5bQK0lK/Mv/1eLkYbZuELAfEgRCLnLoHUx6CVZZFgR974EaW4o3Q4Okg9/AYjDLH0EjCmCQJ+6G4q6UTkTJDo0qqB9QNtdasanV/rK5ItADqE2EMxgjspxtinE5r2UlERBvzEIc05uYiPWQR9vhlID0JxezwHRFCf4x2i9YnphjAIqpF233gC1uwy9gebfo/GjuY0o3ifkJ/vimI6f9SbTHP781QZujW92Y0NzCeJDRFk7H9eGKSmOHpl05I4vHAuCZP0V1m7MB5QcMnTAPt6hurcA5Zf1hrDWOIokuZ2V9oVMG+Mbu2OAaZoLlahwEYQRNFP32G8hUVOFDxB4lJetuysLwC6h24QbW01Z51E6Bui7d+awbrMLrxVTC7NjJ+WlOuLRpJZc8HpipVz04oZaZQKBQKhWLOQz1EgIFqK01UUvRUuSteZ70tF7bsitfNBw0hpNJCLGdRdZ9knVHzPVU/RZTDrz2w5lmgNNlsN9T/ceMYx+BpWMag6a5kzX2MdFcjEUciomWp/fGy3bYLPD7oQVqSdt411DLCvu3c88A5oPeHl0lx+0HHQUdUw6ArA2VWwK1ehs9tpM+YzlD0l9U6w1pVSOMJwaP2izaUeCb4mmWHl915NlK2fhUbKE32tiCXY6KmsA7pE8FblPTQPgnJKySVzJB0kuIGnnWT16MXxo5DmDfLLJNKmdjA4arH4zNpf02VGfEMWRyTL16eBUmD96fsvz7Qu+O7LZkOEY4ZsxqFAHy7iMNE9r3SCnMZgewuqCVYia43eJRQAH0USrAdlsOBfdpLD72vJeYhgvsW70vwStm+U3ug9iIIae7rdRmyA+1uGTPKWqLEGfQaYZmSiSpqpNW2KzVBuR4xhCR6BJveXtEU1CACFE2akiYVZ4UROYpoG3DKaJSk4e2BxVtBp40GIjoD0+EHYBljfk4Ag2JNxhkJO6IHBZZEamepoc5wWEBuOY90VlyHBwQisQgqjL8Vxj8IsTRlg/ReDStTg/EyPOsJnxnY90j0NO8DQwrrx40DTdYPbdC4s+n4+wog3lZ2D9YDY84YW9jujiOmGluROJYNJxSC9dFkRNK7Hl9y8HLBl5jnIcWUrJso6Io/xC9QlAeAuBEUgsRioHg6bR0vyUBg5eYaFIjl44TFKTycJQMGaSuk2hJMYLE+DokZCMJHSNLTRsxCg3s/AbFF7CYwvn37jSdG6SFXBfuxhhA3TjHN3z9YVkvNrhNkFFJjuD/MNoVtozR9w+Ls4AQIbxakxNJRGzSCqp7Cs0Q8jqc85iaT3FkzVloO1G1CRETFjS6b95Vz3fh+ocup3ndHlQIm4CDhhwU+Iy3dX2wqvvDIQLPMpg9KmSkUCoVCoZjzUA8RIEmGuUqJiHpTQ0REtAwC7sagyUDVfW4vAXW2AfiC+FmpJiWPFNK2oqsPtig9FC+fmnbBxQPwSdYVpYmUWcAx6O6gtwDaDDBtoZr9izXL0vDpiv31MXHK+i+nEugNoUcHg60lHSIbhP32hCuB8rEOF4SOfSB6gFazZUvykJVnWIYY1Djz0HVEzhtUEahCrpnCCAbYT+R1ww3RIyJkA3m9PlKZCdFT4tknthVorZRztPHAW+v4xHEIXpVGxb5F704T+jm+7XiQOXhmhEBpX0C05AkSA73tPtHjw+YteIXAuxPXUkOPQsYfuC95i3A/9nZl50Kg2kSBzcjDhl6rEtxyKNxZRW8iBpQn6qliVPkxkCEbQEkdHDeWAol/Fy6sSgGoNKDxspE0WVq4pgPnCKI9b7tn7tgK93y7YOk7dfvDxA4sMYL6RNMGDaqeNqhBBEgnKpRO8BevFUTcC/E/nXBToBHUmYBUdGhzQkQplYwzdhAXtLjss20VfxZZxtRTOSXgMDBFHIu3ssKrkWEDzw4RSONh7TNbJw0pLqSyBsO8dz1ms9n+FqSc0rYENMbQULJ9XDh/c7zuzV3OwMLjgYZNCsTZ7PGVjEkEZtKFINJpU43xQV6FGAfWn5Bp5A80aRwL4kOyBNIJQIcx5WvYDaaOeyEZPixuBZaPwLM3VmOWDEjhAe/LiEtK1CMzPg4ek2SQlmuCKTGYSu8ZahKUr9GQEo1MD+XIaLIQDTDXlmWcgcxDmKq1L4EUQBo0UuERNMmQhms86g8V13Ef1Rb/RYFZab4MTaTGsKAywtYvIyIKs7U+PEx+3VwyB+CDaXm9wSMZQSF81bSY2g0jPSeOCtQgmjYoZaZQKBQKhWLOQz1EHvSAZ6MvCn62GVpELjiZiGgIPEd9YF++UVwZL1sP0I6KCxBenXH10F4tOcFGrBGWRmom2icrgQGeG/QKDYMnJYQxWa8PBgzidklwYYRwaaB3x2aL7Q2dhhCW9hgHqm0PddZth3P42cTieN37W7fHyysze+PlvRW3HwxEX5mu+cJXZfvjdWcud5mAr+x0FbElN3wpOneMJmW0kOCJYOxNfRsUZkyw6GnkNjyBsCjGmIGv/hK6CMi7bIO3q1CyJD3ir7uVbBDYLGkPIY5EKaeET/OnGQhtp9KH5C1iOkR2jgF6VyBDrOQ/CCwg2rZllezB+1eGPtICleYLwAevEI4JMxmQ5cVstnJbRJ0PQ6IAeIskgUiEHR+jbSHDjdHXmFjgqwkofJYHmSq0hUQFoBzDVM2LVHKPCSr0uLaVbnfgs53OjbSgzbnEbLbuOCTOoAcon8LM3tqEK76siKMF9RBNG9QgAixNHaDWdMCoqPaIMsOMrr1YiJQVVXUGTx7EETeX5xERf/Gi4ZNLuBtuGOKMfCnzmPGAStB7IdUe+/PF7hTAYEJjpuBLRaHJKtO18aHhI9Uy433UF4NdnoV0fuhjPxg+mI7/8sTKeHlZurYt1p1bnne1zt5IOyNzAmow5TDmqIHbWyroyuKTojgIpmot1DUTY2nsywWNFiHFXTKIvC8uyXiSQmI8YIcI0+sPMZRCFkQ8+L59DGP9Bg0MrCbeCzxOJvoDBk4Ay1yksfmXDqpdM4BxlBC4Od8li015nTp/3FVQsJwk/Cxk8YkZgvaaRXoQhSUDv3GHdY+TET3GLm+BPmMGERzryhm1gCdMxQ/gnmvNQu3HjFtuSbvl0XLtOTpegew1DFcAmn2iGhlgHqP3qEHT7qcNahApFAqFQnGcQtPupw9qEAHakkVqSybppcKKeN2K9L66dhjoi7QWrkePh/ViFMCLMw5RgEhVrUw7r0kf0EU2K+3EjKOIMLC5N+ECtsewzpjHg4WB1kipoScI59KTHKtbn4UvTtTuwcBnDE7PQVTv3og6xKy7MgSNj1Td+gyMCWu+xRL6MP4OCHDHukrNBML6kGyCg7GlPljJD+mLjEnE1H+9c/E+f1tJI8jnOSjOhxpMQ+g68A8vTlSTGDrwCkltYu0e7Hiqz2PbvomsthADg8fx4Exxn75hxIfM7SM1Dp5OKBfRMHuuifEk0fuEGYJ4HCJajdF1GL8M3h1OfYLnpWSiffi9l4gEJidgxpnHq8n6g0BkrIdGZaRxaztFego9PYzJDvwDxCDtyWMj4gkV6GUqVNyrr1StF9VKAa88XnHPbUt3lqdTmFExbVCDCFA0KUqZpJdmGgD1ZEw5z8BbghVNBSPHGgNpeOnjdrg/FoNTcTE4dp8YU7M6sydeRtHHDjCUENZAaYXYo/2QFYaxU0gbDoKBYg29Mku7d2PG9XuNoxDRwBqNKMehiuv3BKgftwAMnwWBy0Sret6KmPKP8gXZtDu++HDLptz6YqX5yx8/sqpYLNbWEMNsGxCaM6gczAq61r+MUMRRsjjYY7iBwcYUkVGRGgUW0cjx7Q93IcgCTMmdL8XuTKEPZktW/EaQS7tv4sXFLDrP70jRtPgVKbmq9pF9WTJDyS6j9AAeAsyYk46pTbuXKEbBEDVIu3nifphxBIcpGHX3WZjDOMVod2AwhWCcBGmoMSgINtrHFBo7aUjzR5V6NI5KIM0deILq8GOoAtuFyYgi11pmsxJqECkUCoVCcbwiNIenZ6HerKahBhGgYFIUmIDRPjvKPURE1AvlKTC7CzO2pOBi6xlCz00feH/2QvYZejnyWCIk6gM9Le+UF8TL6J3C4O7Qk8KxH7xXqK/zdnlhvIxUlS2TQeRKi+AxQk8WfoUNgVcNj00+EshJJ5xnCek/HsTtAsfXZJ1HbHO5JsmPQdftkAlYZTpE7qsT3eP2y5C57IVnBwozGubij7K7IBNM8gqJ8GbbCPSP5M2w8wVqIRgVsswwINoTNC2VuGDZdcJQfZCq2kuwY2XihAnJbYVtGoxJ+l0QVfTtm9UsE4KjE1V0F3k4RDy1LEPMP1b0zNiAbJapJtZRk1LEokaBf1BMm0q69uJMAGia8vxORJU8NKpgJ1H5jxJcpym4z+AexoyzwEOr8aQHvycLLxu85xPRMnqFJG2yZHRzJI9EmqXiuIMaRIDt5fnUUkqxGBtr/LBsLLjz0TDAFzK+4K3RNAwvdzRskCLitNsEtM/U7Q8NM0xrL5j6+CUG4PfR9YtGEGaF/RwMJR9w311QBw4NmwMVV1hxNFJLawPlwIGq+x3T7jHrjmjQjalYGxMWk0Wc1O1iv17b4wQbTYNgD18aPRFRCuKkUp7ikklw+7PMMozpQEPJtxPJVmimbpIdN76LMVMNaTLhWR4LMzdjgElxSDFV5f+dvdzxy3UqWWa4P8F4m0r2nFirrJHtxoraglHCvsjr39isFhvSYQn/eh9VKZ4j1lQw2HznKOWfOGY7piaghW2O8yp6fp80QEarWZFJLEKMG6aEewqLE0eTwfs2KXy84McrrrfLAUw2A8sdUEB6ca5G4RerqHR6lKGU2bRBDSKFQqFQKI5bHKZBdCQyDOYI1CAC2NId6KWxrtFB8GBgcO/WovOevC+3O17OBe4LwuoPIT2FOkVIr6G3Bdtb7xPT8xHaYq0yXyDy/ooLwG4P3GcfeosKBJl04GroCUbq1mG2GO5vT9lRadh+XrqWtTZUcZRajtzxwmy8jiSOz83BHjM8Lz0pR5+l4AuPucenwMUzakwoP2ArdRvBi5OAr1xGzUCQaOyxYW586ATdARIFZ1ej4CPQD/h1LJXdsLth1JhErwl6k/GlJ7FaBj0iuN6zLLl5mjiF8aVsBK+LhEb0mQQhTsOV2gAPEnru8BhI8/VQaRL1iIH0rI5eov78Mw8S1oQj/zHDy9CWdkRRyABzOdDBxTSrgMqOMgRDECENW2CykLnJSs/BPZWMAq8DQfyxGVidoa6sm0BbCt8Brr8f9a8kIqLKmFArRDGjoQYRIE0hZRJV6oA7O5+oXfjvVebF6zAe5sK2n8XLCwKXnr7fkzq+P3QvbzSC0ADLMMHGehXpAG5OVssM1afBiEBjxSpVYwp8yBSkBbU9GGt/lOXmO0ZExF5iqCK9s9TjxhRlmbVDHyMgdjkMyzuq3fHyEqh99sH8FiIienb01HgdGnf7Cu5Y5zJ+97Z90DVTlwhjo3xIwAM5yEDKP2SwhKz4LNJnUaYaGgvYd9VvzPjjZODlAinpwPixGleBx7DB3/ElyAuO+scxpbT7hLDcgHZjXUi1yg4VTMyw+XEwQwpjemw8EZ5v4CwNChiyg90g/kei4PAawn0ijRRNTDxHFTQu/H1TdOticehKzn9CpcLC9noqA52bKMN2aNGBcVTCj4no2y7f4gKfklIgoIByFGO4vwAxj2konA0HJ5+u7aeSblQE8AhCKbNpgxpECoVCoVAcrwgNHRbtpVlmTUMNIsDbxV7KptN0Vn5bvM5mOWGgNQbyYvC0zytExOmiuF/wgnSBZykpXPitUcZZQSiNgbXW0MXbnsTA5TxNRlUoJMRLcDjPkT0eeytY5qOdfBhjJULcl9+KbC3geRDGMwBB10UICn924OR4GTWHPtL2JhER9Zfcvuel3HH8hXYXVL2133mn5rUgBXdwzxB63dBDhLoltkUaNFPwDKJ+Cn7wco7I/hE4JFbvwOOOwZ0iVVH0f6WjVwWrtVjHYTNeFwzSPmQvjTCVOF6XxSZj0HLzfScaBG43Oz7vz+g9gcZIW4WRkGIw4fe+8gwyv+eIZblFHqcQ6p4lC6C10+LuW3HutjvB6YnbmSR4Y4L6+yVVaHxQKy0wR2Sa7DmC67uSh3suh95OOP8g7lgZrD0TCpBd2ZJ13puUR7iRiGehJuyNCfc1F26s1yyqVCV3qWImQw0iwAfy71Bra8Coqv1RjAoqVmcE7oDHCDma5uflmso0GgDdEO8SCGnwVU8QBbqoxyCdHFPmsQYayzjzxENh3TMExvEgpWelADCjDsfMY63cgwsz4qzMQFGonYY4uc0VwX1zzGWLWVHHfSUXD3UiiOa1QUFGpKrGSm5ebdnm4wDQCBoad8as73XAYo/AgAnhPCfhzgstZ4Dvr9BvBDFBR99bDmNmMANLUD5mYUHRMAIUa5QEroW+3Zj9wzTkNyK8go2+uKIm0aj9kaDXpDgeZutGMTgshoelzAtGEPYBbWxcU4LRa26RGVVCplcsZijESDWjYB2n/2MMkSD+mR10nVSzYCxGj1FUKWDfBGAoof0RFOovyhKIvJIrY8jocmYcofCiVZvHGoWJALZzO89GN0cQCOEFRwMmlFNDm91e0RTUIFIoFAqF4niFxhBNG9QgAqQTVUonOC1lKTGkT5Am2wslM/LgbdkLnhIbEI0igkjBIU2G65HO2hsJCiI1hl6XE1KOxkOvEH7h2WBw9Aq1C2U+0AOAQeR2WywhgsAyHj6qkMh5mVB4MgseNTxO6RbXx8/H58fLOwu1IHesM9SbGoqXP9rqgt2/mz8lXq4eouQ+utDRA1SaqB2bFAjHNZXlwuJPTd06pM/E55m39LmQzcTouoN3YQTvDkneIs9+JO+UFJjta8+oMZ8HiYgfHM9xasoT1CjGookXSpgCStVDp5i03/vD6DCods9EEzFQOlNfOgSFIJt69cVZjbALIYibHb9q/bFOCNdVCurKBTCXEJyyhXm19Rknw0YhaB1hcH8VArYh2iAWfUwW3UDKBX9ZDrwvseab9RCFQt2zJLhzUwlLmflLuBwVaAzRtEENIsBo2EJhGDA6yNb3wowuRG/g7maM3cmARbHfijsK4omI/aAyvaXgfL9WwboXlKyTPtFF4urUJTCwLDWH8UGomI1UIBOiZNRWjbNHmgwNGMQAGIsDkOqfT9ZTVfvKbt7L0gPxMqp4o5SBpQ4xPfa9sssExDpvpy10yztH3Xx9YEJusFyG+mQVT10ljBVC4wiviSrWOMMYhij+gT22qoLVgo0EqiFuipesVBXW9x7E6flrbcpFZpP8L5Gcum8Y1wMvoOjwJab4IJ8SDdZEbFHDIq2oqBAKtERkaEgxXMzYSfmNdTSmYppLMmbQeEsmCRxOiwAAJpZJREFUveuDidoBRsoP481CKFpbyaGiJwzKxr2xaUMDNOjwOJUgY2tPRLtBNiQaQRWg16TrLYjoPWT5ShBjxOqXlfGjplrXpgKZbHhbZIF2swaW8dQ/U8x8qEGkUCgUCsXxCqXMpg1qEAFKJqCUCSgNHMBY5MkJ4OtnxLgAPsziKkA2Apa7QGrLAj0w6JFCLSAMvLYeJfSYoBcEA7BZAHPVUVs2qBs9S0XBU4XeItQtskBqDOkz9BxhJh2Oz7ZBz9NE1S3vB8/SgbKjHlvAQ3SgVJvL/IzLLONil+7L9g8Xfz9e/j+bfz1ett4gieIahwDs8Qm3XBlzyzZeMci784ZBmOhxwurdCcxEirxLxuuumZxtJXiLPFOotPq/YoNxf+C1vSSZMKMkh4O10TyUmSg4KH1Ye7xMGLArZTOJXqFGL4EpCDBK+5hKXTZ5nXAusAXzBEYeJ4mxaabmWzT3EI4By4wDT5WYZej7XaDXMHgbz6ndJ/4eCJQq8yK5249K8yKPTRr2B8KNYdVzYZH/nmcsNvyO9/B4ubbzSnkajQxDh2kQHbGRzHqoQQRYld5HbekktaIgYnQvpOGqCgkEBcHH+3zhF+Plb793Zrz8vs6aQOE57VvjdWj4IMWFhkgn1AWzRgn+joYNZp9hQVRsY6ktpOs6Em4uqDKN8T+Y7m6Vu/PwUEfDBjPpMDutO+kMF2tMoaGFxg6KU57btiVe/sf3PkyTkco5sUaJhsRjtjDvjEwrxJaCY1SGzL2xgnvy4nsm0+HmlU7V+paKQeLTCNsgAxsLMqIonZTKnhCsFUvBedL5Jw2DpTADc+CyerAtijSK1Ff9arF2Gssiwj7qJQfY8IU4pKnULxMhJe41aiv20YRF6YGRBAV9Rk4Tho8smRAZVdwCgGVs3GBMSD2iSjZSrZ50fSKK9V6xUC2y8yj0WIG4IV9yKqpX48SYGCq0R7V5n3GERhBSaWPF2jOhWlIrYzZCDSLA7kon5SsBq0pvvS0/Ky2O16GxgBpCmD5/8aK34mUbPMzT190yGkSo3eOrVI+G1EDoPClo+KCHCJWq0RNlgQYMFmZFo2SEXB/pSJNoBJ5K6C3CfaNBh8emPaoSiW3xmK7OuFR7RHfWHets9HZGzxKiJHxCL8g5g2jzvlqQdku2caHGSglS+tvd9eF7mLJKFoLWEfsCtcZMMxU7SWjie6jX2xj1wDCTuNyFfx9oPDH7xVOw09svkVjyI+ExmkTPjBBb5JuvZDCJR5p5s0x9H0zDCTwOqN0DKduxF6mJubBCr0I8UbJUOwmYoo/jmIqhhMc3TIMxLlx6Pm9QEyLvYvmP2DADj08VPEEYPM0KwMJ1mCzZ9qDaj2NCwweFrzFeyGOIJgUPkY0lrHriCI8alDKbNqhBpFAoFArF8YowJJlrbnZ7RTNQgwhwamYftWeSLEFiRyT49ZORVfG6JHwmrmndGS+vyDjxxoAJKNa8PmETKd+SSOOQR2UaqSCki5DiQq+QXZ9kApJQxBD2XRJqrVmPR296MF7HvFowR6Z2DR6ncsTDDBo3J/RUYeYbCj2uaHHZZ9ajhHPpL7lYpvGsP/1/fsZ5iHKZ2pgk93gIy7k81kqqf8AY4VMZ17MEpaovuET6NMcNBZeHx7vTjKIzZhf5+mVOAeFpwRgij0NEjHfBXTLGw1I6fvqPFTD11R4jcp4SkfKB5aRw3OP0dGEcUh+NKDiBQjRJ/4HCOYZR2r0RxsxVpoVrssFjiCmPM6+Vx4uEh6bib8v6g9ibMOVxM2F/SOcCXcsEIAvRtZLyn2cmcCpkfAYpm9boHQZXnjgiBfMUxyvUIAKMmoDIJKkdgqrfKJ5ARDwoGJ8nqCHUC8VH+yDQ2BoJY55YHCKiESj5gXpHWaCUrFL2yxMr43W/mHXUEhpHqD2NhpI1fpCKkyidUEi7t8HgA2VH1+G8MJgZDRE09OxDBak2VK3eQa7UBhpjq7J768aJY3tn3AWyY9B6El5ol3VsipcHF9WO++bhBfG6vmE4b2C0YPgMKt7aWAR8Z2IMkRGX66bCCsEi7SKCBxexP5MHzRSu4QIOs0BnlOqvBUYRCUVhmcFj6Rjhdx81NrlN0r40BSOIoEyD+PK27VmclRRk7B+f00NqTEOJ1FxsmMHvqF4OPI5YwZ4VhvVQo/gF1yBAHMckxfZ4DW2iSca2OWgfnGb0xxlZBBigDD+DogYVO+HewevNni8Ink5UoC1QgfghEwglPeJuBSPNZvE3UxD6iEEps2mDGkQKhUKhUByvUINo2qAGEaA7GVJ7kujbo66g6FvjtfpZFcg+aku7Txektcrgi+7wKED70teJiFZmnOdDEm8cNzUvzFkt78br0JuE3piywFFYb1aZiUz6L4F8Amgy+MoeAworHgeMGZcDIcDaep8wcLuQcHP9v7vWxssXLnRZZifldtftG49pEWQP+spd8XIPyBegx8nWO/uF9v2uP6hRNNDiaLz9w27evkBqFIBDEUcpmFai2OJ9gBdELO7KNojWV/xfynJ6ulsMo9RllAQAMXFv3bO6Idk6WRg8ywJp/fvmVFQ9HyN6YDBDCa7T1HjtfqhmoThp0n88+KnwZYg1Eexu/GP1D1rwygrj81FwrLAsesYkrw/uxwZsNyMbAMHdPCvN/i5Qd3h8oQ1mlNnjyx+LbsMyFoWFNrhL62RmdB6OOevPJmM1BqOJMU+cUCtOMbuhBhHgzVIHtZYCen9uW91vqKScD9xLFTOl0JjxqUhj5hNSXJgJhvBRUSWIM0Aaqq/SFS//AugTsbIg0duqLASDoCGFlBkaHemwUvc7GjtSfxjXZIG0Fo5pcd6pf++F4q1ELtOvPagZnLtLLt7orQOOMkuBOM6vdb/iHd/CdI3iHCy747+s9UC8fGKbM5S25FzZkP3jzjgqRRL+ITxMq2U3b5Y+7xcOjh/ERkoLg/iIRu+wRNn/UpXKeGABTZv2bQLhBcvylnH8sD7aFA2mhNRFgxeNqGUkxOj4ss+QjsEMJkEZYVLquKlbZ4SCtIkpvDX5vn0GmNzGq1UlbdegDRsz7kOKh/LQXVLqvs94qlsf7ZPRnmjoMTrUv2wN9mQa18G9WIBSSCk0jlz7+N7FwsjG3zY2BMPmz/dhQ0t3TBvUIFIoFAqF4jiFMSGZw6hYfzjbzjWoQeRBO/AEa7I7iIhoR+ACfTGQF4OjkeJCKs16U3C7cXIeE5+SdW29G0cQnSoWPA0emGVp581AbxGqRS/LDNT1W2UaSM7zkYaI3IJHCa3Kssn8BWkxUBr1k2wbpNcwaH20DAVbc0PxMqstFu3zf/pOjNftH3Lj39fqPEs4flTBfl9Ewb097mrGISZgu66My9YbKblzF3uIJBqk4ueIkql6V76RPquxKGUjTwR4k8RCqlV/H8mIYgvRI9Ug4JjIn30mKhjjasEREf9H8OJIAdb43K/magNMVvweHZH58npE/F4cRlVJHifbVqLosD/pQ97nefHH/Mpz9PTNs8aaoBN9np4mvFNN6Rr5fhfe495rEuO2wUNkCvCMSUGNtoPvmhJAgfuotLDkD0s4KjDm8Lw8GkPUNNQgAgSJkIJEglW7HwxrcSR7yo6aQSMD6bMCVFvvCOpjiHAdZnchJTXmoZaInEGBRhAaUkhhvQfxM2+PuZd9sqN2Y/SmBr37QMOhDFlOvqr1gfC0Gq/6M84Q1ohEIwjb5lNwPKC/eWlHze0qdtXGDAUbq0WgJAM/JYnik11R4d5WOIcIjANrT7nlvnFHn9p4IYkF4W9yeFDjsn3ghp51kyG88OJkJjBmQoFGaGSgJFExmxlHaAz4+3BtYWyCoCPLYPJMlyX64KWE/TEBSORBGtBnaTx49fsmgsOE/Rr/CWAvd8++RSqrCeMD4TMApDgekiQJbOkO6Z0uxlfhQBL1v0vUmFj/5eAvanZMMTMS6dpoPcYY8fgruJYDoLJZqrDNaoQNWWHkgw5TMYugBpFCoVAoFMcrzGHGEKmHqGmoQQRoTZSpNVGlvUCrvDKxnIiItow7rRrMOJufdRlMUv0vux7FDKsG63+1wnr/50gQfb0g9YTArLDTcygWCRlUEVUWwJcQCiKyrDUIf8XyJJYqw/mV4HOKiT5iFhnWGbN9gPcHPW1taeeN2V90xwY9OaVIFKdQgn4hgHLrYHe8PNSF5Uvqa62dmn8vXvezCRe4jV43PLfL2wbjZXs89gw5rxECqbEQg61B4ygZCcOF6AbBIFL0HAX+h1v8zAsF746gSYRf1rHOEDpPUNNFKrWBsJ4qoXSHSIN4vAvM6yZSd/5jkzD1XpDMKNC2nf5Hn9fjwQK3cX/Qlnlj6u9h0YPUhOdI9LwcZB0RzxZk+7TLTWgI8Q7r6THmaRHoM7Gmmh2fVGLEE6xf30ntD17HUsgMFpatJmHgUXYl1pIzEqcWnf9wooGL9EgiDA9ywzUBjSFqGmoQAaqUoColWMq2pWYGS+5FmhIuTqRjTs26l6w1sDArTKLGMEYIjRUbd4M0GaaqY9V6fHmjErXtowz8+N6Ke5H3lbri5RaIo8J0d0vvoYEzUHEGZFoyggC2TTtQiEhDtoEU7XDCGTP9RTfWXFQMdkmXoym3Drpjmk35n2hoDKap+YcaHtOlOZeJtq9QM9j2B85wM1DVHhVx5Yzt2g9Bxm1XqcCtyUQV4aXvqyGGNZigArhB4Tpgc/FSTkWXbwVE0VmmGovj8S+7MuiesdGkAgTwH/ZutlnhjKJDuguawmnGjDgT1mcwYQo+U39Gysn3UheDdBASrWZ3AsuCirMYJ4KrG6XmCcxoQ9aniSK0jSg9ieJk4WQeA4pljaHhDuc8wcQpoU1Y3y/LTkOFa1RlB4PI2DgzzDIDAysJHwX2kVUt6qtzNkLPqkKhUCgUxyuUMps2qEEEGKi2UqEa0M6So1uC6ELsgUrrqO2DHgeeeVWvsfPTwpJ4HWZgzU853R0MsMZlq2vU6vH4EBFloBQ50la+rDT03JyY6fcuI1AjqCNZX6keA6LbIRAZvWAjofMAWW+LzXojItoBx/wtCATvSLvsrgK4BsYrtb4Xt7pyKS2r3ZgwMDsHn4mYYWd1mXDe7xSclhHWLcqD1wq9RamoHEB7zp2XEcggrJSFyFXmbolWQWkBJszoT0KcHD0a9eX3JplkY3+BPY0Zd0gJKrRwLSNPYKsEDO5O+JPueBkyW1oKPQ5CCQlcz6qCWM8B6kO1gIAoeFowE43RJtaTw9xafk8QK0/iK/uATiisN4brpZpqAF+WmVh4C4fhq0OG3jDh+Dak6wTNIql0CxPStCKeTKzRH8QvBelbL6lUZw/HwQQg2X1S76lieRZwPKwju4mylEcMJgzJHAZlpmn3zUMNIkB/tYNaKimWQXVKa436OlBxlMh41aWF74GConvSbhkNF1usNA80FBoOuB4pp9AjXDgG1zYTTITtuJHmbnxbMw0NGDRaMkJ8EhqAPhoMx4+GD8tag31aY3B70UkZMOMO/OajZddfb869qUejc4C/Z0CMcbzil0bo8ohI4rlicUMkiG5Cf3Y/mHZfxcKtzdAt9r2L20kvPNZd/cuIUzBCPBEuI5UWHT4oMUcpZ49S1c/y8iHF9b9gZTMvSk+WEH/pSFlyGDfk1jqDB2UI/C/YZMF/gMNIyBFruCGlw4X8vKud0STIBrDUfdhM6i9e38RHf6NMLzFNXnrZ+2KIpmAY14+p9gcN5jCN+/DHa3lji4R3Ph5H/CZgVKtn3Cl4TFRAN7fcFqXdC8VkFTMbahApFAqFQnG8QimzaYMaRIDXx06gbCLNtG+G0rXPA6RJFgKncFKLqzgvCSxabxBmcaHXBbO4EOg1sX2Ps3IecPpQ+BCuf/TS2P1L4omo9dGedK4BFogc7YeLKvqzsbBe0O5CV7ycjT7PsvCZNlx1n2GYxYfH7O0Rl+nXEdWTs8HVRET5lPNUtUKp7HFweeA5slRaugl3NKMvMZMuouYwM1Gqdi+5fawwYwqCsUuC8BvLcmr0kGTlP2DPuMxohIN3xzJ5WBacWw59TxT8HaYFp8v7xc4oOj8zw7wtIQpf2t8ZfYVBum51Bag0KYMtXoeZbML4WHsPHYMTYM4JifrC1dYT2ERV+4aUGKMkG9NnjJbyePEwOJ0HT/uHZ9uwfUuB2Ww/btmyzEm/lBiFOA4hEcD2h55RTCxglK9HsuioIzSHt0M1iJqGGkSA9wpdlA4ybF1L9BZY3OIKsPaCAGN34NLukWrDDLEgygYrszvLtR2AlymPT4LCsYn6U4V0WMCMEvd2ybCir6mores3KxSc9ckGEBGNmFzdOgQaMCWsT5YZjJct7YY02ryEMwqHA0eD9RfcsekbcVlmw5lam/ktbrsKPOXOnufik0LBl28NoT7ItEuyY+OnEH39oRBkOQXZYklMtYcNPG9QLChpyvCSFl6UCXTb20WMPULDDOkiaMMuSVtsU1K4xuwdKSTJk5nF6A7JiMAMcXvZwCWPOqfNUDpVZxHF65KC+reUIt7I6BAz7Rq0RbB4GGwvhRNZQwSFJZvIBGT7rE+qOkiqvdDGYyyiocIy/gTjqGE8FG6GGYnF+vXNpOhjPBw7Zg0McJYNWYh+KEgHTDGToQaRQqFQKBTHK4whMUiq6e0VzUANIkBLUKJMQNQOwoArWvbV/machwgpJPSIDIKnBz0sNnAZPSLl0J+ZVcLgYk/FHfRgYABwFT55cjC+HFBflvYZBs0fHCd6pDCIGCknS49hcLUvYJqIe5GwTIedL7ZFHSL0zCD9VKm6/YxHdEsh4y7hoYKj3YJu8K4JJUQsloPHrw0+P9OChwgps47oWulPunMvFDAn/lkKi8m6VTxDLAM0TSC4A7xV0I3317DFnZeEp34Do3bxOSyV48Bd2uwuwevCvE8CDWJPF6PopFIKwiGwTlIvhUfEq6ozR5s/SDteJwSFT4WeQjBaiOnr+F9ivm4Y/ZP0z4t1bqkqwUPXyLNE5I4T0l14bg3sr5qpzyybvM/4d/RYoj4R0wXyjK3qP284l9QEjANpt2g/Bj1PwnVq82mqAkV3NGBCQ+YwKDOjBlHTmDUG0YMPPkh/9Vd/Rbt376bTTjuNHnjgAbrgggum1MdJrXso15ZmafArI0MoD+naaAz8vOTStNG46E4BlRYZMSieiLEsLMNKyPSyL/WkQI0hWJ00NHKicfDsNb+xgDEzXQmXcmH3WTDOSEJ6cAEcO8xgQ6PKHic0LBalXVzWHnLZeil4I6eAlspnynW/B7D81qhL3cfsNIwXssemDMerD7IGe9KOjmv31KYjIlrTvouIiHaMdsXrjMA/oGp1KltvUeBjK9UK18c4vCUEpepYsXfI3dKM0ml31woWiA1zWGQ2KoiK3aIoZBMfqfZF4hEmr3WBSYrw9AF7mFLRYceXFkufljKE2AGM/lbwJQj0Gd46SAV6aDUe1zKF1Phah/zv5N+zQvZcwr8+Gb34ZQkEfwabrz8x40+kzzxZZniNSUaVkGVo3/FVHqUQIzPsN3Iq2XqjT8zKg+OUKvvvHZ8BKIUVVqN9V0v+348KTEiH5yHStPtmMY1qCkcPTzzxBK1bt45uv/12evnll+mCCy6gj3/847R9+/ZjPTSFQqFQKBQzALPCQ/S1r32NPv/5z9Pv//7vExHRAw88QP/xH/9BDz30EN13331N9/OL2T2UzwVMl8bCVr0nItpS7I2X/+7VD8fLvd3OE/GRRZvj5e7okxc9Opghlk349W58niP03GBwdAk+8QoEFBekWdiMM/TooIeoyjgMtzhG9QI0uG/0ahXCep0ioklB2AlbuwvGBscD29psMiKi3fDl15WrUYEsCB08RKhJVARXQ1/FeYAyqQN14zyvfUu8/HbB1TVLCp+Mdn1Pi/Oi9Y/46TP0EKHoo80yS+BnLtNmgTIDof8c2c/i1DCID0IfMG0eUoBZUx5tmWoOvColPz3CPCxxFhT8LnkOGtBdoIXJMoBCwQPgCxIWvV2YkSbMxfjKWUienmbm6GkrUXpiLTA7JqQYJYoLx++ZSlP1xoQ2Xg8Rq0jvzxzzjlPwVJXb4HoTPHq+fQtMt5gUYB0oEk3JtJGC+nEebShlNn2Y8QZRqVSijRs30m233cbWX3LJJfT88897tykWi1Qsuhft8HDNkGlPTlBrMmDZUYNhTZBxS8FRMPiCPWvprnh5SctgvLwUVJitGCAaHGhQ4MuWixm6/VhDCNPhkfoqQXwN9jEOxpGlsJC+QkiZY2jw2GODAoyS3IBUy8xiFHgSNGzw+OKxacu6c2bT3XE7NDIw7X6s4gy6PZFIJhHRynTtHO2odMXrMINwe3K+d9wB7NMauefNeydeh3FPr+x06uQoQxAEB3djp+D3IhpBkC2GdFA8JOHFYKAtY08wjT8aH9JGUpgSUw6GJvGzV3oGSxlR0ElpXu1v5oDQtpnCsSH7U/udsX/+N70vW6kZY6FhmvnhZE03MKDk4q4Hb+MRSz/4OHA5jkNCo0WIe5LkBBrstNG8iVxsUTNFg5n9CsZPwtMWqcdKzi2PRxES0xlDpJTZ9GHGG0T79u2jarVKixYtYusXLVpEfX193m3uu+8++vM///O69eOjNYMAY0rGw9q6QtG99EtwM5XH3GdsseraTISQ+h59gmLgs2QQFWHfSHmHkbESwOcs6q7g/th28BgoRBGNhdD/BE3CG9Qw5Wv0RNm+kt62iGKDT0M8Xgk0iECxuVxwx7cy5p5CZVNbjwZRuYrjhPMFxsAEFH0drdTaj1egFAcUfC1MuD4MHBs0iCrR3Nl5g2siHIfYIzBykunmH1IhBIM2MoiqhVTdulofcKxxM1Sqth4gTPlnhTIT3vXMQ2QPnxTvPYUUcXzpNIofrxuTJ04m4RsnEZnq8W0QIXxjEQ0iweA8WF/NwmcQGTCIMImCJI9ZtMwuJeEcieegXL9vrFTPzhGsDz3eIEnZuwoeIntNhsXafT0d3pcKlQ/r+qmItX8UkzHjDSKLxCT3tjGmbp3Fn/7pn9LNN98c/3/Xrl106qmn0tW//I63vWL24HHv2t1C683C+kb4r0PcTqFQzCSMjIxQZ2dn44aHgEwmQ729vfTDvu8edl+9vb2UyQjR64oYM94gmj9/PgVBUOcN6u/vr/MaWWSzWcpmHY3S1tZGb7zxBp166qm0Y8cO6ujo8G430zE8PEzLli3TOc5gzPb5EekcZwNm+/yMMTQyMkJLlixp3PgQkcvlaOvWrVQqHX5KWyaToVwu17jhHMeMN4gymQytXbuWNmzYQL/xG78Rr9+wYQP9+q//elN9JJNJOuGEE4iIqKOjY1bewAid48zHbJ8fkc5xNmA2z+9oeYYQuVxODZlpxIw3iIiIbr75Zrr66qvp7LPPpvPOO48efvhh2r59O1133XXHemgKhUKhUChmAGaFQfTpT3+a9u/fT3fddRft3r2bTj/9dPrud79LK1asONZDUygUCoVCMQMwKwwiIqLrr7+err/++kPePpvN0h133MFii2YbdI4zH7N9fkQ6x9mA2T4/xexEwqhqk0KhUCgUijmOWVG6Q6FQKBQKheJwoAaRQqFQKBSKOQ81iBQKhUKhUMx5qEGkUCgUCoVizkMNoggPPvggrVq1inK5HK1du5Z+8IMfHOshHRLuu+8++sAHPkDt7e20cOFC+uQnP0lvvfUWa2OMoTvvvJOWLFlCLS0tdNFFF9Hrr79+jEZ8+LjvvvsokUjQunXr4nWzYY67du2iz372s9TT00P5fJ7e//7308aNG+PfZ/IcK5UKfeUrX6FVq1ZRS0sLnXjiiXTXXXdRCMWsZtr8/vu//5s+8YlP0JIlSyiRSNC3v/1t9nsz8ykWi/SFL3yB5s+fT62trXTFFVfQzp07p3EWB8fB5lgul+nWW2+lNWvWUGtrKy1ZsoSuueYaeu+991gfx/scFXMYRmEef/xxk06nzfr1680bb7xhbrrpJtPa2mq2bdt2rIc2ZVx66aXmkUceMa+99prZtGmTueyyy8zy5cvN6Oho3Ob+++837e3t5lvf+pZ59dVXzac//WmzePFiMzw8fAxHfmh48cUXzcqVK80ZZ5xhbrrppnj9TJ/jwMCAWbFihfnd3/1d88ILL5itW7eaZ555xmzZsiVuM5PnePfdd5uenh7z7//+72br1q3mX//1X01bW5t54IEH4jYzbX7f/e53ze23326+9a1vGSIy//Zv/8Z+b2Y+1113nTnhhBPMhg0bzEsvvWQ+8pGPmDPPPNNUKpVpno0fB5vj4OCgufjii80TTzxhfvazn5kf/ehH5oMf/KBZu3Yt6+N4n6Ni7kINImPMOeecY6677jq27uSTTza33XbbMRrRkUN/f78hIvPcc88ZY4wJw9D09vaa+++/P25TKBRMZ2en+fu///tjNcxDwsjIiFm9erXZsGGDufDCC2ODaDbM8dZbbzXnn3+++PtMn+Nll11mfu/3fo+t+83f/E3z2c9+1hgz8+c32VhoZj6Dg4MmnU6bxx9/PG6za9cuk0wmzdNPPz1tY28WPqNvMl588UVDRPHH5Uybo2JuYc5TZqVSiTZu3EiXXHIJW3/JJZfQ888/f4xGdeQwNDRERETd3d1ERLR161bq6+tj881ms3ThhRfOuPn+8R//MV122WV08cUXs/WzYY7f+c536Oyzz6bf/u3fpoULF9JZZ51F69evj3+f6XM8//zz6T//8z/p7bffJiKin/70p/TDH/6Qfu3Xfo2IZv78JqOZ+WzcuJHK5TJrs2TJEjr99NNn5JyJas+fRCJBXV1dRDQ756iYPZg1StWHin379lG1WqVFixax9YsWLaK+vr5jNKojA2MM3XzzzXT++efT6aefTkQUz8k3323btk37GA8Vjz/+OL300kv0v//7v3W/zYY5/vznP6eHHnqIbr75ZvqzP/szevHFF+nGG2+kbDZL11xzzYyf46233kpDQ0N08sknUxAEVK1W6Z577qErr7ySiGbHOUQ0M5++vj7KZDI0b968ujYz8VlUKBTotttuo6uuuiou8Drb5qiYXZjzBpFFIpFg/zfG1K2babjhhhvolVdeoR/+8Id1v83k+e7YsYNuuukm+t73vnfQStAzeY5hGNLZZ59N9957LxERnXXWWfT666/TQw89RNdcc03cbqbO8YknnqDHHnuM/uVf/oVOO+002rRpE61bt46WLFlC1157bdxups5PwqHMZybOuVwu02c+8xkKw5AefPDBhu1n4hwVsw9znjKbP38+BUFQ93XS399f9zU3k/CFL3yBvvOd79Czzz5LS5cujdf39vYSEc3o+W7cuJH6+/tp7dq1lEqlKJVK0XPPPUd/8zd/Q6lUKp7HTJ7j4sWL6dRTT2XrTjnlFNq+fTsRzfzz+Cd/8id022230Wc+8xlas2YNXX311fTFL36R7rvvPiKa+fObjGbm09vbS6VSiQ4cOCC2mQkol8v0qU99irZu3UobNmyIvUNEs2eOitmJOW8QZTIZWrt2LW3YsIGt37BhA33oQx86RqM6dBhj6IYbbqAnn3yS/uu//otWrVrFfl+1ahX19vay+ZZKJXruuedmzHw/9rGP0auvvkqbNm2K/5199tn0O7/zO7Rp0yY68cQTZ/wcf/mXf7lOLuHtt9+mFStWENHMP4/j4+OUTPLHTxAEcdr9TJ/fZDQzn7Vr11I6nWZtdu/eTa+99tqMmbM1hjZv3kzPPPMM9fT0sN9nwxwVsxjHKpr7eIJNu//GN75h3njjDbNu3TrT2tpq3n333WM9tCnjj/7oj0xnZ6f5/ve/b3bv3h3/Gx8fj9vcf//9prOz0zz55JPm1VdfNVdeeeVxnc7cDDDLzJiZP8cXX3zRpFIpc88995jNmzebb37zmyafz5vHHnssbjOT53jttdeaE044IU67f/LJJ838+fPNLbfcEreZafMbGRkxL7/8snn55ZcNEZmvfe1r5uWXX44zrJqZz3XXXWeWLl1qnnnmGfPSSy+Zj370o8dVSvrB5lgul80VV1xhli5dajZt2sSeP8ViMe7jeJ+jYu5CDaIIf/d3f2dWrFhhMpmM+aVf+qU4TX2mgYi8/x555JG4TRiG5o477jC9vb0mm82aD3/4w+bVV189doM+AphsEM2GOT711FPm9NNPN9ls1px88snm4YcfZr/P5DkODw+bm266ySxfvtzkcjlz4oknmttvv529OGfa/J599lnvvXfttdcaY5qbz8TEhLnhhhtMd3e3aWlpMZdffrnZvn37MZiNHweb49atW8Xnz7PPPhv3cbzPUTF3kTDGmOnzRykUCoVCoVAcf5jzMUQKhUKhUCgUahApFAqFQqGY81CDSKFQKBQKxZyHGkQKhUKhUCjmPNQgUigUCoVCMeehBpFCoVAoFIo5DzWIFAqFQqFQzHmoQaRQKBQKhWLOQw0ihUKhUCgUcx5qECkUCoVCoZjzUINIoVAoFArFnIcaRArFHMdFF11EN954I91yyy3U3d1Nvb29dOeddxIR0fe//33KZDL0gx/8IG7/1a9+lebPn0+7d+8+RiNWKBSKIw81iBQKBf3TP/0Ttba20gsvvEB/+Zd/SXfddRdt2LCBLrroIlq3bh1dffXVNDQ0RD/96U/p9ttvp/Xr19PixYuP9bAVCoXiiEGr3SsUcxwXXXQRVatV5gU655xz6KMf/Sjdf//9VCqV6Nxzz6XVq1fT66+/Tueddx6tX7/+GI5YoVAojjxSx3oACoXi2OOMM85g/1+8eDH19/cTEVEmk6HHHnuMzjjjDFqxYgU98MADx2CECoVCcXShlJlCoaB0Os3+n0gkKAzD+P/PP/88ERENDAzQwMDAtI5NoVAopgNqECkUioPinXfeoS9+8Yu0fv16Ovfcc+maa65hxpJCoVDMBqhBpFAoRFSrVbr66qvpkksuoc997nP0yCOP0GuvvUZf/epXj/XQFAqF4ohCDSKFQiHinnvuoXfffZcefvhhIiLq7e2lf/zHf6SvfOUrtGnTpmM7OIVCoTiC0CwzhUKhUCgUcx7qIVIoFAqFQjHnoQaRQqFQKBSKOQ81iBQKhUKhUMx5qEGkUCgUCoVizkMNIoVCoVAoFHMeahApFAqFQqGY81CDSKFQKBQKxZyHGkQKhUKhUCjmPNQgUigUCoVCMeehBpFCoVAoFIo5DzWIFAqFQqFQzHn8f7UkdyQ4M90nAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -294,17 +298,16 @@ " }\n", "\n", "# Set up the initial condition\n", - "expt.initial_condition(\n", + "expt.setup_initial_condition(\n", " glorys_path / \"ic_unprocessed.nc\", # directory where the unprocessed initial condition is stored, as defined earlier\n", " ocean_varnames,\n", " arakawa_grid=\"A\"\n", " ) \n", "\n", "# Set up the four boundary conditions. Remember that in the glorys_path, we have four boundary files names north_unprocessed.nc etc. \n", - "expt.rectangular_boundaries(\n", + "expt.setup_ocean_state_boundaries(\n", " glorys_path,\n", " ocean_varnames,\n", - " boundaries = [\"south\", \"north\", \"west\", \"east\"],\n", " arakawa_grid = \"A\"\n", " )" ] @@ -313,7 +316,114 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 6: Run the FRE tools\n", + "### Check out your initial condition data" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHFCAYAAAAaD0bAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9e7wdRZU2vHrvfc4JEBJu5gLEICJoAlEEgSAjogTIq4iAgJcJF9FxvILCKKAxYQYI4IzAMBJvSIIIYRyMyoDhoibKAIpIRnw/R3EMkkFC5gVCQkjOZXd/f5zdvZ+1ez27qvfl5CSp5/c7UKmurqru3V29aj3rEiVJkkhAQEBAQEBAwHaE0paeQEBAQEBAQEDASCMIQAEBAQEBAQHbHYIAFBAQEBAQELDdIQhAAQEBAQEBAdsdggAUEBAQEBAQsN0hCEABAQEBAQEB2x2CABQQEBAQEBCw3SEIQAEBAQEBAQHbHYIAFBAQEBAQELDdIQhAAQGjAPPnz5coikZ83JdeeknOP/982XPPPWXMmDHyhje8QZYsWeJ17lvf+laJooj+rVmzRrW///77ZebMmbLjjjvKHnvsIWeffbasXbtWtVm9erWcfPLJsu+++8pOO+0k48ePl4MPPlj+5V/+RYaGhlTbffbZh449ZsyY9m5MQEDANo/Klp5AQEDAlsMpp5wijzzyiFx55ZWy//77y6233irve9/7JI5jef/739/03BtuuEHWr1+v6l5++WU54YQT5JBDDpFJkyZl9StWrJDZs2fLO97xDvnBD34ga9eulc997nPy9re/XX71q19JX1+fiIhs3LhRxo0bJ3PnzpVXvvKVMjAwIHfffbd88pOflJUrV8o3v/nNrM+lS5dKf3+/Gv+pp56SM844Q04++eR2b01AQMC2jiQgIGCLY968eclIv4533XVXIiLJrbfequpnzZqV7LnnnsnQ0FDhPhctWpSISPLNb35T1b/pTW9Kpk2blgwODmZ1//Ef/5GISHLDDTc4+z399NOTSqWSbN68uWm7+fPnJyKS3H///YXnHhAQsH0hUGABAV1GM5roySef3GLzWrp0qYwdO1ZOO+00VX/OOefIX/7yF/nFL35RuM8bb7xRxo4dK2eccUZW9/TTT8sjjzwic+bMkUqlrnQ+8sgjZf/995elS5c6+33FK14hpVJJyuUybZMkidx0002y7777ytve9rbCcw8ICNi+ECiwgIAu46GHHlL/3rRpk8yZM0eq1arstttuhfpKkkSq1apXWxQ2LPz2t7+V173udbl2M2bMyI4feeSR3nN74okn5Oc//7l86EMfkrFjx6pxsN/Gsf7jP/4jV59e54YNG+Tee++VRYsWyQUXXND0mu6//37585//LJdddtkWsacKCAjYuhAEoICALuOII47IytVqVU499VR58cUXZcWKFTJu3LhCfS1evFjOOeccr7ZJkjQ9/txzz8m+++6bq0+Fsueee67Q3G688UYRETn33HNz42C/jWNZ41x11VVy8cUXi8iwBu2SSy6Ryy67zDl+uVyWs88+u9C8AwICtk8EASggYATxiU98Qu666y6588475Y1vfGPh80888UR55JFHOjafZpqSIlqUoaEhWbx4sUyfPl0JfD79WfVnn322HHvssfL888/LT37yE/nSl74kL774olx//fVmH88//7x8//vflxNOOEH22msv73kHBARsvwgCUEDACOGyyy6Tr371q3LjjTfKCSec0FIfu+22m4wfP74j89l9991N7cvzzz+fjeWLu+++W9asWSOf+9znzHFEbI3S888/b44zadKkzIvsuOOOk1133VUuuugi+eAHPygHH3xwrv0tt9wi/f398qEPfch7zgEBAds3ghF0QMAIYNGiRTJ37lyZP3++fPCDH2y5n8WLF0tPT4/XnwsHHXSQ/O53v8vF13n88cdFROTAAw/0nteNN94ovb29MmfOnNyxtJ+038axfMY57LDDRETkD3/4Ax1/4sSJ8s53vtN7zgEBAds3ggYoIKDLWLZsmXz4wx+WD37wgzJv3ry2+uokBXbyySfLN77xDbnjjjuU19bixYtlzz33lMMPP9yrnzVr1sjdd98tp5xySqbtQey1115y2GGHyS233CIXXnhh5sn18MMPy+9//3s5//zznWP89Kc/FRGR/fbbL3fsV7/6lfzmN7+Rz372s07D74CAgIAUYbUICOgiVq1aJaeddprsu+++cs4558jDDz+sjh988MFZEEAf7L777qaQ0Qpmz54ts2bNko9+9KOyfv162W+//eS2226TZcuWyS233KJczs8991xZvHix/Pd//7dMnTpV9bN48WIZGhpqSj9dddVVMmvWLDnttNPkYx/7mKxdu1YuuugiOfDAA5VR97x5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4/iNl9j1WTVqED2eMUcTH4eKhBxI3x2m3cF3gOXUy7RIBi2WA1ajstho76MNsoBtmYEyy0lmQa0fxtgjmiojidozZK6d22jr6qMIqFar8t3vflc2btwoM2fOzOpT29xddtlFjj76aLn88sudAQv//u//Xl7xilfIueeeKz//+c+9pv6GN7xBHnroITnssMNEROTKK69Uxx944AGZMWOGV18WtqgA9NJLL8kf//jH7N+rVq2SlStXym677Sa77babzJ8/X0499VSZPHmyPPnkk3LJJZfIHnvsISeffLKIiIwfP17OPfdcueCCC2T33XeX3XbbTS688EI56KCDMq+wIoiqtY99AQEoYvXWu8ZoLw8ByNmWzUOdbPSHancm9CgBqFYgH8YqsZWJYaA6fQW2Q8TdFoUhcwFWLrb1OQ0h/warqrUI+riqYyBEnd9ruIyLLktkyupjg77SCUvztj6N7XVAw4Ds50CB3MdmztowsD48yubrWnAzYwVI9Pm5me1H+u5UYENR9qCNrKTChV3jmX2OgSLCkJdA0qIQYa0PI7lR6pQNUKpFSTFv3jyZP3++ec7jjz8uM2fOlM2bN8vYsWNl6dKlMm3aNBFx2+Za+I//+A+58cYbZeXKlYXm/oMf/KDp8cMOO0yOPvroQn0itqgA9Ktf/UqOOeaY7N+pXc5ZZ50lCxculMcff1xuvvlmWbdunUyePFmOOeYYuf3222XnnXfOzrnmmmukUqnI6aefLps2bZK3v/3tsmjRosIxgAICAgICArZVrF69WsaNG5f9u5n254ADDpCVK1fKunXr5I477pCzzjpLVqxYIdOmTStsm7thwwb567/+a/nGN74he+yxR0ev6U1velNb529RAeitb32rDozVgHvuucfZx5gxY+T666+X66+/vu35WIEQMxTV2BTRBjXMwdl3C21pH2TnGoH8iExWXNMGaTU/8dxA9RIqZFIKDAxDmTdXmRhBZ30pyse2HMV5WNolGiyNaHWsXF8u4+Tm9VGurmX40GXdRJQf2kdrYgYJZZqZktFWGpiW2GiA/RFaRmlEpQjITDIb+XYoDFJOR2a/uQOo9ekBOky1Qa0rvPQVQwNbNHu7mY6iw5qVVvtzvYsjGl05kfbe39q548aNUwJQM/T29mZG0Iceeqg88sgjct1118nXvva1XNtG29xG/Pd//7c8+eSTyrYojmtayEpFfv/738urX/1q78sZN26crFy5Uvbdd1/vcxi2KhugbqMlG6AigsxICT2uccjijygpqgWap+sk1qHtENp7DNWlqCp4lSVjhsuDSPn0gj1CBYWD+kBKIInywk5MhA3LA0akTgGg5xf7ELAFL1W9t7NwZwKf+kCT/pzCBHIMeBjpMqANMQKw4bOdqI+5/ZGPrHmrudmcrBrbsLNBTyg8rn5bh1u9l6eWyxaJjUdtihyCJxHs6E9u2SWx9x3LzCPQgKK3oBOs74V3oxLl3x3mBYY2T+hZmUZxdtkFibjpMJ/3rxNCy5aIBD0assEnSUIzrTfa5jbita99rTz++OOq7gtf+IJs2LBBrrvuuhw15zOXTiEIQIAoaVjgxL2hKmqT4zyvyG/rI/SoRTpp3pZ960DAST9aJaiLB+vlEikPDdUXvqGaMIS32hY7RD2hsfHg+9jNMLf6SmV41L7e+sX47GKZJqdZXSNUpG2jvRIqUGvFMuemUb6ZcUjJ7gMXk6RWr+Ip4URQcMJh1Ic2yc8fU7MQw2Et7KRqJKyDMt5/Vp9+W32EHiU0GG2Knmdpfz3eVZoSxxqnoKbaemaVfY+h3RER6S1Vzfq0XIHzSlCOSbAjU2NEjndLe9NO39sDLrnkEpk9e7ZMmTJFNmzYIEuWLJHly5fLsmXL5KWXXnLa5oqInHnmmbLXXnvJggULZMyYMXLggQeqMXbZZRcRkVz9SCMIQAEBAQEBAaMZI0Vhi8izzz4rc+bMkWeeeUbGjx8vM2bMkGXLlsmsWbNk06ZNXra5Tz31lJRK3QkW+dd//dfeVJ4LQQByoBCt7WhbVOvTqut7kfMK5RySuhaJ5YuikXItV/pBoMh2ABubPqjvZVvrdDzUUMA0MJAjvIdV0IRUe0u1awFbJOKBhur9KuxuM5U4ap+U7RBqqMB2qD6lTGujXG8JfaG8wKyozx7UiDPXF6NwitgXkeNez5tFPRV+Tv3qfPrrhLaWBTakYOyVobigFB28A7HSwNY8F8kzy2AFPSwpDRBqd+ovfEze0TQitYqqrLiuehHbKCV9AU1OkcTELKq85f3WbYw0BXbjjTfSYzvssIOXbe7y5cubHl+0aFGhOSGuueYaGTNmTMvnI4IAhEikY5K28/1oVejxUaU7zi3yEWJzUkarEBSohDGGILWGosYGhv9f3QFsAwZAaBiDtkEgNGCajbSaxKyhIUkqoGKvtR+Ea+kH1+CeSv1iVPoL48NhGUYPj9Fc6ME+WhZ6sHOWQoPFAbKEIULtFMrqzj7K9Hkz5uQhzClYbQo+67Q/6zysJ11kXTEhJiH1zE6oZLRl10JiMaXP6iDkxGFu5K4s6xUiACFU3yjrpBfDhEMPYSilcNn8rSjOPmCpQdJykcTMbaPd79IITrVbiONYLr/8cvnqV78qzz77rPzhD3+QfffdV+bOnSv77LOPnHvuuS31O+qToQYEBAQEBARsv7jssstk0aJFcvXVV6u0GwcddJB885vfbLnfoAFqE52kyNo5l2tvLPWNz3nNx2Zqd2bkauWAokakqLoH9UwM2ptMdGfzRw0L0F5IjaVNqmWgB0DjpIIsggGopriG2zMKLCYaG22wHeWO05xehL5yJTL1icxcr7MpCx6N2fhtPbQ+rgjLRROZsjb1Bh5zMoJ++miLFMWFP1eqZPHI86X6YxojS4lBnnv1HoE2NqWeByt1DdDAUP1TgAbRccl+ltN5KM0Lvp4egRXTH6lEKOiKir+BnRgdw3EMglqymzjBqPCK+YB3G5G4dYyu87du3HzzzfL1r39d3v72t8vf/u3fZvUzZsyQ//qv/2q53yAAIdLnzMPGYIuhRdpLxH0thewsmJ85WRdKlq6fjIceZph8NQH3+NgR51J5wEC8oTjO18eDYH+EthIYJ4V4bVlxgGIi6MRVjOhsCDtEeFH2TMTGI/3waaGBCDKGPRbWF01BgbRnlkDUih7eWE+EF3MepL8S0K9We0zwG8PzgxsD7LsMVG0mwDOhB56rIXhO414QNlLvPKR+MOkwPqfsO2VRYD4CHAg9ET7jAzUKrAcEIEjuWYEgskMQHr5ihKSwhKLG+bmghB54sJQgQ9q4hCF0wY8cdBhLqIprVxomIyLhMrqCQIHJ008/ncUlQsRxLIODg8YZfggUWEBAQEBAQMCoxfTp0838Yd/97nfl4IMPbrnfoAECpDnnrF1ZRzRBLe6QaHdFaC+P87yQxnlJ8nXDB9RIZhfZjsoyfBWRKslDhjvnUlpm3jI4PXzKDQ1QUsHdcX33WyJRqC0jZ2ZsmfgYJadtimp9qvm+I3W8flhrR5q38dG8uHLFUS2SK8cc1Lu0O7k2qu+acSxqY5h2EjVA/dhfkhsDgRolfPhA8SLV2vgqLA5qL1vUADEajWqDkEquaTmH4FnfVOqpt/WI7pw+770wORYTqFWPKUaHoRF0pg2i9wPoNZirlZCWRaO34h8JSfTcFQQNkMybN0/mzJkjTz/9tMRxLN/73vfk97//vdx8883y7//+7y33GwSgRkR6cTFidRXvstWTDUHFS+gpYMvDxmMCjivCdUTqLe8U5UkBH2X8PqhYfygMpVpPYluh5A5cq3qg3F/7OIENUFypvxLoHUYzHdQGYl4hKuAhquNRoErnBxeuhkOWwaJDROqRJC37E2mkulCCy7fxEYBocEAHjeaizkTqv7lFz+X7tgXF9BpVEEa4H/rewJyAyqrUno/SAApi9rtQHoBLgWfMNBVh5l34o7Pn2vACY/ZCWhiC+9RfE9pLQIFhfyQFzAC8G2Mqwy9gX6XOV48p18tKaOiwvYwlUCEtVgJvUdyYFAl+2E6Kj46jQ9ngt2aceOKJcvvtt8sVV1whURTJF7/4RXnjG98od955p8yaNavlfoMAFBAQEBAQEDCqcfzxx8vxxx/f0T6DAIQwjO0TPJYWfTYELhoN+yM7a1Mj0+HNiM+1tKpFUpojpHfS+6EjmkmugTRomlEzV9u8Ki0I2TXHbM61YUr9qCUAbRAagxqJWEXqGpkIJopaGlUmfdQHB60QPCARaDEUhYfaiFqbhDxLqm05MttkvwfT3qi2RPNi9cGeaZextY8xNusvfYbIO4d0KrYpD+CzMPx/YEiVgb6KbTWE1Jlxf5nmTkg9mWuSPfdEK0tUSipWV80IGllYVMbhM6Ty7/VgQuDh+iEjKKiI1gahJ1mr2iCXFoal0FBeagUUIWy8ocIRLdtHkmjavZXzA2wEAQhhca0RHEuLPsKQy96nqOBRBPb3zboUoetD0es1O7H7cLVVTRTdVC+n9ElCjqs+HHQMftQS4L2SAaTG6sIQCjtSU7f7rK2KJrPWUfKxVkINuucqQaZWr9zxSd8k0nNGfVCBHG22HJQrif5LhWlLuCKUbJENA6PfEiIAJRvFAOGYCAVd7QOhoUapKbsfH1sfNmRN8MH56xy1uOkg46T3Zog869B0kIRxSKNJo/cYUmSbgBrrA2HIlVC102g1txgTolL7IxW9utsINkAU//mf/ylvfOMbpVptzSsveIEFBAQEBAQEbJVoJzt80AABomR412RqOZlmo0lfrrHMTth53ZLimXFvUcqv1TGb1TU2wR28RSuyeZJoaJbHUgkokLgHyrBDlnog0uxkNLa1QufX/mVP1njelOYLqTNyjYlF+VC3ODVS875Jf5RWNDRAXrm0rLkWfkfyY6pYOKjp64XfCNs40qkwQ3vBgIGonakYdT6KCGYEnVJgYOjLWBltZJ7/nZWGCJ5vFtNqEKi9lA5DI+kh2IWjZmgItKeDhmaoF2MNgTao08bHRbRBqPWxDKlHNJv8dmwEfcoppzQ9/uKLL0pkePT5IghAgKha8zZh3ywXGAVjLTgeKn3LnT0hPzarj6BDwxyh44KVzlsE6nNjQdd1eRuhEQOzI1EfT5gUUk9ZYDqknuwHiAlDab0+jUijVKjJ/5AsHIJ2zTeeMY8xIueOwC208Xvmf57+RsKznqRNIZieCkaIQmq9HvPQpdSookjx1hGvMpfXlgKxDdJCD1xXJVH/H54g9gcfeRTKlZEPmUt2InSHNJkgTTZcP4iBPmHDMARBP6tQHgSBqVozrhoESa0HKLJeqO+EVxYTWqw8YtgW6a5U4KuOIAUWJe1tQre0E1s7SL28Jk6caB5vlfpKEQSggICAgICA0Yrt2Aboda97nZx66qk02enKlStDHKBOoTQ0vEsstINjMA1Doc5H6+PSRHnMSXkT1TpkDIiXp5vFVKg+mmt9sMw0RF732lJneShKrL6VsoUZTIP6X3taDdcnSjviRmTSWuxM2xpYZ6zW82nsTmcucWhnPCirQrQ7U1Gze2bOyaYP6TxSrSs0YFnJE+ivukO9XO63HhYypSJt2O2gWh+jHo9DOSJ9aJcvy9idUKFICaImLK3HdCCYe6wCaTN6kCaDcq2+rwJanwS8x6BvZTxdIKuXj9bHorVouXYeyz4f0Fkccsgh8utf/5oKQH19ffLKV76y5f6DAASIqsmwuyh+WGrvGk1OyGAszNpN1/4IMcGj/r2HhQ+FDTIn/dmIcmNHZGyX2tSL6gJaABezTAAinjH0Whx2IF4JJAusWzrnVL0cV/Mfk1h/Uet9oAt1GVzlt+S2zGVH5NG243AKPTZUYEhrw4CCJvPEQmqsp/4bVXvLtf/DGB5hFwoFLmTvCwRTVEmA03IPCj32ixupiNPw/mUCEK5zhHIlyALEYoBFgyITEZoEuJ5IuC70VEkUdRRCLE8yHxSx62GR3YMN0Mjiq1/9alOa63Wve52sWrWq5f6DABQQEBAQEDBasR1TYH19fe5GbSAIQIBSdfgPg8Zlictb1CIMn1w7jWgwvIzUUq0J20m6bFJFpFS7Li8PNGZAm94PkmIgVoahzdt40V4+c02rfHbkxj2jGifc3WKWcLCmTXeHSDeoHFFl+z6iNsi0//UwfDZ/IkVTeTwU1pj0efTor4Amh8Ypss7zitjp6IIGorSpseqY4fZo6OsztnPDrbSn9XIMWh1l5NwLWo5UQ6VoL6INQuBzUXs+zXx0DW1pXClrCFzTkDKGi6wamigrvpBInSITEekDT7JqT/1lTD3JlPdYi198qvWRfD19twI6hvXr18u4ceO822/YsEF23nnnQmMEAQiQeoFFxrqgHnf2HXCt1wWFHmL24IbrvBZpr+FGtQUAF24UbuDjj7YL2CYT5nwcKdRiTOob+hVppOigjbXmM0ES7w16hFnJLLEOXIAToFRiRVU4vtZY7RIUxE1f+QlDDgqM2ts4PpKqD3servdFPOhe/YMZHasXmwyOTWoCydBOcNj1DDZOIy2TxUEJ5yD0JJbQIyJRzbamVLFf3BKNWJ6vZ+7uCSmLmcBX8nXS8ByoxL75MRlFxmgm5RFm/AhFAyta44wuN3jZLjVAu+66qzzzzDMyYcIEr/Z77bWXrFy5Uvbdd1/vMYIAFBAQEBAQMFqxnQpASZLIN7/5TRk7dqxX+8HBQXejBgQByIK1ufLQxjj3BIW1LflyUXbCbFqQ9sKdc6rJwcBuqPVB400aJ8XSvCDYRWIuMAcFJkzrYwWVI4aoWnNEjNYtekTtioEuQ5oMuzZ27SyfGCdxjB2+4QHYrE3WO9G80HcADW9NjQecRmMTWZWMmyzwAjJqp2gb8zwYGrUc6vnIn4YOAUICGiaM4kpTryDlQygw1JTo4Jy1Mci1xhDjRtFCqJ2pUVXoEenUFjUim0eeFhMRqYIHwUBUX3D0u9H8B2MxgywNDtOSqvkFCmzE8MpXvlK+8Y1veLefNGmS9PT0uBsCggDUgCgh2uq2JHDjA8eoDPXdMFTK6sPjHtoUdjwoMEYhJZkARIQeQns5BSA2J7XAQnsXW+NhD5QtwIrCc39cTRqEUTvQtlppLsE5k6WKzZzhNFRbFQSTzM8hOGkeTZ1o/yMtkq8rjwptPOsFI7iZrCIZgzbyobjS8eAjr6MuQxujD5ynkp9R6GHl2jOCQg+Wy2BbViZCUioUMOEBP+5VRU/l3dkxICB6R8ZDWG97SFpGeKotoArzHxyqv7DpNTJhr9XI0iNKcbmwnXqBPfnkk10fIwhAAQEBAQEBoxTbcyTobqMlAWjRokVy+umny4477tjp+WxZRJIzzM2EZ4+HqBMPmmZakFqI8mOQHTlhH8wxEDrMP+zK4Cmp1sLdqzglECeFan1cHl/kutS1OGhIZZiNmiiioUrjuyTM+6YAfByWIhU/CKgxK7Ab0hpFNnAjttgVUEX5UE8ucO6v3sS4jV7vpHr28ga7mEZC5w2D84jdbfpMqucR8pDFfeANCIbPpYpdLtfKqN2poNaHaIDKLaaSwHQa1QTHqWmA0GsLvCOrSPdWwREAn/tUu+QxHRU/qGpoonBslfOkXkRtEIv5Y469lWpQAtxoSQC6+OKL5VOf+pScdtppcu6558qRRx7Z6XltESQNUaCHK2v/9/jAEbOIlqGEoQ73ZwFd25lnVypMKKGnYpedAhCziWJUl7IlkRzUeEZCShGRKoSVSD9EyvuGuK3rgbDs4uKgjDTJUF6y83PZhq5bfSbY8+sMhNii0FPEjZ/1x0Bc1E3q2mM86zlEoQfzgrEYfJYgHvfZQo+MAUGnp/6AlHshDxY8k5VaEMAeiJ6MAlAPfOSRCioXoILYB19TY6ngAXWVvGCSL9df0pQy4xSZPbbK01XrbxAFP6DlkPorkgCV2fikfYyoDVAibZpgdGoi2x5ayuj2P//zP3LLLbfICy+8IMccc4y89rWvlauuukrWrFnT6fkFBAQEBAQEBHQcLWmAyuWyvOtd75J3vetdsnbtWrnllltk0aJFMnfuXDnhhBPk3HPPlRNPPFFKpZbkqy2Gak8k0qMl+yxtBNsl+mgxDPpKx/hBqsueWyFjbA8HDOs4TWNh0ElapW+3VakuHFBB1NCIFLUm+DgZmrmYaIAwlQHSD3ZmbR8NUHMuTlExLIgexlqp7YSVtxfSZSp+UNOhWw9+6NGWecK5OTr7wadpLIy2DNyo2ujDh4oznkP1PDKtj6KPoVyjV2OgtxLQAJVA01MGDVClYtNaqQYI00GU0Qi6ZFNgCCt2Dmo/qIbIMDQuowYIAsiW4UaVSmU4r97dUM3LSxmFsxhECEMzXjUytuM8h6fvNvpu5Xi3EUmbNkAdm8m2h7aNoCdMmCBvfvOb5fe//7384Q9/kMcff1zOPvts2WWXXeSmm26St771rR2Y5sig2icivbous71hyUvV4piQ+tppVIjCFaC5MES9tvJNczC/dcRDStFeBsWlbICw7GED5EwO60N7pWUWkJEIPRhtN/O6IQKGT8A9c2HC8yyhraGc2gbpKNUYbTr/4fFB4YU769qWsniUYRAqrTGZpKNuu+EFhl34UFlqTrX+mFeXsvWBceJ8Pd24YHcqj1f+eUvgGYwgsGGlF4WeeplRXKkdSw8IQFFB+55OJPJMx8HbW1b0GxkD1pK0D4zegufFHsZvdbf0eh2L6Ox6H4Ktz+jFPvvsIx/84Afl7LPPbiv5aSNaVtE8++yz8o//+I8yffp0eetb3yrr16+Xf//3f5dVq1bJX/7yFznllFPkrLPO6thEAwICAgICtjukbvDt/G3luOCCC+QHP/iB7LvvvjJr1ixZsmSJ9Pf3t91vSxqgE088Ue655x7Zf//95cMf/rCceeaZsttuu2XHd9hhB7ngggvkmmuuaXuCI4lqr4j0iUlrMQ0Qxv9Qu0dVn+T7YBol3LGYHIc990IONUzDwgICGgbFzPBZU2BEs5JWkSBqjAIzgx8yqo5pfXqw81of7N557Kad993Q9DTWi+FtpDbp+Ft01aDR8MpRttqEQjACLiZUdef/oPKAnR59mFpGQnU5qGufwJz0fak9exFQYGUPrY8ql/IUWJEs6CKd0fpYKBGVdER+I1TqDNT+rzUv9p68CE3FtEGK5oMf1bo3o0obFIyg5ZOf/KR88pOflP/8z/+Ub33rW/KpT31KPvaxj8n73/9++eAHPyhvfOMbW+q3JQFowoQJsmLFCpk5cyZtM3ny5LbS1G8JVPtEpI94gpCPMi58WI/mT+mHT33McbGAvnFZK2FCwbTos/arj5Z/W5XglAUSTKMnM6FHeVTBQAaromgxTEBbtedhUREoZCVM+PKx6xkJ4DysjzFen5LT0B4I+ityWT7ruWU3g+wseOs4vdTUYSL4sdxRJlfrY8uTLzOhh/XtzPXFNgwlfO6hXBO4MfltGV3cWUDDVj24RonFh5onzB8FlfS60NUebYBw8WLCdxFKOCbPtTW3gNGJ17/+9XLdddfJP/7jP8oNN9wgn/vc52ThwoVy4IEHynnnnSfnnHMOp18NtCQA3XjjjfLjH/9YLrnkElm7dq3Esd6NfOtb35IoimTq1KmtdB8QEBAQEBAgEjRAgMHBQVm6dKncdNNNct9998kRRxwh5557rvzlL3+Rz3/+83L//ffLrbfe6t1fSwLQ3//938ull14qhx56qEyePLmQxDWaEfeKRH2iQ9k7NEBaqwOdlfL1SrmrEtow7wT8B5+3N6yfie5o7XJqaKxV/rjjhTKh2sxrqZL7QQy9szmxXErMs8uy0WVGrj7RDV3AzN9IFeGc0msnmghFhTrd+nBsMiVmyJueG9s7ZZpMvYg2iGp9oD9DI+ZVxjkZQfa444FjHqpjuwv2PqQGz+jhVTYorcZ6VrY8uEYLGK3E0lSk7ZkWDI3/i1x1kXg+Xv1taS+wpE0vsNH7yHjj17/+tdx0001y2223Sblcljlz5sg111wjr33ta7M2xx13nLzlLW8p1G9LAtDChQtl0aJFMmfOnFZOH7XIAiFaH26fdwDXVAiYlnqBcvsN217C+kAkZAEupPlmfXi4wVs2QCj0oCeWsKCC1ocWljhFK7psnpQA19qbru8j+6IW6ZB1TmA1IbYrhdZiJaWw5yrfofbIg7ExCCB+8E06z55oYtnYNI5pRQgmNmIMlgDkY/ejkpqm9UyoxI+12gQYkZuB9vIJYsiEnlSAUIEBC9JerQpRzIbGNQYXhvJ1ZUWXCZSb2xRZglVRMO8xROb9ti1IFVsR3vSmN8msWbNk4cKF8u53v9tMejpt2jR573vfW6jflgSggYGBbSb6c0BAQEBAwKhFoMDkT3/6k9OkZqeddpKbbrqpUL8tCUAf+tCH5NZbb5W5c+e2cvqoRaoBUvSDK1AAbhSqdpOsO2RlWB9qF5Lnf9R8UGPTYW0QVe+n2eBR64N0E+6EWfLztIzzZwHm2MvroPMKGYsrTxYynK2k6x4oDVVgcEbnISxtEFOCEY1MEa0U60Nre2ptq2TXz85TWjPjRKoBAg2FkdWdxdvSzgFIe4FGo6YNUrF8iNYH6TD08ir0mwOYJqTl/hynRUrLaGuLUHNiZaWPDA1RrUd7TlkfzefWOKetCkEAkmOOOUYeeeQR2X333VX9unXr5I1vfKP86U9/aqnflgSgzZs3y9e//nW5//77ZcaMGTl11Je//OWWJrPFEQ3/mc4CPtQTCieoVo/yx+lHlLXJBCDy4Snwbnt5fpGAhin1lTChh7m+Gx9a5flV8vhAu1BE6BGpf9mInQsdpogw5BNFL21TREjJ9eE4j8Fqw87rhFDGvLkM6kkJOvg+edgD1e2ImBBFymQTkw1BbObwHYiM5KQ6MSmhuggVZNmgdNrbC8dmNi9FfmcmDLnPI3Mi15uOY1FrvnDl97JsmFoVIrcGLFy4UBYuXChPPvmkiIhMnz5dvvjFL8rs2bNFROTss8+WxYsXq3MOP/xwefjhh2mf3/jGN+Tmm2+W3/72tyIicsghh8gVV1whhx12mNecnnzySalW8y9nf3+/PP300159WGhJAPrNb34jb3jDG0REsgtKsa0YRAcEBAQEBGxpjLQR9N577y1XXnml7LfffiIisnjxYjnppJPksccek+nTp4uIyAknnKDopt7eXrOvFMuXL5f3ve99cuSRR8qYMWPk6quvluOOO07+7//9v7LXXnvR8374wx9m5XvuuUfGjx+f/btarcqPf/xj2WeffYpdIKAlAeinP/1pywNuraCxdQqUfTRHkdIA5XfL1FML5+exQ7bOY6krLA8XHX8HdkhET55YBs+RUZdDAc0QM1ZlRs6ZASUZulX4XFarYP1Z9ey6Wp0THbuI+tEuay1MTUNYtY97xQRKz/MZz5Hri9LgxOuwXMZyLQ6QytdlUz5lD+vukaBxvNJpjMA8tGGzu40LnZhzydA4dR3tRnMueO6JJ56o/n355ZfLwoUL5eGHH84EoL6+Ppk0aZJ3n9/5znfUv7/xjW/Iv/3bv8mPf/xjOfPMM+l57373u0VkWLHSmFmip6dH9tlnH/mnf/on73k0ou1cYNs7mFCjaJLIOE6oroTQaNm5RAAqBDJnHwosW+iVyt/Dhsawo6BxyYp85D3g8xuZ53VijSMXpqMn54/rH4b055qfz310rY2d+M4RextL6Bku5+u4O3vzoX0EIKdbPXk/0eswgvdBBT0s5SkwlruLlbslbLTzEbfOZfP0cUu34BP80PICK4p0Tjh/5rq/RdAhG6D169er6r6+Punr62t6arVale9+97uyceNGFfh4+fLlMmHCBNlll13k6KOPlssvv1wmTJjgPaWXX35ZBgcHVQYJC2mMwVe96lXyyCOPyB577OE9hg+2rnTtAQEBAQEBAYUxZcoUGT9+fPa3YMEC2vbxxx+XsWPHSl9fn/zt3/6tLF26VKZNmyYiIrNnz5bvfOc78pOf/ET+6Z/+SR555BF529veVig310UXXSR77bWXHHvssV7tV61a1XHhRyRogLoGkzIj2hbldUa0RNZ5dHfODEateRIajeb6ygIhkh0S8zyyjIFZkMBWjXcZ1eXqqqjGybjvXjSaMp7Ga68BtSMka7qen6Eh8blsF21bdMdrpq6wyy6tj6pnWh8POIMpWm1pZ1AmsX/Q8Bk1QCn1hZ5QStOzBV10mMaj1T4QrVJ1OI8qxokiRs4ZJVXwPrY6vy1hBN0pG6DVq1fLuHHjsvpm2p8DDjhAVq5cKevWrZM77rhDzjrrLFmxYoVMmzZNzjjjjKzdgQceKIceeqhMnTpV7rrrLjnllFOc87n66qvltttuk+XLl8uYMWNou3/+53+Wv/mbv5ExY8bIP//zPzft81Of+pRzXAtBAELUVI3Ww9bOA5gJGYoKgDJzbTcosJjY6VDzAeMjwjxZKO2FFFetjLQXtftRVEuUK3pRTAXoDh+7H9ODS43hszDmJ0IulT44psDEvMvI/JQXXRGuymET5RW7MSH/sPhNnDMOZwk90uRZNicC5SJ0WNG+0yFIoM9SpblnF7P7YXRYJ1AkcGHhvo2HhAVnVAlJSdkC21S46Cl2H1ul30bU3sdChyiwcePGKQGoGXp7ezMj6EMPPVQeeeQRue666+RrX/taru3kyZNl6tSp8sQTTzj7/cd//Ee54oorMg/yZrjmmmvkAx/4gIwZM6ZpYvUoioIAFBAQEBAQENB5JElCKa7nnntOVq9eLZMnT27ax5e+9CW57LLL5J577pFDDz3UOSYmU+9WYvUgACEsSbtVydvyAnMFBmw4T2lhDCNoanCsKDBLnQX9Mg0Qqc92vT5UHK2v9RGRXT/z8nHRXh5Qt6NGOdHgfOpEMqhFG5H7Sw2ws/tha6oaEpTZfVu/syvuUK7errbA0mlEuYIeL1H8heqx6TyKaqWy3T6j0RgtZ9DRKg4WBDkUDHgIGiAMdGhRJszYuVUwTQqLo2MpbIso3URsbQrT+iSk7AK7N1baC3ysWqX2trimh6FNCqzoN+ySSy6R2bNny5QpU2TDhg2yZMkSWb58uSxbtkxeeuklmT9/vpx66qkyefJkefLJJ+WSSy6RPfbYQ04++eSsjzPPPFP22muvzM7o6quvlrlz58qtt94q++yzj6xZs0ZERMaOHStjx45t4+LaQxCAABnXai2aPlQM867KPBXydTkQs/T0Y+fzTaMeLtnYtvuVDwWWlpkaX08K+qAckQEP+qfel8fbTQSq7D6RgHuMujG7VnYi9vSoB5HVh7pU8iEwJ+Q+zwkvahI/avB8pEKleiAZl0GGdAlATEZV723K97LjUO/IM5awQJ+M9sLknrUJMLufTtvesDauoII+afRcwReZ0MNoL3Nv5nE/itB5PvfJikjNaLb0ukY0qnSHKDBfPPvsszJnzhx55plnZPz48TJjxgxZtmyZzJo1SzZt2iSPP/643HzzzbJu3TqZPHmyHHPMMXL77bfLzjvvnPXx1FNPSalUf8FvuOEGGRgYkPe85z1qrHnz5sn8+fOdc6pWq7Jo0SL58Y9/LGvXrs28w1L85Cc/KXaRNQQBCBDFtQXQemDaeQBdHzi2oLNUF1YXbHfr0JowDYWX5qJVuIRKl9DDoDQNLcyn4URmi2Ipe5RQSVKpYAJR68OsjN6ZYTm9rsRxvAD88grUm6tza4fxuongn6ANEBFU7PmxOeWLEfltlTCEtlRDhm0L/m7E3V0JPW1EJXbBEkJ4olAQeow2PpGWnfPxEHpcwkI79kkh7m7nceONN9JjO+ywg9xzzz3OPpYvX67+nUaVbhXnnXeeLFq0SN7xjnfIgQce2LGAy0EACggICAgIGK0YYQ3QaMSSJUvkX//1X+X//J//09F+gwCESEQktrUmRc0paGRm6zgxeTF3/speBQ47otmysb20QYaqqbgbaL5DnevJLtP7W+qAxsP4USmbR4LyZccVBYaqCKLyB61C5p2Hx1V08BZtdlq+Nx6/Les7fT6wAbqOQ863qAz3hiU4dY3HEBtdodaK0p75rmjSU6hngQ5bhUuzwrQtCPU6FwhcWATtUEGFvEGN89pBEepxSydRHelUGKMR6JXWSQQBCJBSYI6QNZ2hGQA0UrGDiuO0l8EFYN/kW2MmCqUTsUENHpXNRa3bgskuTQGN0ooekqkxhrYRInSY43bgdUfE0DcxHqIIj+Otw3mgMNTic9iRGCYOGooKc3heYrxoWN3OO2cZuBvPoIho2suKvUWEnqjDQo8P0merGrtj2Kp9UAdi/jjHa9HY2Se5cDeFnlbSaYxEKpCAOi644AK57rrr5F/+5V86mm80CEABAQEBAQEBoxYPPPCA/PSnP5Uf/ehHMn36dOnp6VHHv/e977XUbxCAAFFVVHA2EdtDx+WxwkBpL+Y1JPl6peSgySId43sYY7s2OEy7w1RKiYr6Wyur+ZP+qFaq9n9Fr3hoR4psfmO7bBrWsuBrTKNnGf0SA+yEUGqCxrtZUiQcw74fSkNVRBvg86yn02APMmq51DNkGVWriyk2QcsLDDVp1XzT4XrjIgm9OVIGuJZ7OWogqpQCq88VAzGmj1Y7miBXIMRW0el72q0I19uyF9hoxC677KLc7DuFIAABMgHIEAqUkAKH2bNVKLw+6S+yDiiKhpQJe2V8Z7kwxJAFR7E/cAmzrcD6NNu3y+6jEcaHSLmTsxACrr5ZpGJ1fwkdlnZRMj6+IqNn8WmVTvJo6xSiSB8RuTn1jwsKG+4baQnlmj4kc1I0a34cSlF7zan58VapFPWIoTAE16uEHhCWy+m8jYjVRee3pe1jLHSa4nPZYHUbwQZI5KabbupKvyEZakBAQEBAQMB2h6ABAmRxgACp5icy6hrrOw6U3DPDYXKclTsyj7yBKnr56F0u1CvKATVDqRYJziIsj9NjrVXDZ3aaRdVJA91ozZXSdvY0lKYhDXKJQfaUZotQe6aKkB3vLLpp9Gv27aOJsqJJK2NyaFxm9XDf0+e04LUmBu+pggHCpDDEkIrLg0bLisqKc2NUFZ1Xrx8cqi9UeE+rtecJg1pj9GqfSNXp/Ipq5kZjtOV0fixII/5eqfF5FZMyjgRG323rOt74xjfKj3/8Y9l1113l4IMPbmr8/Otf/7qlMYIABDApsBrY941mZ+/wA5ut55T2goWb8nIN/xcuG1AaLS2rZK4etJcxbyUUUVsfWyjI3K097H5omAGLViR2VY22YVl9KrzYh22hTUR/gLP0IvAbltl1Nb/ernp4dfvcxq6K9mW1x/cCA2Xis1lGf3Y4tQMvcfrx9ImMTAUPoKpiK9I2AMcZqtoK/ixDPabyIGGy2ThWz4wu68Qz6RKcilKJNq1VP16Fl1XZW9XuaZXc265gO7UBOumkk7KM9e9+97u7MkYQgAICAgICAgJGFebNm2eWO4kgAAGi2p+5GbK0IA31FClt5NGWht8x5tEy7eUaQ6SBrzFoAZbIkuXPsoIbdmJnonZ+ZFfMgkSmxtit0l4I5Y0GbVFDZeRUEwFtT9n+YXReLbHrtyQ6TLV10hNIJ53FI/h7QRnye0WJod5DagSeaa1RqLcpZXV2W6YZYtqgcvoAg6YKYwJVURsLWgrVJg0SidfSUz+vt1x/8HugbOX/86G3XB5VDErzQtpYRuZIWfH0HPl5MGPyOM5rg6qDQ03n3kkEI+juIQhAiJqqUVEm6XpIvrPaXdnu1hXQsOl8GsZpMT6h1xg0ICAuFnG6WHhQbmyuRpA6RTGSeqewwxZU5ToOAk56T2EtK0GZRteG3zkzZ8KhiaAjltAjIlKzv4g87H7MLPIIDyqgUORdF53KDnfTOK4DD36kInGT3U0qyWCgROPD2Vi2bpqiV2LbNgfnwYSJSkqHwfOIQsoQCZCYqA96lKtTgkwfCFxAv5WNOVmJQpvBzCLvYXvD+rboK0tgadYm248Z96hx7LRNPDCCNkDbKQW26667egc9fP7551saY4sKQD/72c/kS1/6kjz66KPyzDPPyNKlSxXXlySJXHrppfL1r39dXnjhBTn88MPlK1/5ikyfPj1r09/fLxdeeKHcdtttsmnTJnn7298uN9xwg+y9995b4IoCAgICAgIC2sW1117b9TG2qAC0ceNGef3rXy/nnHOOnHrqqbnjV199tXz5y1+WRYsWyf777y+XXXaZzJo1S37/+9/LzjvvLCIi559/vtx5552yZMkS2X333eWCCy6Qd77znfLoo49KudyilK7UEbX/Ee2IK+dX0fFoPB+HF1iLDlB8bGrMnOTrkEJQcyLWx2kZx0PayCMgYBTnd36Mp4qG7HJpcLhcGrLHYznVtDdX7f/lfJ2IqOzhqgxeN6k2KGJB9goFK3Q/CGxTZWqGuqnJ6SKK0IMl0MbFwJfG5TxFyoJ7ImWidq2lfB1ODbVBSusDz57LADiyKLIGoEajWtNexOh15mHUWymRF6IGl+dUYxuLelIG4kwLo8aMcpXsPJaXLzG8UpWRvBEFNx4cOQ3Q9kqBnXXWWV0fY4sKQLNnz5bZs2ebx5IkkWuvvVY+//nPyymnnCIiIosXL5aJEyfKrbfeKh/5yEfkxRdflBtvvFG+/e1vy7HHHisiIrfccotMmTJF7r//fjn++OOLTSg1AiqCIhSBB8XkTHCqziM2L+zdNb58qinxelIeUBl9RaRAj2vMoloT5kEI3SRGlF59SfY8mAAUpQLQILbNDZGfh5EcMwHhhpUjQoFlH2AP7xuGkY7C25GcTUWkdo/7Yd0zNh9F3RB+M6nW2hABHz+S+JEvl/IvgbIvwYkQyioGW54KzK/Ic8G83pLBUm1OMMuh+j8GoA+cd18vvCjGcbwHKITEBoWEbSyKafgf9ji2oIKbNJygLfRY9o4+VH6G/uAFtqWwadMmGRzUz+K4ceNa6mvUBkJctWqVrFmzRo477risrq+vT44++mh58MEHRUTk0UcflcHBQdVmzz33lAMPPDBrExAQEBAQELD1YuPGjfKJT3xCJkyYIGPHjpVdd91V/bWKUWsEvWbNGhERmThxoqqfOHGi/PnPf87a9Pb25m7AxIkTs/Mt9Pf3S39/f/bv9evXiwgRtFvdWDukbppygWlCkob/Nw5HtD40Do01J4+M7Gk9vTyqDTLqFdVFelSqaNjROn4Yrc1C2ktyZRb7R3lzkfuYUl9o7Ky0PkoDBMHmVIbxPLXgkyHb1PqMUIh+n/nZJ3o0zh4y97UwjYil+VEGx0g3kpQb1VRTgu+N0j6Atkhpg+B5qzVBSkgpNXGCzIAZLiY1SsbgiIkHvWlqREkcLsWGFYi/o7Q7Vbw3YrZJLA8CRkORtaSuGS+mhVZo5Z0ZDBqgkcRnP/tZ+elPfyo33HCDnHnmmfKVr3xFnn76afna174mV155Zcv9jloBKEWjFXiSJE7LcFebBQsWyKWXXmoMJnmBx3hHC8OgfGhAQ4/8Xlm3kb2AqTYGdaM+4PZpnYe1KKnBiTCEXwjlYp80VlG3eyX0DED9kP5/45xYkEtT2EGvIubObgRyRBQWeph6P6u0+3CijWc9ixTeCTmsIA3oEnpUPesDfqNSTWCtluBBsOzhRAfGKynKLM9d+whDSZVRauk0oD/Xc9CIlPKxEr+KSDwIwhy6yxnjKIGG2EqJEnqMeTCBhQpA+T4QNLRHJxAZY3QZ26sNEOLOO++Um2++Wd761rfKBz/4Qfmrv/or2W+//WTq1Knyne98Rz7wgQ+01O+opcAmTZokIpLT5KxduzbTCk2aNEkGBgbkhRdeoG0sXHzxxfLiiy9mf6tXr+7w7AMCAgICAjqApAN/Wzmef/55edWrXiUiw/Y+qdv7UUcdJT/72c9a7nfUaoBe9apXyaRJk+S+++6Tgw8+WEREBgYGZMWKFXLVVVeJiMghhxwiPT09ct9998npp58uIiLPPPOM/Pa3v5Wrr76a9t3X15eF2EYkpSY0Ednc6A7IqemuWHlWwXGPstm3j9YHN2Ll5sd9tFxmG7XFILs2ozn3rLPVOmYsITU5OM1Be2FZ0V6MPoSNcFzB+pomCgPoKQNnqEftgrGrZ/DS+lgawhbVlixLe0OjplDegIrFZCq7zsKVT8wK6pdrnnrnocbPonBEJIa8WzH85qlhcLlkv8wxeQET5REGnmm1BxH7K/w7m+sRaFeB3sGuqxbNRDRAOvdfvajf+da0N3ZcNbYY2tV2x6weqfcW+g1oG/vuu688+eSTMnXqVJk2bZr867/+qxx22GFy5513yi677NJyv1tUAHrppZfkj3/8Y/bvVatWycqVK2W33XaTV77ylXL++efLFVdcIa95zWvkNa95jVxxxRWy4447yvvf/34RERk/fryce+65csEFF8juu+8uu+22m1x44YVy0EEHZV5hRdBM1Zg0tCvar4g0WQjImC79nBIacEC7D9NlW2VjJP0pGq32wVc2FDg2+fIhLRA1F15KxGbAGXyPeLExASj7PbBfcm9iyJuUGK7tytanhEIPzMnx4FguwiLcFsK2AWo6hBd0Mk+7jVNIInReVwMkOubBhJ5yya4fqgkyKNBomkfM+upQ/cFJhV68B2w8LCvBCF7A7L4z7zESPJB5UZl1TJDBLox8fkUpqyIR4ang5OjDiw5zbi4NG6uhEXyQ29XibAPC2jnnnCP/+Z//KUcffbRcfPHF8o53vEOuv/56GRoaki9/+cst97tFBaBf/epXcswxx2T//sxnPiMiw/7/ixYtks9+9rOyadMm+djHPpYFQrz33nuzGEAiItdcc41UKhU5/fTTs0CIixYtaj0GUEBAQEBAwChBsAES+fSnP52VjznmGPnd734njz76qLz61a+W17/+9S33GyVJIR+ObRLr16+X8ePHy+s+cYWU+8YUO9ljVxFZdYrOsbtw7l4KUmCJYQQd99TL1V4ow22o7gA70x2GJ5v02JRPomLuwM4VjY9r5dIg7jRhys3jrWko2qteRsNmFecHLU1rw8eo6cF7sEO9PLQj3IM+0AjUyhHcjxLQYYoCY79Xkv7fQ+sT2510Ig6QBaq1cmnjSP4y3Qb/0doypDUoRj3RAFXgd6lAKgnUzmzqH345+jfXX5J4c33PqCgf9OrrqfdX6Rsul9EDENNLECqUaYbSayyToIT4HLy8uf4w979cv4Zk/XC5BFQXxr+Ke+F9Bs2nylWXPofESQFRxCjZRZHl+rDodB/KzWJICzyC8ebN8qdLL5EXX3yx5Rg0LqTfpdd+qoXvEqDav1n+65+7O9etFaPWBmirgbJvsOszEZPQVPRj4ngh6TePveepS64PBWbQXsN9+1MflA6zvHVYhGtH5GtFezGhh/SX3Qe8bngjLFsfEVERndMPH7P18aF86tFsC1BdTeqtPiictjyo/sdJNe9DnWfuBlqHU+ghbVVSUSKEYCTlVEgaAoE2VkJAvai8mzDxaC3AoJ4bvlxEQGaJUWvzrjKXefITmbQm2rZA4EVKvaPwXRN8IiaQe6xN5nmqLREOlbAT5c6L2JrMljFLiGLltG+WnbUb2I4psF/84hfy/PPPq4DJN998s8ybN082btwo7373u+X66683bXp9MGq9wAICAgICArZ3pBRYO39bK+bPny+/+c1vsn8//vjjcu6558qxxx4rF110kdx5552yYMGClvsPGiBA5gXW6gPDVP1Gfz5DtJqbiafCqBWIpodpfaz+eIoBMrZhBM3A6DCrrLQ+xPAZYRl30yCHmNICjaBVEMPaDh89v4iRqzZKzU9KBYwrqA1qGQ5Njmrqow3y7CvfOWoourNiK20Q0foobVBNA4TaParVNLQjw9XDD5QKuVNB9QHJDM8Momuan5IHBeZ6VtRhNOxnHorqvUy1lnCcMVatUp2WwXTjkOlc0RuNBK5kThdmnkXSNjtnJDVA2zFWrlwp//AP/5D9e8mSJXL44YfLN77xDRERmTJlisybN0/mz5/fUv9BAAIk5QZKqHAHhapHBi4BiCTxdHqgFYWxmLF8YyVSbwlG1NsLBCN1Lfj7pms4c3FXyUvztJdI/ePo41aNoMJQVunswg1GBbA2BUCFoTbbdgyR+p+INAg3jAJT9XGuDoWhGKQa5R6vPq5Rrm1UQmGvXuSvXF4YinxoURel4/N8qM4t7hoOl5m0Ybd3CkNK8Id6w31f0awenqMuuyQWssQ83m1sxxTYCy+8oGL6rVixQk444YTs329605vaiuMXKLCAgICAgIDRiqQDf1spJk6cKKtWrRKR4TiAv/71r2XmzJnZ8Q0bNkhPTw873YmgAQJUe0Wk19lMoeUNrcd5zr59xjY0QEzTw7zHbCNXOExC3atghKi9qXmKMa8tpLVcWqISa0t2aJbGi8X70cbiedpr+B+1/3kZO7vbNPY7fGKB83z6G2F0QuvDc37ZWoe0Hqki5X2lPMLqDw4aHPeUUiPo+vEBNIgewvwnzdW/LE9WBA8q2jXTeKy1cRi9hWkx4th4+RkKOmJk7wOjzZl3m5VnjFLD8M4prQ60z+67TaFGRBuEtyOdKtP6lJSnW+1/mD4noGs44YQT5KKLLpKrrrpKvv/978uOO+4of/VXf5Ud/81vfiOvfvWrW+4/CECApCzKC8jrnJYHs6upaUUnaBIrFxjxCGOJQM0IsLjgoOs7usSDy3tKVTGhhwo1hsBE7YUSXIwJXWAFhsTNhOHtJaIFoMwGiHwAu+Wevs2hgJDkI2ymTTS9BcINCD0VeHAiQzCqgGRSBgGoirZB1fpDZNl3MfcsFFJQKNPvHAoIw21iIrHEajNCkv4Zz6SX1xb+RlkEdPKOEIObyBCMEmLrowaH9zyBHGzpJkvZBSE1SQORWru6elEJPZbt4QjaAEXS3v5la16BLrvsMjnllFPk6KOPlrFjx8rixYult7eupfjWt74lxx13XMv9BwEoICAgICBgtGI7tgF6xSteIT//+c/lxRdflLFjx+YCHH/3u9+VsWPHttx/EIAATXOB+aADonYhmqQgBZYZ/SoNEOw6VUwg2GXh5rWap69Qd18CrU9poN6kvDlfX+6HqRFvLpdxtMocz6AMNaFc0/ZgAMgYAhqq/F40MF2XVpeteNHqFLzi/SCVYcTLwQCEvSrgYd7YubGPFEmlPshgD2h6QNsyqIx0MdJorjuq8WAGzK2nUIF6zPWV1imPyLx2R6SRFoffo6b5KbF3BDUvxGMt/U0ZVaeuC7W4QCGmzZXCDO+dovjz90CBGFpba9BIUmAhEvRw2isLu+22W1v9BgEIUdM12gk/3ac72Y6R0kUyOsbyAvNxfceuU/UyLjIg9JT7mQAE5Vo9i9BMvcBQ9e3wwmAUnvo21QQgFfm2N7/IizTSXo6xC9Je6YeACb/dpNGKeHC1PgiOh/Uedj2urokwmgYx7IGHCW19VD0RgCxhaAwIQBiMED/iVXjuE8uaRwksdlkJRigfZP9IjLoGpsuV/wsHIWtCVEFjGKATe2sCZo/NBVnCKAPOM1YCENxTTDarR6q1hTkreh7qHXaNLGCqufEKbvDbBIIAFBAQEBAQMFqxHVNg3UYQgABRtfbnaEe1Iz6GhI4+nMHofM5jOXlqb4Ly1FJqX4eKWCTbfpVUzq/6YdTqlGEnjNqgkrGLKqz1MV7qhKi7MbYP5j5LywkLAldA+eGjKWGGoVvSUNo1dmGKL/OK64Tnlz0P1MaVDK2PiEhPzXNL1cFDxjQ9JSNyHmqIeiv1h30IU14gLYMajcF8HYNu09r943GALJUHHEYDZqS1MK8dvCep5qcHPOSUFgb6Rs2bNVemAVLUGFLXytC75oSAFJkytCb3PcmX6fpi0GEjGgdIJAgxXUIQgACloeEPuNNj1KFKFWnoo/na42yr6j0EIDr/2gEqqBEVfGQtAEToYcEILWHH6ne43i30GB60CjqiM5RV8lfDk4UIKZ0A80IxXXnJeaPSq8wSVNqgvdL21MUdzrOEHpG6vU9fuf4QMqoLYXlX4XnYX7VSf8iGeoCisZLajtQHk9kUWUCqiwhAJbCJq2CS15Ri9BCAXIlb8X6h7BJHtlCJnnjp/U1iIvR4vC7Zo8Cizhtr4YgLQAFdQQiEGBAQEBAQMEox0rnAFi5cKDNmzJBx48bJuHHjZObMmfKjH/0oO3722WdLFEXq74gjjnD2e8cdd8i0adOkr69Ppk2bJkuXLi16KzqOoAFC1LhWJfE7NA0Kjo0H0/Sotg5Njk8MFDqmAfpyODRANIYPjctj9K12XLbWx0V7sYCNKrghlNHjK9MMlY0fvAnMOC8Y64RQN/o3N3asTBOodtbEwL2AZqgjnmuOa2RaH+rZZeRPwy7Qmws1CqgBqhieXT7XGhe4dypQIhpVgyZkCOiwuFzTUChtRr0/VzZ7H9Dfnj3WpVTzSaguh9ZnuDxcj78FmwfSiqhhy4JVQls8roNY2jRZ+tzQIK4IsqaJodVxBWBNtuFs8HvvvbdceeWVst9++4mIyOLFi+Wkk06Sxx57TKZPny4iwwEKb7rppuwcjM1j4aGHHpIzzjhD/uEf/kFOPvlkWbp0qZx++unywAMPyOGHH15sgh1EEIAMWB9rH0HB2W9R9qJVe6AiQ1iCSUNZ2wnl62jwRqJfNNXHTOBiAlBe7pAYF0kV3Rm6QDqsnF88vW6pIQCpqTmiEzfWl9LgdsSbx2tB77BQ42xKrzEtgF0NSQ4bOXJzlYiggwEDmTt7GtyQUl0deHnww94DYw/CXKs1waKKbtNdpDETHz699rwj7VUGoaenxxbsUAhl9zUbmSVzpXO1+qiXMYhlHFvPENDE+DyyNc3w8iqxxMrGZi/ahiNBn3jiierfl19+uSxcuFAefvjhTADq6+uTSZMmefd57bXXyqxZs+Tiiy8WEZGLL75YVqxYIddee63cdtttnZt8QQQKLCAgICAgYJSiUxTY+vXr1V9/f3/zgUWkWq3KkiVLZOPGjSoH1/Lly2XChAmy//77y4c//GFZu3Zt034eeuihXMTm448/Xh588MHiN6SDCBogQBYI0aUBIpsf5ya8w4ZzjDpTcM2p1WtBrY+iMqAer9eIy0NtY5mq2hifxftRAQ+VFxjsFMvWj4sAjQzVlKV0DbaFHSo0xV1zYqjxRe1s7fHUrtnlNNSiooFqkzwMm+s5uGxNj44PUy+jp1Cq7fHR9DAPrnQeyquoRc0L8xjTVBzOv/7wDQ6lWkbUYNjjFNYQu0Df0doBpQGytT5YdmkZfbSQzOPLAt7rmNKo6TvsHFrnBcM1xuGUoTVDtd+z2gGNqy86RIFNmTJFVc+bN0/mz59vnvL444/LzJkzZfPmzTJ27FhZunSpTJs2TUREZs+eLaeddppMnTpVVq1aJXPnzpW3ve1t8uijj0pfX5/Z35o1a1RWd5HhRKdr1qxp48LaRxCAAHGPSNRrf3SpNxJGW2W0kfXwejzQrbIaXl5lrj7URFwNoKlBl4noRcQVbVvfOzaQw60XyyzwowUddc5uEltj28KLVwTp1J0aqRNLYmyckyq29kMzKqt+HMrwwWf2O6lQUCL0lqay7P4sryEmPGpTjvwHzkXVNEMqUDEZnH3AI0PIi+F3U7ItCsIeXm/1tvacfCLJp4I/elOhoFNSv/MIfug7BEbPu2x8aHJmEHa25kCIq1evlnHjxmX/ZsKKiMgBBxwgK1eulHXr1skdd9whZ511lqxYsUKmTZsmZ5xxRtbuwAMPlEMPPVSmTp0qd911l5xyyim0z6jhoU2SJFc30ggCUEBAQEBAwChFK55cjeeLSObV5YPe3t7MCPrQQw+VRx55RK677jr52te+lms7efJkmTp1qjzxxBO0v0mTJuW0PWvXrs1phUYaQQACJL3JcFoEDAiYaljJ7gGpFqUNsjygimiIpEGTU+QFYEK1Ue8TWNGpUWI7LrxPOP+0nnk6Me8x1Tw9QLbKPhog636w3yjKaxdEwBsEx6CagXq5ZKjKMG1CCbPZ46Qg+J6eXpKv9IHDgNnSZuTLrgCENn2l+nas8CrtRMIeTuM8KBfVBqW0iwqOSPRBjIpL69WjTr0B3SiUukQ9IPCbOjRAimIkHlydgFNbRRwIzHtAKWpYyx3pLWjcMqTAapRmvBVSYG1NIUmozdBzzz0nq1evlsmTJ9PzZ86cKffdd598+tOfzuruvfdeOfLII9ufXBsIAhAgiWrvC7pFp98VTKRH7DNcQfu8BCDWxmpbFK16lXVaS2m5nap7Z9M8ReZEBR1TgCOSmEoi1nwiKh8T5lQrI7dTL2qaIar9v34cP9yaESQUWKsRnY2PjLJbIrSX+kgadFeZjIeCDELngKrVKbsq90MYGUKIklvJnFigyaxeUXL2/JWAZjxk6v7TUPJ2e+u3Q4FLOSR59J26wTPbLEQnhB6X3Q+jAVv21FPvrTjLWXBD5e6e5I6LwIZ4JJnBERaALrnkEpk9e7ZMmTJFNmzYIEuWLJHly5fLsmXL5KWXXpL58+fLqaeeKpMnT5Ynn3xSLrnkEtljjz3k5JNPzvo488wzZa+99pIFCxaIiMh5550nb3nLW+Sqq66Sk046SX7wgx/I/fffLw888EAbF9Y+ggCEiOCvhuzZwR05Zk1XAhAxsjNcx2k6Cuy6m8LQSMO4FhX7x0OLZGa299BUUQ2WQxii0WUt4JpbwiSZzTNhi9gxa1h8lSqmAehA7J+yFX9HzQPKxGaniGYF518FKRXr45owYQlFjXAJZSwKsQKNX5PODYQe0h9L4mlBCVxGXByRhsdUCUNNu+b3CYWd1MicaeOI1ofaKznAfkcrFYaacyEpo/namytbNkCsLa5TW7ENkC+effZZmTNnjjzzzDMyfvx4mTFjhixbtkxmzZolmzZtkscff1xuvvlmWbdunUyePFmOOeYYuf3222XnnXfO+njqqaekBOvgkUceKUuWLJEvfOELMnfuXHn1q18tt99++xaNASQSBKCAgICAgIBRi07ZAPnixhtvpMd22GEHueeee5x9LF++PFf3nve8R97znvcUm0yXEQQgRDNVo5etDKFuaoIweg8pGo0F+2Nlo87HpsiqL/xiufrAOSnuPF92eVp4oaitj/EbKfqNGWsgiI2BdbgagUs0UKvKZqSSRtVF9b/dYxnd+wv8dkxzUFLaheGydif3H0OkvtuvKq0VasTq9SpistHGRzOAmg28HxVJAyGC9sFDZao1Hul4bu2O0mAVcPUuqvWxtG3U7gdh5P1SdlwdViez+5QYmjKVC0y3dvZnNOU5vUjy5XpyZnsNsjRDI5oLbIQpsO0JQQACZJK2B11fP8ldzrojApKyLyIvb7YY0481mZ+DiisiLCF8bJh4ZvjaAkwEJLa4WHQXpb2IMGT+nj4fEISyJajZ7yghtmQ2rULS1SE0DDYoiTKhJDrtNVqEvmIf80HMip7SV0TQQWGoOgT3CbOpp+cSBtKic0RErWZWQtWo7P4oK7oms4myhSwE0nmxoinzbeleihmfG/VM6KFxopQQbVFg2AeZoAP0PpL5uYRDL5f+JP+soClCVAXhigk1Ves42ZClk2r1JgWMKgQBKCAgICAgYJQiShKJ2hC42jl3W0cQgBBxNPynNlGpxF+vK+otlUU+Vq7SQv5B1P61HYvKW4UaIpwzMyhOy8wAm0WodWiMWLAx1ACpckqBDcIui3mBuVQeROvjleQlafi/T1vRu8qMRquyeYLGowJ0mGGwi8b1SIcxntLSDDC0qunhVIaYbVLtx+BQ/WKo1gfKCd6/TAOE3A9oYUrkfqg2+bmxa2HaipTGUxQY8VJi98MFpvWxjNP5nN0azMgIYVAi97HT8NEMZccxGapHf1kuPtD6lAjtpcqGyzulvYxXcVv2AtueEAQgC+qByS9mKnYHE4yYJrpppag3C6mx7DATekh3CgaN5pV4FBcAqw7LSGspCgwW4KG8UFkYtY9SEtk3gf4W1ofKS9dulyOTAgMVPLRF77AhgQytaV2lfrxCsp/jR6sHdPZWRFWVSiB3tDi0cGB7cFUND64YhJuElEVRYGmBePbgnJT3GJaH+8MhmF2NS3hJ2DsOiFmcIgM8Ori7Td1zisyPLQooS/p4xjmQZMKhWyB09YFggjwVxNNLQQ9cpMCYMKRiAtWoTqS92IYsYJtCEIACAgICAgJGKUbaC2x7QhCAAOaDZj48qBKHWrXjSvJtmME0DmfRbwKaDjaejzFzAQ2Q2gG5olqTnF9IcaEGKNUSRTS4oA3TmJlRYGwTrrQzNeoJd49FVwvH/VC7UeBAcUeb3rIYElLGEKW3RLRBiWH0y2ixIobUKvA0iQNjxe0REanWNDlo1MzKSutTNXbtNKoxVMN5Kv5S6ulEtTv+mgblpcQCBjq0H0yzweIYubRVlNrzoMCsZ6VV+NB9Cbk3lhap6Jjpu4sUNKW9iBeY5dnlE41+xBAosK4hCECIuPbgWw8MW1iYIIOeXYZJA3fNJjZAFvfssM1pbO980T0WiyyKs7KJScy2LLS8uaCQG+ny8lJCETtPdZgvq/koew+sZzeYjGOMp+yEBrDJsL1MdRA+5hiNXAl2cK9BMMpkq4L0SqFAvw67H5H6B0lRXZi+YwjeCyyTIKLWRBN8lkpYDwJazb7Ix52cfYBbjUTsEjDZ2D4BD83ggR4Pu3Xt7SQ6tdNRFBSGjPMw0jmzHYoNAUiUfQ8IrCqTO7RxJEOltJex4QnYehEEoICAgICAgFGKQIF1D0EAQsTDf5aWxechUvSVYawcWRSOiHvLCPPwgktLpLQS9TLV2Bg5cqhB4VACZRzb/wKKpLSgnl+M7TAMmBVdiRNhP4ulGSK/oaLDVKyjvOZC5Q1j143BEkv5euUhReYfsTatKTzM+5uQWCxKC6Y0kYbxsaoilJC2cs7VIy2m4muC9szHYTAF0wq56CQfTY8PvZaWvQyOiQazVSPoIhojn3g/RSiwhK1pBgWGzhfK28tIaipSp+KZ9+wW1/YECqxrCAIQoFStqUmtyJ8+LwT5aGUfaRapGLtmHyQHBUb5bSviqY+bKEsMWCRomAuUbqoXdUDDKFfvDHLYOCQKpsY8lHCAbUuOuWJ+OBasEmDNlQUSj4wFv7Hv9D5Y3mD5gdxNCsGyebEETdKWQT3+jN8k9laprRFuOrTggZIHFAt85FlbS9gpSr9xu5na/z3uqTOhqsePwfKCWeeqEAHkISsSIoCdVzVsx0pIe7FM7s7ozvYL6GGh0FUEDVD3UGTzExAQEBAQEBCwTSBogACloWH1aeQw+vXZxVoeSRjojqVqYDSZ5X2l0k54aHLSnY6PYaCl9cH2TOuj71Nzy3EfrQ9NL1Jqfpx7gUGTdBeoNtPwjzKbP3ZSuxb0sjHySeX7IP3xqjwcVt+0D58cZ83qPMDG9goimtJ57ES4qWp3rjzuhv+PMYjQYFqVE7fmIptaAa0PzsPHO89Ha5J63BUNvNiJFCqt5gtTc1UHav/zsQCwDJ9FJKoZu5cI1eWj4c7KjAKTfH0IhLhtIAhAgPLLIuVqo/pe/98XloCj1vAyKbs+/tYHXERRAVSosZKQKmGICDVGUDB6HOHy7PIQekwqUeqUFL2PzP7FsDXh3JMlgTbOKcn1yyIVU3RJrU5lLybMp4s7CYhZSKBijT1+57rRHJOiSNmgB5WbPOwumEBg5cdqVejBc5nQw4B2MxhJO9sHdYCLQYGrzGysmu9huLMUcdM3gx+S+TFPQ4wgLjXqqwQelDTHIK5vcb5MN28GVT/SVFigsbqDQIEFBAQEBAQEbHcIGiBA70aR8mDj7qBW8JHAC2grYqa5YFoMa8dBtEEug2jlAeEIDjZcNjQkBXckTg8uqvWBnR/ev0q+Du8dS39hGbhjY5xTrNKSQB8GN+mVesOgeYbLkkcntnzEWBhjrURG2gBML6KMxosEh2PJ6UgThSLXjvNXgUNrdRHRHDANIZQzbym8lILeXGkbH62Py/BZtfEIfqj7tsdxoQh1xmL1xAXnmkKlWMEAmvA7ppofpcmGGFtMG6Q0Q9ka7zE5Q3vddSSJ39yanR9gIghAgJ6NsVQG4oaAWMP/87FpcNn4MAEortgeKTH5oFvwC2iY5NvSMvGIKEAFUhufsnU8r2bGtsPlKFdPhUr2gbMCoOGlKhsstBnBTgw6rGTfLyrEFnBhb9V+IyHGF9oFH5rU6CLtMYS2Mtg5GzR3mh9czzcRCPTYMNeqns5wH0iHkXFMTzH3B8Rl4+NDK7EEp5b9S3vfw0j9X0QkIdfIAzIO/x9pNJ2LrTntpccgAjLOD8MdIN01MFwuE6En8vECM9Z4aia3BSiw4AXWPQQKLCAgICAgIGC7Q9AAAXpeiqXSEzslZp9AfUpbURMzY7jbJTgeAyWFGoiS0mg4dlGK1sDJSq7eMvIebmsb+ir71DTeDIn3w7Q3mh6Mcm0ZfWjRXiIicU++jhnYKq0P7AjTXSMeV3PG5wDnZGqJfHgIR5nRRi2m4VCHPbRSmWErpqggqQnUONazYCuRugt1m2raLEX9wVGkxuDHrRr3pgSauXKL22mq9SEegy7D4eLjA51U086UkD4skzEcRs5IUw1hzjfitYWIDGcBFu8nHqq/mFF/vb7cP/x/RXtBIEQr4GFj2aVOMzXVnXCr80UihU0OcucHmAgCEKDnpSGpVIZ0ZabytGkqFiBP0zW1BWfQPh4b1M5w30aZvXfsG+m01Wjx7WC0PhVqjPtEhB5VxvuEAlBKgUEdCy6JH+h0wRQRqWzOH2eBFZOK/Rul6nslODEom5y8hIBUgM89LbSyoaCD9wmvPT1OPsSUAnNxB9rFyzlV5/e+SH/oBq+eWfAIAwOpWNGew+UYnt0SHC8V9fYzwIQblWzWsg3ysvuxhZDUlT6GZxAFP59gkOn8hqplqLOT3hKHKqizhWwV8HAAhB5FgdXqmABENj9mslMmtBub3BGlwGIpZHpgnR9gI1BgAQEBAQEBAdsdggbIgpL4a3SNQWkNt7XrrfaoBVHDES8ltQtJd2ssfQSBsw3LYaXsZxOzvl4JbZUGi9wbKy4S0/r0QH0lX2ZaHzSEVFqfTfVyz8aahw7sGHUfoA0gKRdkx1oVHNbPhweVlVYrjyY4THamkRWniGqLCCyDZxdV11h2dKua+jja1Nq0tcu2jLEJ9asMbEuoxRg+oQoBMb3SacCQ6U9aNOBhxwHXHmfaG/vlQUaTGSin2h6lpVGGz/Y0lIF4qj0lWp/qAKG9Nuc1QFrrA78Rif3DozNmE60ftt6pEdQABQqsewgCECIa/kO6K/0Ys5xUQgQj05XbUKXmQD4ydUsTIox45NVyje2Viyo9znKZOYQeLDN394TZ/VhllAFQrc0EoJfr5d4NSe04BL+Day1VbSMmLYilAjI2tW2pnPQlEbIwarEWqKCL1DaLCl8e82icj3e9/9eA0WhdW6NZx0bUaBHRlGBKgZFgiui1pzzujNvBhB6WKLQjwPvLXMpbRDrvxMPzKyLPYeQQgJJBEHoGQOiB97lcE3y03Y9dNmkvKHttKI0chN1G8ALrHoIAFBAQEBAQMFoR4gB1DUEAAlR7SxJVSqaGJ/agdlxaGLpr8NEMWfmzfPrw6TtrAKe5DOdIv8yDy9SgEeqsCrQXDRiZ9odzRmPnzfUy0l69G+sX1vNStXa8fiKqzEsDWAZ1PAZiq+1GB3eGXWwf7Ir7QEsAVIp6FixjWmrnSw5ksV2QoiGnuVy0cPeOmhIPOszabVI6rMCUugrUXCBNkhoLwzMRw29YVVokNFqud9EJRYEZl4n9tvS5geqaRqvaxuxSrU3MPLyQ6sI8eYbBs6K9+uE921QvVzbVx8F3O/MCG2S0F8ypAIWroKjmhv8HbNUIAhCg2leSqKfUYL9Te9GJt5ESljyEEBM+L6OLyvISohxj42LhmI5PtGaXPZASlgz7HpEGGyDD00oFegRPkAoskqmtj8hwqIN6eVg/Xn65rj+PBuo68/LG+oA9G+oT6dlYL2/ebXiym0FFPzi2PvbQTiAYjanXx70GTaZ+zw7s2pjQQz+eFtcJZRUo00MwssYgSU1HHMyuCj/oNUlG5RPzoMNi3Dw4ZAxXrq2G6WXCRKJsBeFZErIekajgKYbgxW3VwzuCPGpK6FGJgmFO6diwuZDNIPS8DEIPbGIqSgCq2fFR2su2AdJ2l7V/4LrPNnhRvq7bCBRY9xAEoICAgICAgNGKYATdNQQBCFDtrWmAlLbHosDssuU91lhfb2DPIWpxV+wcT+q7Fh0IkenJHQMqQ3ExyxjfSIx7xrRFVItk2AKXjMCGIiKVTaD12ZjX+ojUNT/Ry/UTowHQBmHMF2hT6u+rlwfH1OZRf2j6IWYJdCeDY0EbtEO9PtUMIUWGu1FqzIzIso6z41BURtr5E5hGx4cC22rAqCLLcFhRZBjsz6bDyvist/g+YyyeWP3+w+OgtiWBRShiKVkMlYUKUFhU+5iuJeq5yh8XabgWNHiuUckJaIBKm21vL6SxkQJLjZ91wEOYB3tOrXXPR3O+JQIhBnQNQQACxL2RVHsj22PJh/bySO5pQdtI4InOKZMOSX2i/te0KfXeNuyZ6L1x2QM5vMRyczIWtpLDxV1EpLKxzpOVN9UFoKi/JgANghSFH6yqHUY4AtV8b62+NFgXiiqb6q9VD9Bo/eOAJgNqbKgmGFXHwAcVygnQgKLsiJBmqBVK9g/HPHEUMv0+NI2N48K/kYVc2DstRLkebK8PXPMGynsaBSOkgdVPUBNY2uAhLNdxTa2BMIS0HBMEHGPoA9gGyjUBTNcZ8xQtfFXBfm6ov/aebAKbOigj7VVWnl8wTprPT+VvJFRXEYwi+SZQYN1DEIACAgICAgJGK4IXWNcQBCBA3CMS9dgGvlS746P1KWA45zIobUuar53LPLx8+k4MDRBL5UFpQyMbPLuPan5GnJ8K7Ax7Xq5fQC8YO1dermt4kMqK+mv1aLVaJUnOBsFTbAi0SDWOqxf6LW+sWzv3bOyFeQBNNh5psuELHtjZfoCqaocPc7K0PUWM7wm8qC6mIewELK6WKLC00W/3F3oW7C9W2jFb+5EdJ9oRBk0z1ahOFnhRiAV2EcqHjW0YOTMDZwSOXB3MGzyXgfaqUGPnelnF/Klpg6iBM9MG+ajBA7Z5BAEIUO2JRHoi8yPi5XHlUd+0TpoI6xZ95bPeWx8q9iHzSIxqCYQ+ZTNRqY+gg67tsPClC2IazFBEpO/FeuOeF1EgQRsfQndljT2SelmGD9BXqb8+0cqL0HQQhbL6q9f34vDNGRxbv0lIkQ3uCLTBTgJlcB/eYXj8eAwEdewBwQnuf6TCAkN96uGEHl6YS6uAfOETCZpFQDflH2KzQ4UhJ+fT/LACtRHCqNHs5JQqAnsyjxtp5v8SIjAh64zeaOrHbS6I6Xp7Ti4aNSbBFmMIaJgAPVyq0cOVl+rn9bxU7w+DlpYxJIVh7+Nlt0aEpNGuHwkUWPcQBKCAgICAgIDRikTak9KCAEQRBCBASoEpuOgrD8rBPNdHX2yd5rGzZjtka0yfnZNFVVmUVmO90sAbGiCf7O2oDUKjyJTi6nuh3rgXtT4b6vrzjOoSsSku6spC2ljA3eXmugaojOWX6hfcU4Fdce/wa1jdsf7wDe1YfzUHxtXLm3etn7d59/qcBuJUM4dG0qC9Ibb1idL26P+LeNKlRZQtqOkh9FU6Jh5X8yeeTlZqmKSdjO2GxlRnWAdtC2aRh3IabFAZBZPHjWl/XTSZotTgnuls9f4/ksp31vwsTW+RgIYC5ZKKrRXV/l9vilof9ORUGiAMemj8RjrnF5lsQIAEAUghKRkf5SL0lY+Q5IKjrRcFxpiA1EyE0F7UJd5I+OrjCef0fiNeKiWkvYD77wXPrt4Nwyf3vFQXMEoY0HAQkzrhBRtfH5XU0v46We7iDJHmLMyyml8tcm1lCGwsBsBzDXKVlQcqUK5/TFKX4QGoG9wZaAigxpIKzAMSvqbJXyOWBNaHYbLqye3XMCQBZqeR2M+eDghYq0KbHWY/ReZqecWx/Fo4D4ywXK5JfLgBiNBeyMMeyLylXgaFjsMe3AhrEVdL6v8iIlUI/6CEHvDsqmysTyoVdrTdDwg96O2FwQ0daxqCerPiu1i7UQn5nbc0AgXWPQQBKCAgICAgYLQiTmwj9iLnB5gIAlAjInFrYXyUAQU0OQVOo/NQ5zl2Q0xFzHYKLo826sHloPlUU6L1UQENXwIj5/XD2h40cEbjYxlCHkdZicJAtUBs6jhOinAVDm1QwjRAmKMId6CpF5pS89fnX9oENNomSMmxATzM+ofrX4Y4K6jJUdqgPhwbtBFpUDkVU0Xc8HiGzP4Y5ZrOieVLI45OiaKhjPMUDYi/Ofad184kxJaYpZ1ApNQYXgp9b7ENW2Ss++tjtOxubg6hKT+g9mqGzTF6dfVDPB8MaPgyaICQ4tpY+z9SXf34DsCcGa1lgBk+M4+wkUxr0RJG2AZo4cKFsnDhQnnyySdFRGT69OnyxS9+UWbPnp1r+5GPfES+/vWvyzXXXCPnn39+036vvfZaWbhwoTz11FOyxx57yHve8x5ZsGCBjBkzpul53UQQgCw4FplOvDydeOeKuitbNg1FXUPNvFUMjHlKPyho36PyeAHVhbm7IKBhZWMtiOFm0I0zoQfLEKY3+2AWFHqcdBh+iBP7Zifgep8Jf7hAYxBGuK4S0GQ9/ZgILe2jLiBFIJmWQBjC/GSJ8bswu59Cz7rHoqu6q+YPaPotT8M2zsm0EyLCLbqRU8/FtItyrgqnmavXTnY1IVslqcVyB1YC9Z4RSs2yASO/UcwiX8MzlKSCDwo9/Sj01Nv2bKz3rW18av8nLu4+Qk/dBgiFerHLdF1Masc9hM6Mnt12tSp77723XHnllbLffvuJiMjixYvlpJNOkscee0ymT5+etfv+978vv/jFL2TPPfd09vmd73xHLrroIvnWt74lRx55pPzhD3+Qs88+W0RErrnmmq5chw+CABQQEBAQEDBKEUmbNkAF25944onq35dffrksXLhQHn744UwAevrpp+UTn/iE3HPPPfKOd7zD2edDDz0kb37zm+X973+/iIjss88+8r73vU9++ctfFpxdZzGqBaD58+fLpZdequomTpwoa9asEZHhXdWll14qX//61+WFF16Qww8/XL7yla8oKbUIori2GzeeGBbXx0oTIeKxAS76VLb4ApgGg2SHxDsxyg56K9fEiO2Duz3U+mBAQ6S9yhsxAOFwOWIGzkWMmRWl4qO6IJSZ0Z+iZbBNCTVRxq5S7Vxt6kwgplHPuuFtdIQ0W7VOkZVIfrIYvB4TIwQSy8VGqU7j9tHFm+3qraYeDKSeX82w1SOAKfViTAN2QiwkqeBvBNoWlccNNX017QLJjs5STVA4v4T+C4sK6ohlvF4wcpZBeJZrz1NpoF6HWh/U9DANUE+N+ioh9QvPrx/9Wru/+A4z2ovmPaw9KypOEGpxPebRTXQoEvT69etVdV9fn/T19VlnZKhWq/Ld735XNm7cKDNnzhQRkTiOZc6cOfJ3f/d33t/ao446Sm655Rb55S9/KYcddpj86U9/krvvvlvOOuusFi6ocxjVApDIMP94//33Z/8uQ6C6q6++Wr785S/LokWLZP/995fLLrtMZs2aJb///e9l5513LjxWFBsCgfXBx4WU8e8OOqnVx9mH9qKu7RbFQVTHMSaEVdfruBhjvMZyKvigayvaAVQU1QVRnDcZXl64MIDQk6CtD3G3F0v4Y8JQEapCh+atz4lQapGlVldUBlSjgAPUWLRxWADqUYEeYUpVpMbq79DQjvU2aRMlFOFlo4DUKnNTQBhicffoO2f9g72rWI+RzK2I5Sgg4e+JQjYKRigApWUVngDnYVNjzC291Rtv2vLgDUGhB6guFHpQiC71D9cr6tqw7xER6X3JtvFJy8wr1QeZXaPHumO+7yL1W2pRXaqBPd7WgilTpqh/z5s3T+bPn2+2ffzxx2XmzJmyefNmGTt2rCxdulSmTZsmIiJXXXWVVCoV+dSnPuU99nvf+1753//9XznqqKMkSRIZGhqSj370o3LRRRe1fD2dwKgXgCqVikyaNClXnySJXHvttfL5z39eTjnlFBEZ5ionTpwot956q3zkIx8Z6akGBAQEBAR0FJ1yg1+9erWMGzcuq2+m/TnggANk5cqVsm7dOrnjjjvkrLPOkhUrVsimTZvkuuuuk1//+teF7NeWL18ul19+udxwww1y+OGHyx//+Ec577zzZPLkyTJ37tyWr61djHoB6IknnpA999xT+vr65PDDD5crrrhC9t13X1m1apWsWbNGjjvuuKxtX1+fHH300fLggw+2JAC1ogHy0gwl+eOUQXJplFrU+gyX8+rioi9Wqq1IiIo4Ih5EGMcj1fzgbrACsW4qm0GzAfFwIszZle7Q2EtItDCRQ5XMtDS0b1Mjhhfe2jzY2KiNiJQLVO23Be+xykv17XlSAQ+eXsIFgTYoAw6BWkFkGQzaSO22PbQ+1vPLTvMJwuh6rr1S2FhpX0BbpHLdgQZI3aeaBihhGqISeVZQY4QTd31zyL1RMYtq5YhofdBgvgQaHkV31QyXy5CvS9FbQGMjva2MnA1KvjDSrpG+wnLVrlcopfMhtJd62FPtWSuTbRFJm+PVzh03bpwSgJqht7c3M4I+9NBD5ZFHHpHrrrtOXve618natWvlla98Zda2Wq3KBRdcINdee23mOdaIuXPnypw5c+RDH/qQiIgcdNBBsnHjRvmbv/kb+fznPy+lElPTdxejWgA6/PDD5eabb5b9999fnn32WbnsssvkyCOPlP/7f/9vZgc0ceJEdc7EiRPlz3/+c9N++/v7pb+/7nqQcqOWAJTlJSooAJn5xJrOKn+anojjRB9hyFLftvpieaitURjC6K2pAFTZBAH+oFwC76YSUjpDzVdKr2CFOoNlbRAPoadFl3gv7r6IMIT2TCBlRGl+JPQYe6n+dcIA5zFEodZ2MTWPJSL0RIr+wflBvbVhIMIQpbWsD6OP4G9RHx7vBYXBFGnhBobuiUi9ddwWhhTFiAKQWkuMidMPN5yGOd2qeQEowg1KPwhAmHgUhKE0KjsmLFVUFwloaKIN+xZLiIqYMBTb9zSLgK4ijJMNnsNTcltFkiTS398vc+bMkWOPPVYdO/7442XOnDlyzjnn0PNffvnlnJBTLpclSRIdNmSEMaoFIIw7cNBBB8nMmTPl1a9+tSxevFiOOOIIEZGcGi5JEqdqbsGCBTnj6oCAgICAgNGGKEncGmPH+UVwySWXyOzZs2XKlCmyYcMGWbJkiSxfvlyWLVsmu+++u+y+++6qfU9Pj0yaNEkOOOCArO7MM8+UvfbaSxYsWCAiw55lX/7yl+Xggw/OKLC5c+fKu971LmXXO9IY1QJQI3baaSc56KCD5IknnpB3v/vdIiKyZs0amTx5ctZm7dq1Oa1QIy6++GL5zGc+k/17/fr1wwZihqoxE6XszUExzVBBQ2oTbEfL2pi74sQ8XmR8HbjOHg89OnQm9+F65f0BmdJVDJyYqZdq9ITLI0uaLABWIMQy9geeWmX7R0/PpWN4edmlqoaifGTe6Fup+XH3i9TYy/Xtfgx0WFyjyZhRMBrGszg6pvEx024zjYxBGdMAPCxVR6q5Ra0VoX6Zpsl6LRN4joXcA6UBSu8pao5KeM/t8xg15kwvQzViqAGqdYvpJVBbi7QXvrdYrml+VOoKDGI4hAtEZ3f46hqrKa3vpr2wXt3TXKGhbaXIAt0FxOK3jjQ7vwCeffZZmTNnjjzzzDMyfvx4mTFjhixbtkxmzZrl3cdTTz2lND5f+MIXJIoi+cIXviBPP/20vOIVr5ATTzxRLr/88mKT6zC2KgGov79ffve738lf/dVfyate9SqZNGmS3HfffXLwwQeLiMjAwICsWLFCrrrqqqb9MPe/KE6GXxhj4WXuzNROwWjjs567lgqf5KXaxifJte+E+lZ9aOHeoNCDC2zJSGZYBqEHc19FSHW5Fs82qOPsN/URelh9CiPHaiPa2cU5kU4PAj0KCpIgAJUhZ1qlF3I51crgMKaoG/w9lS2S5TnFNgMA9Q5YzzX5mNONhuO59tkwlAyvoaKRsa3AiszVXtWrsm1r5AxDgVCbEejCSnqL7yrSYUiBIY2d2gARoUcJHi0+9mqj6aL1ceyqXRbHnJjQ43w2tzHceOONhdpbdj/Lly9X/65UKjJv3jyZN29eGzPrPEa1AHThhRfKiSeeKK985Stl7dq1ctlll8n69evlrLPOkiiK5Pzzz5crrrhCXvOa18hrXvMaueKKK2THHXfMgi21DOvlgEqVpbr5aaqNj9DjXNc8FnGXBojaVrgMsPFcZdCNC069HhdEldiwVo6Y1qfqXl0y4YUGhUnybaXhEtOPjI/Qw+x+LKGGxe3ptABkXLsSTJQdA4wNdlXllyE7d802KK7U65Q2iMQEMjU8LLYOgRWRWj2aHi+alfiSRgXG59QQDrBeCQpV8hF1vPxaKCL3FLVtyh4o38bLhMm1DrDrhvdWbWLwfR7I1xVJVzF8guMwW9MMAQfXD9xAqTkRDVD6j6hsX0tkxAcaSTf4kabAtieMagHof/7nf+R973uf/L//9//kFa94hRxxxBHy8MMPy9SpU0VE5LOf/axs2rRJPvaxj2WBEO+9996WYgAFBAQEBASMOhimGYXPDzAxqgWgJUuWND0eRZHMnz+fBnMqimbxFrSipDVtUGEKzNGhteNtLJs0WRsvRBa0mMyjRNTqkaLG4tr/idqaRERWKEJ9Kb4/r+HxorqKBEIkgSY7ogEqkIcMg0GqaNKYaBXosB5n9GTUiEE92rxYNkAedBgi87z00WoSLYZF87Bnk9rC1J5PpiGiNI/j5U/Uy2rbW7mSDXvZVeFpxvxooFIVbBPbwDuc3V9yD1Dzghovl20AAaO17LXE1gbR2A21iWutjzFP7GMktSodigQdkMeoFoBGE5TRL9Z3QhhiC4BD6HEakUrji9z8RfChKiwjaK1qx0USF1KjTELW03la8XeKur7jB8dFgXkkQLWiOHeV9irSH94vtGPBDwTQYWnzCtg/YPyguGLcO7Gfm7iehUNnQmfG0waoUM8EIEOoaVXowXP1xxXPcwtAbqoEqVqopgJklK9rESzWDXcpN871oKuV7Q0ThrJKe346kjyuJcMHlNADAr6y60Fa3IgEEZXJhkEZVUe5+QRsvQgCUEBAQEBAwChFpyJBB+QRBCBAEg3/FXpgcJfi0Ab50FtMM2TRV5wisHem5nWxnaQy9HU0x+Nsh2xoezqiKfEwgnYFMfTS+hRx1WNg11iEXmt1aDQEL9njRdXhH6+8ua4eSWBXrIx3I5snS58x3HhDTlYd7M/FAzMNANPqoMdSrZ55MXEjaKRX8nVUO+KgwNr5CGlNSaqC9WmLEzAOkOeRhgiwtEFMu1rkkWZaH2WMbTtMpG2U1gdpLwyjgb+disadHre1PlvchiZQYF1DEIBagKLDqOcUqratxQcbu8cpMicvmszsxH88KnDRj4UxP/Zi+rywBWxhaL1BoyU+UaGtG8mEuS25+KgYSfZDq57TlPKBpLNsgUgiOyiQKxo3Jlplnk5muAbmwcXct1M3beV9CG097FzS8UvkmZYCXk80tQJrUwBsDVLPsnMXwzqH0yyBD29Bi8mDrbg+Ig1rCQpDGD6jJvgooUd5gaEAhBvU+sOXRoDWqXbguLG2Bq3KtoEgAAUEBAQEBIxSmDkqC54fYCMIQIho+E8pZ1qkwyyVvpPeaujC7IMZgzJjRebZkHbL4pMwz51sd56nCkQa6QmmUm5x+xQb//BJomcZPotIUklzX9nHVRetLiI+XmxWYtcu0mXOnGmwE44gL1slQhUKTAlUOaWh4fLgjvUxhuA0pMNQG5RYwf7gFuigmlCGvjEvVRqgj2mAWMwa633xokMKUKTcYBr+4XreWEJenAcJVmoy4URDxRwcsqZIrZLrUmchxWisJZT2MrQ+w/W1MtYN4ANn38jIMIiOqqD1IQ4a9YTSI6gCChRY1xAEIAdMl1yADx3W+uDGOB5UlzPbO3GxLeKurGwy1KJll12CGB2HvLz17NZ4sfak0X1beXyl2b4rbiEK1ftImWTDE287SoVi+3T4TiRO9QG7XOuDH9cvNrUREhHpgY9Tqb++jJQGhqWacn/9YzIwWL/u6hgQjMbUh1Gu9LWytgeB6RtU13C5fkKajZyFWkBQCsZF1TKbF9OeiQhcLPyDizLD1BZwATR0g7qZ+e4QJUJDmRs8FRzTFuBdHqOM3oowOnzVEHoEqK9BeCgGiQCk7m/9mU29vxIU/F0efkGm2CYQBKCAgICAgIDRikTaE7iCsEYRBCALnfD46RY8tD6uOSce6nNG0aW7thIJcqhoL6a9ScfHQH0l3MWyiRv9oXaHUTug4Yl7IM1DSoF1xAjdTfHR+1HIKnVkYRlJi4iKH6R+riw5LNTBAzc0BL/5EMQYQmrM+P2Z5xcm46xsqpfLA7X4MCopJ85TzHpXDitKE3cT1nOt3lWfWFhwakan25QbSwOhuks141iJfZBpWH2rlDiK9iIaIDR4TjU/qPVBbVAVA2DhRGCG1TSWEHmHzXtnd9sNhFQY3UMQgEYxzOitxGbAxwss+w4RQccnIKNlF1Ei0XFZAsvsI4KZsOEjyeRP60Wm2eBLttAT9yIdZlwwWfBZgllzcfEJPsnosGxu9mldRZpnCukVZf9Qn2iCAjCkSM/utDoPKDLlwQXUWB8IQ7Xm+NtqWqbeBwo9lX6k5YybSkI7sCCA2WFGExN7MQVXoEDsG++7CpBojEOeD2fATpE61cnyXTFBwHrX9AtqFfX9Hco/T0roQeGmSgIaDsEDMDSUrwMboCSxvcAivJb0XCr04L1Lcn0FbL0IAlBAQEBAQMBoRTCC7hqCAGShwPNSRA3u05aqVi3jO1pufgFF52F5fDHPDQWWgyvdfQHtVQVtTAmC70mPrYGwJ23H84l7MNVFfutMVcQ+8XxcqTDoThHaG3NCbQDFCGiJtJcP+S3UAzW8+y57pFZIPcZERIYG8ffKex6wAJsVMHwuDeQD5OmUHcW0e25vOUKvqb5rNA/VKJB6cdQzZodNxFgf0EBcBzkk75nSWuZd9ZQdOM65SvpOM7ljHYvhY2l9REwKLBnyoMDKaHVfaxPbY5uG4CMpUyTi9gp0nR9gIghAnmiL72/1XAdv7ww0yOZB7H7UIm1ExB0u1xZPXFfURwOqiyQThT6U9y6h1IrQYSyicya4MRsQZldlUQRKIGC2BIROSD1VSrawQb3bLCGpE0IR9qFoTOKmryiO9ATIMaY++D3QFoUXoCxrOcfw+WHJMMsDeN+hSKJdZ32wZwmv17BFYjYxrv58PLx8cnNZx3W9XW2Bf+Tdgr9zSWP3wyozAQmFHmbjU6O7koF6bAQlALENCAhA0VA+mKL2hMxThSNpVxNsgLqHLWFpEBAQEBAQEBCwRRE0QJ2EyzPDJ86Oi+JS2goos/OwOtL/b9ZW9W3tvkmcDKUBwl04UhGZJkqNSCZN5pfWsx0ejk1ykkVWHYl7onbLVqZomiKhgDYoYRozaItaIsmDUmetbnWYkS6l+YwdMmpsULM4iMbphnceahAVdUbGhntT7curb5iGswjtRd8Ll+cU06Sw+FHsGcoMmDsQ3pd6gRFtJjvX6IPBpvNI7i7U5DAj55rmB7U+CWqIEjKpQfRGHGo6DzM45khGV06kTRugjs1km0MQgBCJFH9YmNDj413l6tqwG+BCD5MUCoynBAGsJ2OmQ3sIPcq1OU1CWlAgVIJWej9wPPqBq9drbyLL/RXHI9RInF8oI6NORGgkWo3aOCwPWWQLc9orp+Z+zkZAwaiIMFR0oc8owXpVBP9QrvRwmgqMXXsO8VmiAgHcg7jkuEb222K9FcIYBT/j+RFpYk9j2IgVooca2jvhCHLJ50QG6eaH3qKPLfseEWrjk6Q2PkW9suC3S/uLhmxXe2sDyIJqdgXBCLprCBRYQEBAQEBAwHaHoAHqEkztRqu0F5S1dxaUfYR8Q73vClPfWBbDq0X1q7xuBMpGPUslQOaXKIogpY3sOas+aK6hdAdq0yHMOFPHKkkpQWYE7UEnpPcBDcsjEq+IGiJH+eOELusITcYoOmtueB/VPMSsz7Rq7FrxliLVRbwAs8OMOtOtcuOgVohpfZT2QBnQuoLsFdT6GO+OSu9Cflv9XFebz6kIPIIwUloxNt4dYvicIO1lpbpgVBfOQ73nhpY2hrGVgXieDhvRXGCxFNLkm+cHmAgCECISrwfNi+py0TtE0KGBDi3uueiildJGYn9YFO1F5pSdxkx2GB2m7keNAvP44Co5y7pcFmRN2ZrYi1kmzDFvGCb0qMBteRda5XrLbGVKxm+gPvg4TxSGpDksoaih74gIVF6u99Y4rnoPT6JEJSq1vNswlAHMGUIImEKPonVtuw41VQwsbtAc7FkyhWKBZ4sIhGquLFK4FTSzRJ5TH0+9dHyfZ5OhQFJepzs7Ul0WvSWirxGfhawAzzfmRsM1rQS0l3ou0oSqkPeuH8q9EMizMixwY6LWbiN4gXUPgQILCAgICAgI2O4QNECAJIr88uq0qvVh3VHqSfJlppkpIuSzGCM+VFx2IpSJpoel2ci80TzE74gFfEuVJiQWUmnQ1gaZofiLan1wx5q299H6IKx6lqNNqeuxjTIdNvpj1BlSlvkUJF7pFBAurY+6VnvnrCkwo7se+EdP/R8J5HlLKnmDeP17288EQ/2dI1oklsLBCvbnE1RTDe5YQNQ9sl9W55hFaRxjTixQptZ4wWSteD5Ib+F75JHHKyrnvf2wD6VlxN8I3qm0fQTzkN56ORqAzPE1bVDk5dzQIQQj6K4hCECIJhQY9eQqIvQUsPUREdPGR3vDOMYj8LEjctoUkaSQXCA0hCQfmyjsQt2n2odF2fS46QmT7mpV6BGpL9Lsg++y+xHxoxyy85RfevPjitYg/eFCXhOG2jE3qHv2EDsopPOUMQ8+fMYMgIZQQo8Kr5D31vIJcYCw2jD7L5fQIyLE44oMbtGiUvD38IpCXgCusACtCj0i9SCGbPNQIg+tNSdyvxL1XJF3pzY+epfh+x4N5L3DggC0bSBQYAEBAQEBAQHbHYIGCJBEnpoen3rVccP/pZG6cVNSmRF0G8K8bUSMZY/OS44YPsSzSxtHu4fJuqP3rDYdQm+VfKgPIxu1aeAMbUXEprt8tD4uKC2ZI2u9SIM2xQDVvMD8MA9ZuqvFOpcHD6un3m8FjLuVVxekysDcbixXmRHjicYSYsgcD1rU+uA4PtoYl5G8D1rV+hTRQjIwrc+AXVYpK1J4aEYjeDeybO9MIUOM/9E4OjOIhjlHLJ9Y+puPpBdY0AB1DUEAQjTzAiu6Phi0FssX5PrID/eRfljs40WEiraCPVp1lou7iE17QVk5KZHrYtFxU2FHe355eOg4KTBig+DKL1R0kVFB+8r5OhYIERE5PrQuukxE2xSlgo8PdYYocu1MGFLzSO8HDE48vxCmsIPXwoQUBoeNGE2A2wkaaiQ+sJ0Wepi3FxN60vcL7XgwdINh39OIqCZEJyw7rA/Sd8MIjiiibYO2SCDE4AbfNQQBKCAgICAgYJQiuMF3D0EAQnjGAfLRoFhUVtFM7krj0eoz3OJ5KoihohnSOmjsoQ1KYDNn0oxEA4RZ5y2KSxk+D9m7fVPrI1IPCKdiuKC6u8MLR2RofUREarFFGPXk5ZWVlmlARowlQ67LNOz0oOKcHkutUTtJJZ8fbHg8KBJtS6YhVDmdPLbCVjDCTqSoaAcuTU2ntUw+v1GmYYObgFQXSV2h2pfzz30UeagcYd4ZBeYTXJIgo8DQe4w5PWQUWFCrbAsIAlC7wA+3QXsN16eLMdT5lB00WqugfeBHVydIapwGt/VROb+g3qlutxctZr+TBqRjXjkRLmaG0KPaM9qrZWoHwGwaUNipfehV8s+S2w5HebhY0ZMZPaEcsfC+px8T9gH02B2k18gYCZ+PdXoNPSAAlYndD4lYboY4oB9zGNr6eLJAjkVd24ugCD1FbcTInKzAm+y8EhGc0+dpiOTrIpGbFa1VGz8qGvWczbVNoDeacqXHa3Q8E11BsAHqGoIAFBAQEBAQMFoRJ21QADKyBttbGYIAZMH1vPhofQz6yk8DhLtKu027oAbTaozmO1Bt7Az1Hh5hVkyjEmyyFO0FAQ1LqpyPx6EzssM8KAWWN34sDGt3xQyYLdpL6vROgrvjMumDjV2t/SAlfJhQU0I0Q5ZXVkwecLaQFkiLQGHs/BNyDyIPDaFJX9Gx60VMB2JeFfSnNFGkTUcMjX00ISmKeLr5aC1Zf1VDe8o8JbuJTOPY4Y88i2kUN/w/YKtGEIAQieSFH+v7VkDoGa7X/8+Xuy/0DHfY/HBCnC5Mmx2WyLTlsAB5+558Oe+t5czB1FBv0kLMQ4p+2AsstoT2UsH8elIKjAhAXuOkNhnwUcbfCIVK2onh4stoHuqZVqtXthweD3Jk3CfM+cSEdiYMtUpVGMJQRK/bQ4BwjV9UeEzbF/U0cwnqrC2lnvI58GhAw05QMGojAdX/f3vnHhzVVcfx791NNqG8FBCSAI0wdsqr0RqsjaUWK6VTsa06o30GrDojLY8ATguWjiAjDdppJ9URHLAyncEOTIVWdJA2WMB2sNABUnmMgjYUpMFMRR7aksfe4x/Ze/M72fPLuXezm2R3f5+ZnWzO3nvuOff5u7+nFwXmBDg3OUzXPzWHqeSXrED+ZOlCTGAZQwQgQRAEQei39FAASjUSJg+QTNCUhAbIccknYX7V2lxl/ihu+YQ2R9GPskr2KkI+UcsnwnyiTucnkvxxo/aPto7fV+c2/Oi5RCJJY0JJMndvf0XaQT7K/zhtrv+JtMb9D2132js+iCv/47iu/wH5cO1wVebt447T+YlEOj+03fsweDXquvsg2vFRBRHjB9Go/9HbyccfJ/loA1Hmj2m+FK4/C3R+3HWktZvGymHa/10/EXR8bL9H9LGG2g4zX/Y4pxPueHLH1nbP8q6n7q6pAPc9H+7aMLXTc4y9ziKdnzDE3c5PkDlmOevWrUNFRQWGDBmCIUOGoKqqCn/4wx+My373u9+F4zioq6uz9nvhwgXMmzcPpaWlKC4uxsSJE7Fjx440jz4cogEimG6knap02kYWYNqNYfBBwto5rbQtAzNdNtX7ZDrur8y+iWgRXN7fzp0Uae38PdpC28n3Nhqt1bE8n4COjIM16aRBjW0ytWgRXAEiXLwm6l9CTVYR0q71TYbhm0bMpgJ6pWtGHGqK9c1oTCh9GLTooZDr2h703JjCmHlCpBlQZAJacV7tAUyOEXow956SbtNTmD7C+juleLxMPlYOySpOzWEONaNqpkx6HXnXMDHnGSIKAdjN5pmgl01gY8aMwZo1a/CJT3wCAPD888/j7rvvxuHDhzF58mR/uZdffhn79+9HWVmZtc/W1lbcdtttGDlyJH7zm99gzJgxOHPmDAYPHhxuLmlGBCBBEARB6K+4nsqzJ+sH584779T+X716NdatW4c333zTF4DOnj2L+fPn45VXXsGsWbOsff7qV7/C+fPnsW/fPhQWFgIAysvLQ40rE4gARPAzbppeTDitjyVvT1K79zP3ssTl1/FeWLS3fq4Ppj0MNt/NIPtDS0zX2e4nMdS0Pp2v1hFSfVnT+lAnaJPmRVne2gD7zYBTj7O1rSxYtD5cf7qWhjo2E02DqT/aRMtHUHVQlGoiqdevYZ+GxXeC5ubNaCgM+13TiGllJ0I4GTNo+44p3+Jp4TQtAtUG0RU5p9hIivvSpmDgxs9FQ6VDGxTmQcocf0UjMtNh0vP7SNYKdTcOri5YZyNzvXtBFHmSCDEej+PFF1/E//73P1RVVQEAXNdFdXU1Hn30UU0j1B3bt29HVVUV5s2bh9/+9rf42Mc+hvvvvx9Lly5FNEDJk0whAhDB7EuQ+C2IcMO2d6/q5QqFmkLNA0VcpeFep3VtmBdXtNVk6gK6RHMlTFyaqauFZmE1Cy/WJHWc2YvDJOxwid96A06Y09T4dHl6czd0R+sq6T+YvgLRRIQLbeQyS9vQHjzUDEgfJow50ijcIvn3brfpJC8bROihD8mooQtlvm7pMUpLAk0miM4bX6+VN7C+MFDhnAqKzOKREP43EUbANJnD6HVLBRrShyZQk7F6wpBREALMSRFdQyHXTKHcnpncEuteunRJay4qKkJRUZFxlSNHjqCqqgpXrlzBoEGD8NJLL2HSpEkAgB//+McoKCjAwoULAw/hnXfewWuvvYYHHngAO3bswMmTJzFv3jy0t7fjBz/4QYoT6zkiAAmCIAhCfyVNPkBjx47VmlesWIGVK1caV7n22mvR0NCACxcuYOvWrZgzZw727t2LDz/8EM8++ywOHToUSoPnui5GjhyJ9evXIxqNorKyEu+99x6eeuopEYD6C6logLT1w2h9GE2PS2tmRbp/w2cJ86LOvWXb+g6r9SHOzFFfA2Q2ezltIZKoaaYRztmZe8s2mZA404J9+yljfbmjb7+dJ4hmDvNOENYxnvxATGOaOcnLqaLlWQm5T/2K8qSNc4jmbqB+bSbOpBlCZR7gJq3tmxCO5Q6ZTLA8S97CjFaKWyZVbLmCwpbQCAPV3nBJEU3aIG5/cNogA5omios20e6t3vIk9w9TYqWzFlgvaofT5AN05swZDBkyxG/mtD8AEIvFfCfoqVOn4q233sKzzz6LiRMnorm5GVdffbW/bDwex/e+9z3U1dXh1KlTxv5KS0tRWFiombsmTpyIc+fOobW1FbFYLPX59QARgChBzzPOpUEzTyXfVDmhhys8yiZ/87pNxzXImO1sWau1ulwG/x6gawQXFZISSQxbmSyy6YDzQTElGMzkQ4iDE9xMi4IKLAahJyzcvvG+0/NOK4yZ5u1xF1tijnoyS2q2oycqHZ7hOHOnFSf0UOHQNfxOi7JqVhlyXDRhzWCy4iKaOOh8TfMJk/2ZW4/CmVtMvjCanxbjd8fhn29UwGRq4HFRlqbt0PNXWc51EBNYEP+/vjCBpQkvrD0VlFJoaWlBdXU1ZsyYof12++23o7q6Gg899BC7/k033YQXXngBrusikjh+J06cQGlpaZ8JP4AIQIIgCILQf+nlMPjHH38cd9xxB8aOHYvLly9j8+bN2LNnD3bu3Inhw4dj+PDh2vKFhYUoKSnBtdde67fNnj0bo0ePRm1tLQDg4Ycfxs9+9jPU1NRgwYIFOHnyJJ588slQfkSZQAQggpfEMNxK5maTY7Ou9WE0PZyTs2FctEkbd4rO0Zqmh6r0NXVwx1+q9dG1QebvJnMXNXVl1KkzSG4RjzA5ZtKFtW+7hqozFoYxm7Jay2StiVY3jNPe2MasmVe4vEgW8xqTj0h3ZrUcW5v2hFsPMJaG0Xej2VNZiw5LXJja7qLXGe08wDlmi37U0DRDWsIn63aMfZs0TVyEZRBHde8c4bQ+QTSz3rqMxkkzh3FmucQyWmQYmYv2PaEBUr3qBI0eCkDhFv/Xv/6F6upqNDU1YejQoaioqMDOnTtx2223Be7j9OnTvqYH6PA/evXVV7F48WJUVFRg9OjRqKmpwdKlS8MNLs2IAEQwZjC2wVkIjAKQOYIkUD5uQ7RnEIyBQoHMXmYTl9kERh5OWnJD19ju1e8KIvRoUTk2vyrywHK4nWoyRXCRZOygDOOgN2AurFMzIdCbePf7wYnT84aOlT5MEmYjurkAJjLrPmVCh0Ml+GPqodlMLVpxU5ICgT7ItPkaxq3tgah5WbauneF3Dc1HzJBYDzDPhZrLaHM6/MxSTfRpC/tOak+uBRZonOTacLzvYQUgSoqRicYEiVpkGJ0X+d6WuBmq7DOBBeW5554LtbzJ72fPnj1JbVVVVXjzzTdTHFVmEAHIhklJYBF0OpYxaHi49QJc5zbNVJCcQF4XQXL4mISeju8dK1DHZ4dqfQwV2wEg0ko6NOQqCZLmn62+7TcygoJ2k0xeU3/whJQwTW+e3Fsz1aTR8RkefHqeGrPgpPudJGs82D0aKo+RNihzu8mXJIjWzWGEIa8/Wmmc+uZQgZBKNQUGv7sgmaC5FxDfN4TRqmlvF4xw6z9cmWNItVlcygcTnLaF9esx+02F6jue7LOn2tqNv2tzMQk9AFCQePzQtrBpKHxNH+MXxPmwGQQta24gEA1QbwpAvWwCyydEABIEQRCE/orrokc1VfIkaWMqiABEcZD0dmRWiVt+77JMysNhNDX2FS3jYH2E6JsfWdzgA8Sby6ipK7l2FxDg7ZZ7IzclhOu+p8QGu/ddseQTTB8h6jTpmgHSbsmqq/mlpJqFOIB5SNtPFhOunlyQSRhozMZLzhnGHKaNlZ4fnkYgyAFl5+tpF0i/Yet8mZRj9OdkV5TkvrWkoxYfoFQzllO4vsn55icHZLahJTykGh56/L1loswJxO0P01g1jan5HOP8gfyab6b6YIC+T/15i1CRC4gARPCrm2uN3a/jmGUGPXeEXx6ALBvS1G0dTwCznCmHDwcrfPnOj0ToiZsfVA6Xlt/rKmwqfMMNkS1kGaS/dDwgrMvSGyXjG2RS9Ws3bmryIY7jpD/ln2LkIRXIucwCV/CTlucwrMaWmlDMg0pb2fCQp74o1BzWzhxp786mmbrSLN5yghHBFEof2sxKcQ37Jog5zDT3IA9xzsnZ+85pF6jZq5A8ZhJ1oAAABYllWKdsJt08xZbx2+R0zS1DM6fTjN9ESPUcolVvmpXEBJYxRAASBEEQhP6KCEAZQwQgght14ESd8NmRPVJ9wezeR5ffBmeK4zRN3hcu7J7bpCGARQ+Zp1ofex0vo9YmDcqKjGJzyAxh3mL74/og+5RGt2naoIQ2hWp9HDCmIm6bXhPnbM5pg0xmIa7WFhepZ9pnzP5waEQYHRNxjvYcxLXtaSYyuqGMGj6T0Pev/VwxZjjXrjPqnJxmsxeX6NB0vKjWp8Ci9QE6naC5cWg1vehxtjjdc0kTtXaDmpxz0E9LxlmhPyICEMEtBJxCXf1pJIgZyrRaGvyFAkV7ccJQYtxa+hUuN5FWdZx05wtAjKmLMXulReihz/MQD0wWL0S5t96ubCUQAvheUDQ1vXcPj5oPLmuSsqCHwQco+Gl6WDDCly4MkX8MWYY16LnXzphgfFMtY3IzZQTv2u7t3yBhmiYzMf3O5DHSzj2Trw/bX4D8O7aQci0Kj9p5ApjUPDhTF83uywlAftkU+7muEcZ0zuwPU7kMY2g8ulxnvV0gGUhbKQwhGRGABEEQBKGfopSra99SWF8wIwIQwS0EnBi6vM11v04Y7WiqpZQ6NtR9WxDNkGcC4PIV6bYuy3CYt3D2jdakdQhiluG0PqEy4pqbe4V02N/ZXCxUO5Os8aA1sxxNs2HRDLElkcwaBbbOlQnGVKFMmZS5JHyseZAsEvW0ezTyhwyDu2DIQp6SQGkJFM2rUUzaUS0owpQnCF32I13GNcyX2zcUzunba2dyVAXK7uxFYdIIL6r1KSLfY50aIJMm2NHDO81jptic2YMU3DXlB2Jr5AWpipxBlOqZFkd8gFhEAKIosA/L0GZgkyUgbB/0GjW0BVkv1DaY9TS5yLuh0+zP3E2S8QNJCyYByGYi67q87fd0+FOEIWyRTJOZjBxE/bgQQYCYyWiEmS88pftYcTChy54wxPoIcdFN2jJeOyMgcb5S9Jz1C6pS0wkzfi6FhO+zQ68XGlZtFjwc07EFYI3cCvQQD9hXV0i4ui/4UPMW/U4EI8WZG02bZ02rzL42RYFx61nC402h8R2LJpvDrG4SQlYgApAgCIIg9FdUD32ARAPEIgIQIXAx1BD+n0HW0zthlo8kN7ERYcwiYeDKA3QmQrQ7Poeq6xNW42HaXBjnzXTTk5uMp8Ww5E0KtH3OHKUlFTTnRvHfgDnNXYDjGTq3k9cd/cePaCMaES0iKEB/XnI7arYDo2GhJzt1IvfLi9DkffZtGzWRjHmLNXtRE5fJ3BXkfNMKz1qOXQBTMnUc9rU9mtmLmLoKmPpe+kY7/nDXJ1cqxejQzTj5x5nrwZQfKGwdst7CdaGFMIZFfIBYRAAiRNoS10I6zn2LHxEnLLFmKC9ggvNHCOKGEeL5asv07ATJ7BziIcnvcsvEAkQKpRypxd04MpVaPtXK6wDzEGFMRdp61LzjSbdmAYkrkqoVP3cMDxNKmAcLV5mdjjnMsdV80hjTE00z4E1Fmf2uWExj0q4nJlWEZhrTsu+R5Q0CkBbdll6hR+uP+vt4EV8k8ktxRU2ZbYY6dmEq2HPpH7h95u13U2h81z78cfQjAUlIGRGABEEQBKG/IiawjCECECHaqhCFYvPoeARR85veblgtJnd+Uv/UhCOhVg2CM4FxZjTljc38u+bsTF+iqMNzm6cBYqJQUjSNsMn3qMaL1k0ybi+A43OqN4NUnarDVLQOosazRfxomi+qUbAPw/iWzWiONOfpiEHrwGmLohathL4Rc7stCWNYGIdjf45BooqC9G3aBs1jpNXOo98tEV/0GGmV1S2lRmxtXfsrKur8ntD8qBhN5hRg39jqmlHClC7hrjOuGrwpos2QGwiAOT9QLzpBK9eF6oEJTMLgeUQAIphMYP55rp3v5ovNGkXFCBuBEismLjyXNDrMtc0N1VbIlM/uTE1gwX0QWKHHVjyTqzNlEIYc5kGr74MU/YFSFZaoKYM+QFIVotJBEFOhTYJgaykZBCAaUaOdqAGSM6YYSh+oeKbpd61WmUFYDmuOpPgJGTubdFNXgO8mkyvrzxLADOX1x4W+a8VLDWYvAMpLaBhEyGITP1r2ZRhhUzv2TIJHmz+blm06xXEIWYUIQIIgCILQXxETWMYQAYjgxFWHhsNo9uJWcuzLmFbTNEB2J2L/nYaWqCBvLPTlRdPYu8nfaURNhL4gUU0P872zCrR5yGmBqbKtRQJ5L6aK0SJwZEod7DKaCDZ/DT3mjmFZJhmdDVu9pp6gjYOZi3c8uFw91PxjMp0B/nkfunxHps7JsPvRGgXGmL1cphwFxeRkHjWUl0gaUwizFz0utF6X5hAdwqmaK/Hh0RMNi+3YcCZyk9aMXnNWbVAvaoVcxUfNBEEEIBYRgAiRNoUIlPWC1AUdelGRVkv2WPZ8Vsw/vjaeCj2dv7smYQld/I58AYiatDp/jrRRX59kv5+O/hI+QAEuKrYAqq1gJpNlWKsdFTcsG+RGGipqKB2RZIxPDo0yMUX2cL48YbadDoL0ZyxOyTxMONOZFr0USfzMObbR5jQ8iNIgOLEpGDyCCD1Bsjt7GPZXx0C4/RHC9ET7JrW7goW2e9sgi4aK9krD8eQSN4cpqKr1RzqM90EmaCFjiAAkCIIgCP0VpdAjKV00QCwiABH8RIi2hHtMu+aIbFCb9iRwwDdfUYdC6izsmjUlJidoTevTanBw7vJdS3roXYchI6s0RbThTYt7k+ccm/0cLVQVr1X+ZlTYNq1OEIfXdGiDTG/72n6mWoJecNzOZN9cMjrNdEZVBl5CRovTKgJo/cJEEgWBOxas1i/xPc6Yt4JofegcPY0MY5rSyk7QXaqN1fAwpWY0zuyl9RHCpEYJa9Y0EeZ6cBjPeEvSQy0irE+LCQLKVVpUWuj1RQBiyRkBaO3atXjqqafQ1NSEyZMno66uDjfffHOoPhxTws0QJw97q/VcPJzktqR22zao0EMFFvq8ZGrveNcQNXVFyXddGKJZeA1RHD0QDrzRKW6PMc2aP5DJB4iNerE8nDhSDZ/nfHnizI3Um0OQ4p9Btpkq6Yx2CXJ+sGGThsR0tqizpD48XyRDW1DCnB9s+gE3eVnuO/dQNiUjpKYp1gQW4hrl6rJxUV6mvsLKCWGOhxbtxzg8mghTx7S/RnspFz3TAEkYPEeqMni/YsuWLVi0aBGWL1+Ow4cP4+abb8Ydd9yB06dP9/XQBEEQBEHoh+SEBuiZZ57Bt7/9bXznO98BANTV1eGVV17BunXrUFtbG7wjpQClrDl6gmgjTY7SbN6eUJFkRBtD+zNYEDr+SV41wuX4MUV76Zvsfbg3WtuYgiQS9E1PTA6UdMBGxhhOMk5zFIRMleewaQAygSnZHGc6s2l4QpVQCECQKDuTxjGIeSvsd49A0Y8hnH7DmKmY0y6U43MQepKLye+Dag4DaCKNXSQc9LliiRlATGCZI+sFoNbWVhw8eBDLli3T2mfOnIl9+/YZ12lpaUFLS4v//6VLlwB0msC0c80YPmofl2P6R1Pp09+VsTmUaYwKUYyN3NuMJvTQaC/G78d4M+vBDcn363G4/WGfuLkPs78Qi2sxT6QK3f9RZj+5Bn8EpkZUIMKYa2zQfcpFvaRqLqACVcq+VAEe3D5MNFoQwoSOh2kPItxQs1e6hTgTYfeNYV7WSDiO/mJ60tIyWIqv9iZiAssYWS8Avf/++4jH4xg1apTWPmrUKJw7d864Tm1tLX74wx8mtbe3XwGQHgFIwyAA2cptJC1j3YZdi2QUgDTHZ5d8jxvb/RIYmgIjnPOj8gZIBqpshRu7bsefi2FsACLxts5l3VbynbZ7sfTUDyOABsiUryVIRWuHKRvgfeUy8wYhUwJQT5YxEuJhzmooQi5vXZEhlADE9GEVgLh2RgDyvseJD5DD+ABpml4S+eBdD9r8zEEDKs6cs6YM170lAJk0qdr2AmhdtSADU2bszv2lFNl3ie/tqi3xW+a1K+1o65EWvh1t9oXylKwXgDy6RoMopdgIke9///tYsmSJ///Zs2cxadIkvLXryYyOURAEQcgdLl++jKFDh2ak71gshpKSErxxbkeP+yopKUEsFkvDqHKLrBeARowYgWg0mqTtaW5uTtIKeRQVFaGIFPYbNGgQjh8/jkmTJuHMmTMYMmRIRsfcV1y6dAljx46VOWYxuT4/QOaYC+T6/JRSuHz5MsrKyjK2jeLiYjQ2NqK1tdW+sIVYLIbi4uI0jCq3yHoBKBaLobKyEvX19fjqV7/qt9fX1+Puu+8O1EckEsHo0aMBAEOGDMnJC5Yic8x+cn1+gMwxF8jl+WVK80MpLi4WwSWDZL0ABABLlixBdXU1pk6diqqqKqxfvx6nT5/G3Llz+3pogiAIgiD0Q3JCALrnnnvw73//G6tWrUJTUxOmTJmCHTt2oLy8vK+HJgiCIAhCPyQnBCAAeOSRR/DII4+kvH5RURFWrFih+QblGjLH7CfX5wfIHHOBXJ+fkBs4SrIkCYIgCIKQZ+REKQxBEARBEIQwiAAkCIIgCELeIQKQIAiCIAh5hwhAgiAIgiDkHSIAJVi7di3GjRuH4uJiVFZW4vXXX+/rIaVEbW0tPvOZz2Dw4MEYOXIkvvKVr+Bvf/ubtoxSCitXrkRZWRkGDBiA6dOn49ixY3004p5TW1sLx3GwaNEivy0X5nj27Fk8+OCDGD58OK666ip86lOfwsGDB/3fs3mO7e3teOKJJzBu3DgMGDAA48ePx6pVq+CSGmjZNr8//elPuPPOO1FWVgbHcfDyyy9rvweZT0tLCxYsWIARI0Zg4MCBuOuuu/DPf/6zF2fRPd3Nsa2tDUuXLsV1112HgQMHoqysDLNnz8Z7772n9dHf5yjkEUpQmzdvVoWFhWrDhg3q+PHjqqamRg0cOFC9++67fT200Nx+++1q48aN6ujRo6qhoUHNmjVLXX311eq///2vv8yaNWvU4MGD1datW9WRI0fUPffco0pLS9WlS5f6cOSpceDAAfXxj39cVVRUqJqaGr892+d4/vx5VV5err75zW+q/fv3q8bGRrVr1y7197//3V8mm+f4ox/9SA0fPlz9/ve/V42NjerFF19UgwYNUnV1df4y2Ta/HTt2qOXLl6utW7cqAOqll17Sfg8yn7lz56rRo0er+vp6dejQIfWFL3xBffKTn1Tt7e29PBsz3c3xwoULasaMGWrLli3qr3/9q/rzn/+sPvvZz6rKykqtj/4+RyF/EAFIKXXDDTeouXPnam0TJkxQy5Yt66MRpY/m5mYFQO3du1cppZTruqqkpEStWbPGX+bKlStq6NCh6he/+EVfDTMlLl++rK655hpVX1+vbrnlFl8AyoU5Ll26VE2bNo39PdvnOGvWLPWtb31La/va176mHnzwQaVU9s+vq3AQZD4XLlxQhYWFavPmzf4yZ8+eVZFIRO3cubPXxh4Uk5DXlQMHDigA/stkts1RyG3y3gTW2tqKgwcPYubMmVr7zJkzsW/fvj4aVfq4ePEiAGDYsGEAgMbGRpw7d06bb1FREW655Zasm++8efMwa9YszJgxQ2vPhTlu374dU6dOxde//nWMHDkS119/PTZs2OD/nu1znDZtGv74xz/ixIkTAIC3334bb7zxBr70pS8ByP75dSXIfA4ePIi2tjZtmbKyMkyZMiUr5wx03H8cx8FHPvIRALk5RyF7yZlM0Kny/vvvIx6PJ1WOHzVqVFKF+WxDKYUlS5Zg2rRpmDJlCgD4czLN99133+31MabK5s2bcejQIbz11ltJv+XCHN955x2sW7cOS5YsweOPP44DBw5g4cKFKCoqwuzZs7N+jkuXLsXFixcxYcIERKNRxONxrF69Gvfddx+A3DiGlCDzOXfuHGKxGD760Y8mLZON96IrV65g2bJluP/++/2CqLk2RyG7yXsByMNxHO1/pVRSW7Yxf/58/OUvf8Ebb7yR9Fs2z/fMmTOoqanBq6++2m2l5Gyeo+u6mDp1Kp588kkAwPXXX49jx45h3bp1mD17tr9cts5xy5Yt2LRpE1544QVMnjwZDQ0NWLRoEcrKyjBnzhx/uWydl1YklQAABWlJREFUH0cq88nGObe1teHee++F67pYu3atdflsnKOQ/eS9CWzEiBGIRqNJbx/Nzc1Jb2vZxIIFC7B9+3bs3r0bY8aM8dtLSkoAIKvne/DgQTQ3N6OyshIFBQUoKCjA3r178dOf/hQFBQX+PLJ5jqWlpZg0aZLWNnHiRJw+fRpA9h/HRx99FMuWLcO9996L6667DtXV1Vi8eDFqa2sBZP/8uhJkPiUlJWhtbcV//vMfdplsoK2tDd/4xjfQ2NiI+vp6X/sD5M4chdwg7wWgWCyGyspK1NfXa+319fX43Oc+10ejSh2lFObPn49t27bhtddew7hx47Tfx40bh5KSEm2+ra2t2Lt3b9bM94tf/CKOHDmChoYG/zN16lQ88MADaGhowPjx47N+jjfddFNS+oITJ06gvLwcQPYfxw8++ACRiH77iUajfhh8ts+vK0HmU1lZicLCQm2ZpqYmHD16NGvm7Ak/J0+exK5duzB8+HDt91yYo5BD9JX3dX/CC4N/7rnn1PHjx9WiRYvUwIED1alTp/p6aKF5+OGH1dChQ9WePXtUU1OT//nggw/8ZdasWaOGDh2qtm3bpo4cOaLuu+++fh1eHAQaBaZU9s/xwIEDqqCgQK1evVqdPHlS/frXv1ZXXXWV2rRpk79MNs9xzpw5avTo0X4Y/LZt29SIESPUY4895i+TbfO7fPmyOnz4sDp8+LACoJ555hl1+PBhPwIqyHzmzp2rxowZo3bt2qUOHTqkbr311n4VIt7dHNva2tRdd92lxowZoxoaGrT7T0tLi99Hf5+jkD+IAJTg5z//uSovL1exWEx9+tOf9sPGsw0Axs/GjRv9ZVzXVStWrFAlJSWqqKhIff7zn1dHjhzpu0Gnga4CUC7M8Xe/+52aMmWKKioqUhMmTFDr16/Xfs/mOV66dEnV1NSoq6++WhUXF6vx48er5cuXaw/KbJvf7t27jdfenDlzlFLB5vPhhx+q+fPnq2HDhqkBAwaoL3/5y+r06dN9MBsz3c2xsbGRvf/s3r3b76O/z1HIHxyllOo9fZMgCIIgCELfk/c+QIIgCIIg5B8iAAmCIAiCkHeIACQIgiAIQt4hApAgCIIgCHmHCECCIAiCIOQdIgAJgiAIgpB3iAAkCIIgCELeIQKQIAiCIAh5hwhAgiAIgiDkHSIACYIgCIKQd4gAJAh5zvTp07Fw4UI89thjGDZsGEpKSrBy5UoAwJ49exCLxfD666/7yz/99NMYMWIEmpqa+mjEgiAIPUcEIEEQ8Pzzz2PgwIHYv38/fvKTn2DVqlWor6/H9OnTsWjRIlRXV+PixYt4++23sXz5cmzYsAGlpaV9PWxBEISUkWKogpDnTJ8+HfF4XNPy3HDDDbj11luxZs0atLa24sYbb8Q111yDY8eOoaqqChs2bOjDEQuCIPScgr4egCAIfU9FRYX2f2lpKZqbmwEAsVgMmzZtQkVFBcrLy1FXV9cHIxQEQUgvYgITBAGFhYXa/47jwHVd//99+/YBAM6fP4/z58/36tgEQRAygQhAgiB0yz/+8Q8sXrwYGzZswI033ojZs2drwpEgCEI2IgKQIAgs8Xgc1dXVmDlzJh566CFs3LgRR48exdNPP93XQxMEQegRIgAJgsCyevVqnDp1CuvXrwcAlJSU4Je//CWeeOIJNDQ09O3gBEEQeoBEgQmCIAiCkHeIBkgQBEEQhLxDBCBBEARBEPIOEYAEQRAEQcg7RAASBEEQBCHvEAFIEARBEIS8QwQgQRAEQRDyDhGABEEQBEHIO0QAEgRBEAQh7xABSBAEQRCEvEMEIEEQBEEQ8g4RgARBEARByDtEABIEQRAEIe/4Py27+wXW213AAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "expt.init_tracers.salt.isel(zl = 0).plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### You can plot your segment data too" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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5hpDN9xwA2655RYAwJtvvokNGzZgw4YN6NmzZ43bPfPMM/j888/xzDPP4J///Cd++uknXHTRRRg/fjz27duHf/3rX5gzZw4++ugj3HDDDY5tZ82ahb/97W/o3Lkz/v3vf+OVV15BaWkpzj77bPzwww9HrLOiKLV6CSFqdQ6WLVuGpKQkeDwe9OrVCy+++GKttvv+++/RsmVLZGRkOOZ3797dWh4JIQRGjhyJV155BXfccQdWrFiBfv36YdiwYSHr/vHHH2jRogUeffRRrFq1Cs888wxkWUbfvn2xbds2AEDjxo1x/fXXY+nSpSguLnZsv2DBArjdblx//fUAgClTpmDhwoW49dZbsWrVKrzyyiu44oorcODAgRrrHOl2APDNN9/gjjvuwO233463334b3bt3x/jx4/Hpp59a6+zZswdnnnkmVqxYgSlTpuD999/HvHnzkJqaioMHDwLQG2SDBg3CSy+9hFtvvRXvv/8+7rnnHixevBgXX3xxra8Hu7Vr10JVVXTp0sWaZ36u5udscrlc6NSpk+Nz//7773HaaaeFNGZqukZUVYXP58NPP/2EG264Aa1atQr5DzOcutQrWhUVFfjll19C9mXuv6KiAr/++mtM9mXWu1u3bo75rVu3RlpaWsj5rq5OABzPX5mNc/MPv+NlX7FSVFSEq6++Gtdccw3eeecdDBs2DFOnTsWSJUsA1O13hSSeI//51sC0adMGJ554IgCgR48etX6wsWnTpnjrrbesv/j279+P3NxcdOrUCW+//ba13k8//YR58+ahpKQEKSkp2L17N6ZPn47Jkydj/vz51npDhgxBx44dMWPGDCxfvrza/e7cuRPt27evVR1Xr159xIe/R48ejeHDhyMrKwt79+7FCy+8gOuvvx6//vorHnrooRq3PXDgAJo3bx4yv1GjRnC73bVqCITzwQcfYPXq1XjyySdx6623AtDPj9vtxrRp0xzrDhw4EAMHDrTeq6qK4cOHo0uXLnjuuecwd+5cAMDkyZPx5JNP4sUXX0Rubi4AoLKyEv/617/wt7/9DS1atAAAfP7558jJycHtt99ulTl8+PAj1jnS7QD92vn888+t63DgwIH4+OOPsWzZMuvYHnzwQezfvx/ffPMNTjvtNGvbK6+80pqeP38+vv32W3zxxRfo3bs3AOC8887DCSecgMsvvxyrVq0K26CsTmlpKSZNmoSsrCzHj7r5uYb77Js3b46dO3c61u3QoUPY9exl2TVq1Ag+nw8AcMopp2DNmjXIyso6Yn3rUq9oHTx4EEKIavdlr0+0Dhw4AI/Hg0aNGoXdl30/1X0nw9WJcw5Jkhw9ZMfDvmLlwIEDWLlyJfr06QMAOP/887FmzRosW7YM1157LYDa/66QxHPM9QxF6sILL3R0fZv/QVX9D9Ccv2vXLgD6f/SKouDaa6919OJ4vV4MGjTI8ZdTOJmZmdi0aVOtXr169TricSxduhSjR4/G2Wefjf/3//4fVq5ciREjRuDRRx/Fvn37jrh9TbcaIr0NsXr1agDA1Vdf7Zg/evTokHUVRcGsWbPQuXNnuN1uyLIMt9uN7du348cff7TW69ChA0aMGIEFCxZYPSTLli3DgQMHMHnyZGu9Pn364P3338e9996LNWvWoKKiolZ1jnQ7QI9+MRtCAOD1enHKKafgt99+s+a9//77OOeccxwNoaree+89dO3aFWeccYbj2ho6dGjIX+VHUllZicsuuwy//fYbXn/9dTRu3Dhkneo+36rz63qNrF+/Hhs2bMCSJUvQpEkTnHPOOY6//FVVdRyfeduirvWqDU3THPtSVbXWZcYycrAu+6ntug8++CAURcGgQYOOq33FSkZGhtUQMnXv3t3xvazt7wpJPAnTGKr6V4rb7a5xfmVlJQBYz3eceeaZcLlcjtfy5cuxf//+Gvfrdrtxxhln1OoV7j+w2rjmmmugKAq++uqrGtdr0aJF2L/IDh8+DL/fH/Yvudo4cOAAZFkO+auq6u04QL899cADD2DkyJF499138cUXX2DTpk04/fTTQxokt912G7Zv3478/HwA+q3O7Oxsxy3R+fPn45577sFbb72Fc845B82bN8fIkSOxffv2Gusc6XYAwv716PF4HPXft28f2rRpU2M5f/75J7799tuQ66pJkyYQQhzx2jL5fD5ceumlWLduHd555x307ds3bH3DffZ//fWX43Ov7hr566+/AITvxenZsyf69euHq6++GqtXr4YQAvfdd5+1/KSTTnIc38yZM+tcr9qaOXOmY18nnXQSAKBZs2ZgjNX52CLRokULVFZWory8POy+oj3fibCvSNTmewnU7neFJJ5j7jbZ0ZaWlgYA+M9//uN48LK2Yn2bLBzzL5wjPfTZrVs3vPbaaygqKnI0VMyHl2ubO6iqFi1aQFEUHDhwwPGDVFRUFLLukiVLcO2112LWrFmO+fv370fTpk0d884991x07doVTz/9NBo3boyvv/7auv9vatSoEWbMmIEZM2bgzz//tHp7LrroIvz000/V1jnS7WqrZcuW+P3332tcJy0tDUlJSWEfvjaXH4nP58PIkSOxevVqvP322zjvvPNC1jGf8fjuu+/QuXNna76iKPjpp5/wt7/9zbHuq6++CkVRHM8N1fYaadKkCTp16uR4eP7dd9+1bqMBem9pXetVWzfeeKMjV43H4wEAKw+T/UF903fffYekpKSwtwcjYT8ue8O0qKgI+/fvd5zDbt26VVsn4Mjn+3jdV32qze8KSUBxiWGL0vz58wUA8cMPP4QsGzRokBg0aJD1fseOHQKAePzxxx3rrV69WgAQr7/+umP+iy++KACITZs2WdvLsiwee+yxiOrq8/nEpk2bavUqKSmJaB8XXnihcLlcYt++fTWuZ4bWP/roo475N910U1Sh9e+//74AIJ588knH/EceeSQkBLp58+bipptucqz33nvvCQCOz820aNEiwTkXAwcOFOnp6cLn89VYRyGEyM3NFQDE4cOHj7huTdtNnz5dVP2KVBf+W/W6u/7664XL5aox387DDz8skpOTxa+//lqnepoqKyvFsGHDhNvtFu+9916165kh7BdccIFj/quvvioAiPfff9+at3LlSgFAvPbaa451L7jgglqF1u/bt080a9ZMjBgx4oj1r0u9qu6j6nVVG3fffbdwu91i165d1rySkhLRsmVLMWrUqGq3q2to/YEDB4TX6xUTJ050zJ89e3ZICPqCBQsEALFx40ZrXiAQEF26dBF9+/ZNqH1FE1o/aNAg0aVLl5D51f1mRfK7Qo5vx2RjyGzI3HTTTWL9+vWOhkSsG0NCCDFr1iwhy7K46aabrARzy5cvF3fccYd48MEH6+9Aq5gzZ44YN26ceOWVV8Tq1avF8uXLRU5OjgAg8vLyHOu+9NJLQpIk8dJLLznmm0kXH3/8cbFmzRpx33331SnpYrgfFlVVxcCBA4XH4xGzZs0SH374oZg+fbro0KFDyH9a1157rfB4POIf//iH+Pjjj8WcOXNEy5YtRZs2bcI2hsrLy0WLFi0EAHH//feHLO/Tp4+YOXOmeOutt8TatWvFs88+K1q0aCGys7NrPJbabBdNY+j3338XrVu3Fq1atRLz5s0TH3/8sXjjjTfEhAkTxI8//iiEEKKsrEz06NFDtGnTRjzxxBMiPz9ffPDBB+L5558XV1xxheM/knBGjBghAIhp06aFJOGsmnj0lVdeEQDEjTfeKFavXi0WLVokmjZtWm3SxWbNmolFixaJTz75REyYMEEAEEuWLLHWOXTokDjzzDPFP/7xD/Hee++Jjz/+WCxcuFB06tRJJCcnO74/NalLvVauXClef/118a9//UsAEFdccYV4/fXXxeuvv16rhu/evXtF69atRbdu3cSKFSvEypUrxcCBA0WTJk2sz8S0detWq+xevXqJli1bWu9rk9TVTE543333iTVr1ojHH39ceDyesMkJu3TpIrKyssTSpUtFfn6+uPTSS8MmJ5wxY4aQJClk/rG+L1O471bbtm1r1RCta2Oout+VcMe9Zs0aIUmSmDFjhqMMSZLEueeee8S6kWPDMdkYEkKIqVOniszMTME5FwDE6tWrhRD10xgSQoi33npLnHPOOSIlJUV4PB7Rtm1bcfnll4uPPvqoXo4vnHfeeUecddZZomXLlkKWZdGkSRNx9tlni1dffTVkXfM4XnzxRcd8v98vpk+fLk488UThdrvFKaecIubPn1+r/deUdPHQoUPi+uuvF02bNhXJycliyJAh4qeffgppDB08eFCMHz9etGrVSiQnJ4uzzjpLfPbZZyGfm924ceOELMvi999/D1l27733it69e4tmzZoJj8cjOnToIG6//Xaxf//+Go+lNttF0xgSQs9gff3114uMjAzhcrlEZmamuPLKKx3JEsvKysT9998vTj31VOF2u0Vqaqro1q2buP3220OySFcFoNpXuHO5bNky0b17d+F2u0VGRoa49dZbRWlpach6paWl4tZbbxUZGRnC7XaL7t27h1xjlZWV4oYbbhCnnXaaaNy4sZBlWbRp00Zcc801dc4AX9t6tW3bttrjrW0C1p9//lmMHDlSpKSkiOTkZHHeeeeJzZs3h6xnfvbhXrXtkXryySfFKaecItxutzjxxBPF9OnThd/vD1mvqKhIXHvttaJ58+bC6/WKfv36ifz8/GrrZP7WHS/7MoX7bqWlpYl+/fpVu42pro0hIcL/roQ7bvP/iqqfe3XfM3JsYkJEkMyEJKRx48ZhzZo1+Pnnn8EYgyRJ9b5Pv9+Pdu3a4ayzzsK///3vet8fIeToUlUVQgicfPLJ6Nq1K9577z0AwA8//IAuXbrgvffeq3Xai9qi3xVSVcJEk5HY+O233+ByuXD66afX63727duHdevW4e9//zv+/PNP3HvvvfW6P0JIfPTq1Qsul8sRAg/oASXZ2dkxbQjR7wqpDvUMkVrbuXOnFe6dlJTkyHIca4sXL8Z1112H1q1bY/r06WFT6BNCjn0//PCDFa7ftGlTnHzyyfW2L/pdIdWhxhAhhBBCEhrdJiOEEEJIQqPGECGEEEISGjWGCCGEEJLQjvvhODRNwx9//IEmTZrUy+CAhBBCjh9CCJSWliIzM/OIQxxFo7KyEn6/P+py3G43vF5vDGqU2I77xtAff/yBrKyseFeDEELIMWT37t1HHGw5UpWVlWiR1BjlUKMuKyMjAzt27KAGUZSO+8ZQkyZNAADrvvkRjY1pQgghxKQJQBMCQgBlpaU4p2dn6/+O+uD3+1EOFVfjBLijeFrFDw1Li/bA7/dTYyhKx31jyLw11rhJEzRpkhLn2hBCCGloNAGoRmPIdDQeq0gCh5tF3hiSKDFOzNAD1IQQQkgcSIxF/YrEggUL0L59e3i9XvTq1QufffZZteu++eabGDJkCFq2bImUlBRkZ2fjgw8+CFnvjTfeQOfOneHxeNC5c2esWLEiorrFCzWGCCGEkDjgDJCiePEI2kLLly9Hbm4upk2bhi1btuDss8/GsGHDsGvXrrDrf/rppxgyZAhWrlyJzZs345xzzsFFF12ELVu2WOts2LABo0aNwpgxY/DNN99gzJgxuPLKK/HFF19EemqOuuM+A3VJSQlSU1NR8OvvdJuMEEJICPttsrLSEpzZMQvFxcVISamf/zPM/5f+zk+EJ4rbZD6hYaG2q0517du3L3r27ImFCxda80477TSMHDkSs2fPrlUZXbp0wahRo/Dggw8CAEaNGoWSkhK8//771joXXHABmjVrhldffbUORxQ/1DNECCGExEGsbpOVlJQ4Xj6fL+z+/H4/Nm/ejJycHMf8nJwcrF+/vlZ11jQNpaWlaN68uTVvw4YNIWUOHTq01mU2BNQYIoQQQuIgmltk5gsAsrKykJqaar2q6+HZv38/VFVFenq6Y356ejqKiopqVecnnngChw8fxpVXXmnNKyoqiqrMhuC4jyYjhBBCjme7d+923CbzeDw1rl81Uk4IUavouVdffRV5eXl4++230apVq5iU2VBQY4gQQgiJg2giwgBAgr5tSkpKrZ4ZSktLgyRJIT02e/fuDenZqWr58uUYP348Xn/9dZx//vmOZRkZGRGV2ZDQbTJCCCEkDmJ1m6y23G43evXqhfz8fMf8/Px89O/fv9rtXn31VYwbNw7Lli3D8OHDQ5ZnZ2eHlPnhhx/WWGZDQz1DhBBCSIKYMmUKxowZg969eyM7OxuLFi3Crl27MHHiRADA1KlTsWfPHrz88ssA9IbQtddeiyeffBL9+vWzeoCSkpKQmpoKALjtttswcOBAPPbYY7jkkkvw9ttv46OPPsK6devic5ARoMYQIYQQEgexuk1WF6NGjcKBAwcwc+ZMFBYWomvXrli5ciXatm0LACgsLHTkHHruueegKApuvvlm3Hzzzdb8sWPHYvHixQCA/v3747XXXsP999+PBx54ACeddBKWL1+Ovn37RnxsRxvlGSKEEJLQ4pVnaKqnPbxR5BmqFBpm+3bUa10TBT0zRAghhJCERrfJCCGEkDiIx20yEh41hgghhJA4iCQizLF97KqS8KgxRAghhMSB3hiKpmeIxAo9M0QIIYSQhEY9Q4QQQkgc0G2yhoMaQ4QQQkgc0APUDQfdJiOEEEJIQqOeIUIIISQOeJS3yag3I3aoMUQIIYTEAd0mazioYUkIIYSQhEY9Q4QQQkgcUDRZw0GNIUIIISQOqDHUcNBtMkIIIYQkNOoZIoQQQuKAHqBuOKgxRAghhMSBhChvk4mYVSXhUWOIEEIIiQMeZc8Qj2Jb4kTPDBFCCCEkoVHPECGEEBIHUUeTUcdQzFBjiBBCCImDqB+gpttkMUO3yQghhBCS0KhniBBCCIkDuk3WcFBjiBBCCIkDuk3WcCRMY6hlkoyU5IQ5XEIIIQDMVDyaAFRNWO9VTUCzpgEhBFQBKDI9PZKIqHVACCGExAFnLKpcQZRnKHaoMUQIIYTEAZMYGI+8QcOoMRQz1B9ICCGEkIRGPUOEEEJIHHCJgUfRM0S3yWKHGkOEEEJIPEgcjEdxg4bRSK2xQo0hQgghJA4YZ2BRJAtioJ6hWEmYxpBLKHAJJd7VIIQQUp+EFpxmzl4XIcsQxq0lIQBV6D0rmgiG1gsXPUqbiBKmMUQIIYQ0JFxi4FH0DHHqGYoZagwRQgghccB4dM8MMUHPDMUK9QcSQgghCWTBggVo3749vF4vevXqhc8++6zadQsLCzF69Giceuqp4JwjNzc3ZJ3FixeDMRbyqqysrMejiC1qDBFCCCFxYN4mi+ZVV8uXL0dubi6mTZuGLVu24Oyzz8awYcOwa9eusOv7fD60bNkS06ZNw+mnn15tuSkpKSgsLHS8vF5vnesXL9QYIoQQQuKASSzqV13NnTsX48ePxw033IDTTjsN8+bNQ1ZWFhYuXBh2/Xbt2uHJJ5/Etddei9TU1OqPhTFkZGQ4XscSagwRQgghCcDv92Pz5s3IyclxzM/JycH69eujKrusrAxt27ZFmzZtMGLECGzZsiWq8o42eoCaEEIIiQO9dyeKB6ihpxEoKSlxzPd4PPB4PCHr79+/H6qqIj093TE/PT0dRUVFEdejU6dOWLx4Mbp164aSkhI8+eSTGDBgAL755ht07Ngx4nKPpoRpDDF/OZhfinc1CCGE1Kfq8gwxDsY4hDmPcUjmcBaMQ3AOMA5VPnrh6rEKrc/KynLMnz59OvLy8qrdruoAr0KIqAZ97devH/r162e9HzBgAHr27ImnnnoK8+fPj7jcoylhGkOEEELI8Wj37t1ISUmx3ofrFQKAtLQ0SJIU0gu0d+/ekN6iaHDOceaZZ2L79u0xK7O+0TNDhBBCSBwwxvQhOSJ9Gb05KSkpjld1jSG3241evXohPz/fMT8/Px/9+/eP2XEJIVBQUIDWrVvHrMz6Rj1DhBBCSBxwiYNH8cwQF3XfdsqUKRgzZgx69+6N7OxsLFq0CLt27cLEiRMBAFOnTsWePXvw8ssvW9sUFBQA0B+S3rdvHwoKCuB2u9G5c2cAwIwZM9CvXz907NgRJSUlmD9/PgoKCvDMM89EfGxHGzWGCCGEkDiINDze2l7UfdtRo0bhwIEDmDlzJgoLC9G1a1esXLkSbdu2BaAnWayac6hHjx7W9ObNm7Fs2TK0bdsWO3fuBAAcOnQIN954I4qKipCamooePXrg008/RZ8+fSI+tqONCXF85/MuKSlBamoq9u38H1JSmsS7OoQQQupTDQ9Qo8oD1LA/QG0sLykpQXpGBoqLix3P4cSS+f/Sh/2z0UiOvE/isKIgZ/2Geq1roqCeIUIIISQO4tEzRMJLmMYQ95WBHzvDpBBCCKmJ2QMkNEdvEBMaoBnvbYOgmj0/4HLwPdfTrQgug0kywGVwf/nRqT/i88wQCY/OJCGEEEISWsL0DBFCCCENSpS3yUC3yWKGGkOEEEJIHHDGwHkUGaijyBpNnOg2GSGEEEISGvUMEUIIIXHAJB7dQK0a9WfECjWGCCGEkDiIeqBWjW6TxUqDaVbOnj0bjDHk5uZa84QQyMvLQ2ZmJpKSkjB48GBs3bo1fpUkhBBCyHGnQfQMbdq0CYsWLUL37t0d8+fMmYO5c+di8eLFOOWUU/Dwww9jyJAh2LZtG5o0qVs2aV5+EFwKxLLahBBCqiFkfbBQ4fJCuJKcmaGtlQSYphjTGqApYKr+nqkBwFymqRCaBij+4KaqaizTrHUAQAAQxjTjkpVLCJyDudxgskt/L7kgJLdRVxfAZQjJDeYrjcHR107USRepZyhm4t4zVFZWhquvvhrPP/88mjVrZs0XQmDevHmYNm0aLrvsMnTt2hUvvfQSysvLsWzZsjjWmBBCCIme+cxQNC8SG3E/kzfffDOGDx+O888/3zF/x44dKCoqQk5OjjXP4/Fg0KBBWL9+fbXl+Xw+lJSUOF6EEEJIQ6N3XLEoXvE+guNHXG+Tvfbaa/j666+xadOmkGVFRUUAgPT0dMf89PR0/Pbbb9WWOXv2bMyYMSO2FSWEEELIcStuPUO7d+/GbbfdhiVLlsDr9Va7HquSVEoIETLPburUqSguLrZeu3fvjlmdCSGEkFhhnEX9IrERt56hzZs3Y+/evejVq5c1T1VVfPrpp3j66aexbds2AHoPUevWra119u7dG9JbZOfxeODxeOqv4oQQQkgMcB7lQK1q3J90OW7E7Uyed955+O6771BQUGC9evfujauvvhoFBQXo0KEDMjIykJ+fb23j9/uxdu1a9O/fP17VJoQQQshxJm49Q02aNEHXrl0d8xo1aoQWLVpY83NzczFr1ix07NgRHTt2xKxZs5CcnIzRo0fXeX/+jNPgT0mJSd0JISThMQ5hPLIgRA2rGXdymBnuLrRgmL2mgqlGuLyq6GH2qp4CRah+MCVgbKuAKT4I44lhEfA7QuqFpgbfIxhaD64BPBhmb68mA8CY0R+gAELW35v1PBqiDq2PZpBX4tAg8gxV5+6770ZFRQUmTZqEgwcPom/fvvjwww/rnGOIEEIIaWiiHo6DQutjpkE1htasWeN4zxhDXl4e8vLy4lIfQgghhBz/GlRjiBBCCEkUjHMwHkXPUBTbEidqDBFCCCFxwKUoo8noNlnM0JkkhBBCSEKjniFCCCEkHqIdX4x6hmImYRpDe8o1lEhhRk0mhBBSLTN6W+IMkiP7f+jvqaghxt4cOYAzboW0c8iQZH0EAtnNIDFANkPxVb8+cj2gj2av+K2we6Yp1oj2TFXANFUP2Qf0sH1hqxsLNhgEl633QpL094AxYr0LgsvQXErNJySGGI8ymoyeGYqZhGkMEUIIIQ0JPUDdcNCZJIQQQkhCo54hQgghJA70pItSFNsfvWzZxztqDBFCCCFxQBmoGw46k4QQQghJaNQzRAghhMQB5xw8ioego9mWOFFjiBBCCIkDuk3WcCRMY+j7P8uQfJgdeUVCCElgLonDxZk1zW0/m/Y8Q9w2XfX/ZM5Cf2tdRi+GxIPLJcasbSXGIHNY+3ZLMmTu0rd1Mbi8eu4hAHr+IWtaATTVyi3EquYZMpn5hczcQozZcg7JgJmDSA7UcHbI8SphGkOEEEJIQ0I9Qw0HNYYIIYSQOGAsyqSLjBpDsUJnkhBCCEkgCxYsQPv27eH1etGrVy989tln1a5bWFiI0aNH49RTTwXnHLm5uWHXe+ONN9C5c2d4PB507twZK1asqKfa1w9qDBFCCCFxYN4mi+ZVV8uXL0dubi6mTZuGLVu24Oyzz8awYcOwa9eusOv7fD60bNkS06ZNw+mnnx52nQ0bNmDUqFEYM2YMvvnmG4wZMwZXXnklvvjiizrXL16oMUQIIYTEQTwaQ3PnzsX48eNxww034LTTTsO8efOQlZWFhQsXhl2/Xbt2ePLJJ3HttdciNTU17Drz5s3DkCFDMHXqVHTq1AlTp07Feeedh3nz5tW5fvFCjSFCCCEkDrjEo34BQElJiePl8/nC7s/v92Pz5s3IyclxzM/JycH69esjPo4NGzaElDl06NCoyjzaEuYB6l8OlMNbSW0/QgipicQZ3DK3ps1wes4YJAZwHgyLD4bIB+fb17WmObNC5jljcBkLvTKHxxibyyUxuCUGVejbaQDcRnnC2Ikse4wyOCDpYfdCU8E0xQqnF/pMfcOqDxjb3zMOYb5nHOASBOPQXMdeaH1WVpbj/fTp05GXlxey3v79+6GqKtLT0x3z09PTUVRUFPH+i4qKYl7m0ZYwjSFCCCGkIWGcRRdNZjQwd+/ejZSUFGu+x+OpebsqeaCEECHz6lyXeijzaKLGECGEEBIHscozlJKS4mgMVSctLQ2SJIX02OzduzekZ6cuMjIyYl7m0Ub3jQghhJAE4Ha70atXL+Tn5zvm5+fno3///hGXm52dHVLmhx9+GFWZRxv1DBFCCCFxEI8M1FOmTMGYMWPQu3dvZGdnY9GiRdi1axcmTpwIAJg6dSr27NmDl19+2dqmoKAAAFBWVoZ9+/ahoKAAbrcbnTt3BgDcdtttGDhwIB577DFccsklePvtt/HRRx9h3bp1ER/b0UaNIUIIISQO4pGBetSoUThw4ABmzpyJwsJCdO3aFStXrkTbtm0B6EkWq+Yc6tGjhzW9efNmLFu2DG3btsXOnTsBAP3798drr72G+++/Hw888ABOOukkLF++HH379o342I42agwRQgghCWTSpEmYNGlS2GWLFy8OmSeEOGKZl19+OS6//PJoqxY31BgihBBC4oBJEriRWiDS7UlsJExj6MfCYriT1HhXgxBCGhS3LMEtcyS59P9YPTJHklsyltmmJQ6XxB15h8x8QeZ7kxQmotrMH2RLRwRVAwJMzwkkcY6ABpjFKFpwPSEATQAurhcicxmSsROmqYBwBXMLmRuY7OHdVXILCWOZXr6+jXIU44po1PqGg84kIYQQQhJawvQMEUIIIQ0J9Qw1HNQYIoQQQuKA8SijyaLYljhRY4gQQgiJA+oZajjoTBJCCCEkoVHPECGEEBIHjLPoeob4sTMQakOXMI2hPfvLIXvpwiGEEDuPR0bTZBcae10AYIXYA4DEGVRNDznnMoPEGFzGf8CyxK0QejOsXuLVh9qHW8dO1fSwe9WKkBcwdg0hAFUTUI0dShogMWHtR+KyFUHPjzBSuhlCLwSsEHxN6IkFNQH41SMnGIwVemao4aAzSQghhJCEljA9Q4QQQkhDwrgExqPIQB3FtsSJGkOEEEJIPHBJf0WzPYkJuk1GCCGEkIRGPUOEEEJIPHCuv6LZnsQENYYIIYSQOGCSFNXI8zRqfewkTGNIVTQw+zDIhBBCoLoEFE3Ar6gA9ND3cr8aXK4FQ801IVmh9R4Ba9R6F3eGtHPGHGH3EmfWaPUuzmGm1nFxbm3nkvTQfXM9DuYY4V5DMOxeMAHVWCYxBlUIBFcV1nashjB7IezHZW5JElXCNIYIIYSQBoUeoG4wqDFECCGExAPnUTaG6JmhWKHGECGEEBIHlIG64aAzSQghhJCEFlHPEOe8xgfTVFWtdhkhhBBCALAonxli9MxQrETUGFqxYoXjfSAQwJYtW/DSSy9hxowZMakYIYQQclyjB6gbjIgaQ5dccknIvMsvvxxdunTB8uXLMX78+KgrRgghhBByNMT0Aeq+fftiwoQJsSwyZor3V0DyVH9rjxBCEpG3kQu+Chc8SS4AQGOvjCZe/b8GVXNb60nczBek90ZoQgC27D76Mv29xIJ5hyTu/N3VhAA0fR5nzlw/jAFMmOsH1wMXYALWU65CBHMICSbAWPABWMYYVKNYe/lw1DZUPHIM0QPUDUfMGkMVFRV46qmn0KZNm1gVSQghhBy/6DZZgxFRY6hZs2aOB6iFECgtLUVycjKWLFkSs8oRQgghhNS3iBpD8+bNc7znnKNly5bo27cvmjVrFot6EUIIIcc3SrrYYETUGBo7dmyt1ps0aRJmzpyJtLS0SHZDCCGEHLdooNaGo16blUuWLEFJSUl97oIQQgghJCr1OhyHfVRgQgghhNhwHt2tLrpNFjMJMzZZwKdAgxLvahBCSFzILgmyW//PU5I4uByc1lSBgE//fSzVBFRN/0NW1QRU2x+1Zng9AEgq4DKmVcbANQEuBQNrNHM7zZhhrKvP15cFNEAygnG4wuCSmPXeJdn2pTFIHJCMIvXQ/eA0YwxmRD6DsG55aGDgtcioYl+nNuvHDEWTNRjUrCSEEELigHEp6hcJ+vHHH9GhQ4eItqXGECGEEEKOeX6/H7/99ltE2ybMbTJCCCGkQWFRPjPEItt2wYIFePzxx1FYWIguXbpg3rx5OPvss6tdf+3atZgyZQq2bt2KzMxM3H333Zg4caK1fPHixbjuuutCtquoqIDX642ojuFMmTKlxuX79u2LuOx6bQxdc801SElJqc9dEEIIIcekaG91RbLt8uXLkZubiwULFmDAgAF47rnnMGzYMPzwww848cQTQ9bfsWMHLrzwQkyYMAFLlizB559/jkmTJqFly5b4f//v/1nrpaSkYNu2bY5tY9kQAoAnn3wSZ5xxRrXtirKysojLjmlj6PDhw9i8eTMGDhwIAFi4cGEsiyeEEEJIFObOnYvx48fjhhtuAKAnUf7ggw+wcOFCzJ49O2T9Z599FieeeKKVbPm0007DV199hf/7v/9zNIYYY8jIyKjXunfs2BG33347rrnmmrDLCwoK0KtXr4jKjukzQz///DPOOeecWBZJCCGEHJ/MDNQRv+r2X7jf78fmzZuRk5PjmJ+Tk4P169eH3WbDhg0h6w8dOhRfffUVAoGANa+srAxt27ZFmzZtMGLECGzZsqVOdauNXr16YfPmzdUuZ4xFnNInrg9QL1y4EN27d0dKSgpSUlKQnZ2N999/31ouhEBeXh4yMzORlJSEwYMHY+vWrXGsMSGEEBIjZp6haF4ASkpKHC+fzxd2d/v374eqqkhPT3fMT09PR1FRUdhtioqKwq6vKAr2798PAOjUqRMWL16Md955B6+++iq8Xi8GDBiA7du3R3uGHJ544gnk5uZWu/z000+HpmnVLq9JnW6TNW/evMblqqrWaedt2rTBo48+ipNPPhkA8NJLL+GSSy7Bli1b0KVLF8yZMwdz587F4sWLccopp+Dhhx/GkCFDsG3bNjRp0qRO+2rc1APJE9v7l4QQcqzSFM36N+DT8xABgOzWoAT03/IKvwqfsZ5f0VDuV9E02QUAaOyVoRp/hHtlAYUzK7eQS+Lg1mDewjatqy6XjyaElWeoKm7LGcQZg5nSSDZyE1XNO2Tuxyytah0AwD6LGXX3S0cz0VBsZGVlOd5Pnz4deXl51a7PqpwLIUTIvCOtb5/fr18/9OvXz1o+YMAA9OzZE0899RTmz59fq2Oojfq8DVenxpDP58Pf//53dOvWLezy3377DTNmzKh1eRdddJHj/SOPPIKFCxdi48aN6Ny5M+bNm4dp06bhsssuA6A3ltLT07Fs2TLcdNNNdak6IYQQ0qDEamyy3bt3Ox4q9ng8YddPS0uDJEkhvUB79+4N6f0xZWRkhF1flmW0aNEi7Dacc5x55pkx7xmy++2331BUVATGGNLT09G2bduoyqtTY+iMM85AVlZWtQO1fvPNN3VqDNmpqorXX38dhw8fRnZ2Nnbs2IGioiLHvUqPx4NBgwZh/fr11TaGfD6fo4uQxkYjhBDSIMUoA7X5qMmRuN1u9OrVC/n5+bj00kut+fn5+bjkkkvCbpOdnY13333XMe/DDz9E79694XK5wm4jhEBBQUG1HSfR+Mc//oG5c+fijz/+cPRQZWZm4o477qjxNlpN6tQYGj58OA4dOlTt8ubNm+Paa6+tUwW+++47ZGdno7KyEo0bN8aKFSvQuXNn62GucPcqa0qqNHv27IgbZIQQQshRE4fhOKZMmYIxY8agd+/eyM7OxqJFi7Br1y4rb9DUqVOxZ88evPzyywCAiRMn4umnn8aUKVMwYcIEbNiwAS+88AJeffVVq8wZM2agX79+6NixI0pKSjB//nwUFBTgmWeeifzYwnjooYfwf//3f7jvvvswdOhQpKenQwiBvXv34oMPPkBeXh7Kyspw//3317nsOjWG7rvvvhqXZ2Vl4cUXX6xTBU499VQUFBTg0KFDeOONNzB27FisXbvWWl7Xe5tTp051JGYqKSkJuZ9KCCGEJKJRo0bhwIEDmDlzJgoLC9G1a1esXLnSus1UWFiIXbt2Weu3b98eK1euxO23345nnnkGmZmZmD9/viOs/tChQ7jxxhtRVFSE1NRU9OjRA59++in69OkT07ovWrQIL730EkaOHOmYn5mZiTPOOAOnnHIKJk+eHFFjiIkGNrT8+eefj5NOOgn33HMPTjrpJHz99dfo0aOHtfySSy5B06ZN8dJLL9WqvJKSEqSmpuKMe96A5GlUX9UmhJBjitCcP/3BB6glyC49SsnlkZFqPDDdNNmNxh7Z8QB1ilef9socLs7gMQZ/tT9ArQ+qGhx0FXA+QG0N1Mr0wVhd3CzDNlArY3Bxfbn5vr4eoC4pKUF6RgaKi4vrLWmw+f/Swc0fIKVx5P8vlZQdRrNeQ+u1rg1JcnIyNm/ejNNOOy3s8q1bt+LMM89EeXl5ncuuc9JFIQQ++ugjrF+/3vHw0oABA3DeeefV2GtT2/J9Ph/at2+PjIwM5OfnW40hv9+PtWvX4rHHHotqH4QQQkjcsShvk7HEGqi1T58+eOSRR7B48WLIsrP5oigKZs2aFXFvVJ0aQ3v27MGIESPw3XffoWvXrtb9uvXr1+Ohhx7C6aefjnfeeQcnnHBCrcq77777MGzYMGRlZaG0tBSvvfYa1qxZg1WrVoExhtzcXMyaNQsdO3ZEx44dMWvWLCQnJ2P06NF1PtCU5smQvcl13o4QQo4HmiagqXqYvKoIqMa0ElChKcFwenNd899DxrSqCfgVFarx3q9o1nRjrwyvxK1Qe48AXFZXDXf0BHEW7P2ROGw9SCykN8jcTuZGz5CtN8jFgz1PMg9ux4QA0xTzQII7Nm+CiNA8NExo1nzui3xIB1K/nnrqKeTk5KBVq1YYNGgQ0tPTwRhDUVERPv30U3g8HuTn50dUdp0aQ5MmTULz5s2xe/dutG7d2rGssLAQ11xzDW6++Wa89dZbtSrvzz//xJgxY1BYWIjU1FR0794dq1atwpAhQwAAd999NyoqKjBp0iQcPHgQffv2xYcffljnHEOEEEJIg8NYxIOtWtsnkG7duuF///sflixZgo0bN2LHjh0A9PD/Rx55BKNHj474dmGdnhlq3LgxPv/8c5x++ulhl2/ZsgVnn312VIOlxZp5b3bgY+9D9tIzQ4SQxHSkniGT7JLAjWd/ZBeH26P/zdwk2YUmXhmpSW79vTf4PJHZM+SR9ds2HuMZIkB/fshl67k5qj1Dou49QyUlpWjZ9uSj88xQwWqkNGkceTmlZWh2xjkJ88xQfapTz1BSUhL++uuvapcfPHgQSUlJUVeKEEIIISScsrIybN682XpuOSMjAz179kTjxpE3LOvUGLrqqqswduxYzJ07F0OGDEFqaioAoLi4GPn5+bjjjjsiep6HEEIISTSCcYgobpNFs+2xSFEU3HHHHXj++edRWVkJt9sNIQQCgQC8Xi9uvPFGPP7449Umg6xJnRpDTzzxBBRFwdVXXw1FUeB2692lfr8fsixj/PjxePzxx+tcCUIIISThMB7lM0OJ1Ri644478MYbb+DFF1/E0KFD0bRpUwB6nqMPPvgAd911FwBg3rx5dS67To0ht9uNhQsX4rHHHsNXX32FP//8E4D+8FKvXr3oniUhhBBC6sWyZcuwfPlynHvuuY75TZs2xahRo5CWloarrrqq/htDppSUlJDKNHQnNE+GO5keoCaEJKYKv4LSSv3BYp9fhd+nTwtNOB6gVlXNGn3enpixFHp4vRlOrwrhCLNv7JVh/3NYcgV7LSTObA9Us2oTK3LjYWj9PaxlLs70h6SNB6hdRqJFAOBCBdMCMOP6maYEH5IO87B0WEILhuGr/tptEwuMRRcRlmDRZBUVFUhLS6t2eYsWLVBRURFR2XVuDB0+fBjLli0Lm3Txb3/7Gxo1ogYHIYQQckSc669otk8g55xzDqZMmYKlS5eGjFv6559/4u677464o6ZOjaEffvgBQ4YMQXl5OQYNGoQTTzzRGiTtrrvuQl5eHj788EN07tw5osoQQgghiYIeoK6bBQsW4MILL0SbNm2sxM9m0sXvv/8enTt3xn//+9+Iyq5TY+jmm2/GwIED8dJLL1kPT5v8fj/GjRuHm2++GatXr46oMoQQQggh4WRlZeGbb77BBx98gI0bN6KoqAiAPkzH7NmzkZOTAx5hb1mdGkNffPEFvvrqq5CGEKA/XH3ffffFfJRaQggh5LhE0WR1xjnHsGHDMGzYsCOuO2nSJMycObPG54yscutSiWbNmmH79u3VLv/555/RrFmzuhRJCCGEJCazMRTNi1RryZIlKCkpqdW6deoZmjBhAsaOHYv7778fQ4YMcdyvy8/Px6xZs5CbmxtJnQkhhBBCYqYOo43VrTGUl5eHpKQkzJ07F3fffTeYEdYnhEBGRgbuvfde3H333XWrLSGEEJKI6DZZg1Hn0Pp77rkH99xzD3bs2GE9vJSRkYH27dvHvHKx5JY53DJdOISQxORXgjl9AICbA5tyBsaZI6eQOa1CAwsY+Xy4inJbefayJGOgVPM31iVxM+1PcH/MzBnE4TEHguUMkvGzrA/EyoJ5hjis3ERmjiHZ2CXTFEBVg9O2gVaNAzBWtP3mGw2P6iKwrMFapdBnYuuLYCzKaLLEyjNUnyJKuggA7du3P2IDKCUlBQUFBejQoUOkuyGEEEIIqVcRN4Zqoy736wghhJCEQrfJGgw6k4QQQkg8mMNxRPNKQLt27Qrb2SKEwK5du6z311xzTa3HTKXGECGEEEKOGe3bt8e+fftC5v/111+Ox3cWLlxYqxxDQD3fJiOEEEJINeg2WUSEEFY0u11ZWRm8Xm9EZdZrYyhcZQkhhBBCY5PV1ZQpUwDobYsHHngAycnJ1jJVVfHFF1/gjDPOiKjshHmA+qoebdCoSZN4V4MQQo6KMr+CUr8efl5SGcCfpT7sLfEBAIqKK3CoPAAA0DQBTeFQNH1doQloWvjfbk0TYEa4u56uRAIA+BQNSZqAamwXUDUrfF4L8/+A+XcyZ4BkvJEYg1sKhta7OKxpmQFM9QNalXB6AFAVZ+Hc1tvC5WCDgUuO0HrBpWB9hIDQDx6aWw177PWCRTlqfYI1hrZs2QJAb1t89913jqHB3G43Tj/9dNx5550RlR1RY2jmzJm48847Ha0yAKioqMDjjz+OBx98EADw/vvv44QTToioYoQQQgghJnMQ+Ouuuw5PPvlkrR+Oro2ImpUzZsxAWVlZyPzy8nLMmDHDen/WWWfB4/FEXjtCCCHkeEVjk0XkxRdfjGlDCIiwZ6i6h5e++eYbNG/ePOpKEUIIIcc9eoA6IocPH8ajjz6Kjz/+GHv37oWmaY7lv/76a53LrFNjqFmzZmCMgTGGU045xdEgUlUVZWVlmDhxYp0rQQghhBBSGzfccAPWrl2LMWPGoHXr1jEJ1qpTY2jevHkQQuD666/HjBkzkJqaai1zu91o164dsrOzo64UIYQQctyjnqGIvP/++/jvf/+LAQMGxKzMOjWGxo4dC0BPeNS/f3+4XK6YVYQQQghJJDRQa2SaNWsW80dyInpmaNCgQdA0Df/73//C3q8bOHBgTCpHCCGEEGL30EMP4cEHH8RLL70UEtUeqYgaQxs3bsTo0aPx22+/heQSYoxBVY9inoZaSm/iQpMm7iOvSAghx4HygIziSj0Hj9fI+WPmAaoIqFCMab9fhRLQwFT9j1pV0aCpwd91xe/8PZdk/X2Fn8Mj6+W7ZQ6Pn8Nt7MctcfgUvTwXZwhwBpeRM0gVAvb/NozZ1lBbkvFe4gyyuUz1g6kBQDNyCqkKmHD+Ee7oYTFzCTGu5xcCICQ3NDAr75GqCsf/X/pzJxw+cRRvPdFtsog88cQT+OWXX5Ceno527dqF3KX6+uuv61xmRI2hiRMnonfv3vjvf/8bs4eXCCGEkIQS7WCrCfp/78iRI2NeZkSNoe3bt+M///kPTj755FjXhxBCCCGkWtOnT495mRH1sfXt2xc///xzrOtCCCGEJI44JV1csGAB2rdvD6/Xi169euGzzz6rcf21a9eiV69e8Hq96NChA5599tmQdd544w107twZHo8HnTt3xooVKyKqW20dOnQI//znPzF16lT89ddfAPTbY3v27ImovIh6hm655RbccccdKCoqQrdu3ULu13Xv3j2iyhBCCCGJIh4DtS5fvhy5ublYsGABBgwYgOeeew7Dhg3DDz/8gBNPPDFk/R07duDCCy/EhAkTsGTJEnz++eeYNGkSWrZsif/3//4fAGDDhg0YNWoUHnroIVx66aVYsWIFrrzySqxbtw59+/aN+Piq8+233+L8889Hamoqdu7ciQkTJqB58+ZYsWIFfvvtN7z88st1LpOJCEZT5WEGlmOMWZmpG9ID1CUlJUhNTcXXv/yOJk1im76bEEIaqvKAZj1AfbAygL1lPvxRXAkA+P1gBQ6U6YO2/lXiQ2V5AAGfvm7VB6i58USz7JYguyR4kvS/oZOTXGiarP8hnJrsRtMkF1LN90kuJLv0B5cbuyUkuyTrvUfm1rRb0gdnBfRBWd0Sg9scqFVicEXyADXnANfrKLhc/QPUAmEeoNb/zzgxMwPFxcUxH/LBZP6/9GdRUVT7KCkpQXpG3erat29f9OzZEwsXLrTmnXbaaRg5ciRmz54dsv4999yDd955Bz/++KM1b+LEifjmm2+wYcMGAMCoUaNQUlKC999/31rnggsuQLNmzfDqq69GenjVOv/889GzZ0/MmTMHTZo0wTfffIMOHTpg/fr1GD16NHbu3FnnMiPqGdqxY0ckmxFCCCEkxkpKShzvPR5P2HFB/X4/Nm/ejHvvvdcxPycnB+vXrw9b9oYNG5CTk+OYN3ToULzwwgsIBAJwuVzYsGEDbr/99pB15s2bF8HRHNmmTZvw3HPPhcw/4YQTUFRUFFGZETWG2rZtG9HO4iktSUZKckSHSwghx5wyv2b1urgkBlUTCJih9X4VfiP0vcKvIuBToUlGOLoWDDlXFWH1DAlNQFM0KH59O5+kotwMpZdVuCVbaL3MwY2eFhdn4IzBZZTvEsLqnQGC0VASY/rL6BmSGAPTAvpCTQWEBqh6z5CjV0hozmdn7M/ScEnvHQKggUEVAgE1fM8QYKQaUJw9TvVJT7oYeUSYuW1WVpZj/vTp05GXlxey/v79+6GqKtLT0x3z09PTq21EFBUVhV1fURTs378frVu3rnadSBsmR+L1ekMagACwbds2tGzZMqIyI75Z+corr2DAgAHIzMzEb7/9BkAfruPtt9+OtEhCCCEkYQgR/QsAdu/ejeLiYus1derUGvdbNR1OdYOv17R+1fl1LTMal1xyCWbOnIlAIGDte9euXbj33nut55jqKqLG0MKFCzFlyhRceOGFOHTokPWMUNOmTeutW4wQQgghoVJSUhyvcLfIACAtLQ2SJIX02OzduzekZ8eUkZERdn1ZltGiRYsa16muzGj93//9H/bt24dWrVqhoqICgwYNwsknn4wmTZrgkUceiajMiBpDTz31FJ5//nlMmzYNkiRZ83v37o3vvvsuoooQQgghiUQzbhlG86oLt9uNXr16IT8/3zE/Pz8f/fv3D7tNdnZ2yPoffvghevfubUWSV7dOdWVGKyUlBevWrcMbb7yBRx99FJMnT8bKlSuxdu1aNGrUKKIyI36AukePHiHzPR4PDh8+HFFFCCGEkEQiYD6pFPn2dTVlyhSMGTMGvXv3RnZ2NhYtWoRdu3Zh4sSJAICpU6diz549Vnj6xIkT8fTTT2PKlCmYMGECNmzYgBdeeMERJXbbbbdh4MCBeOyxx3DJJZfg7bffxkcffYR169ZFcXRHdu655+Lcc8+NSVkRNYbat2+PgoKCkAep33//fXTu3DkmFSOEEEJIbI0aNQoHDhzAzJkzUVhYiK5du2LlypXW/+eFhYXYtWuXtX779u2xcuVK3H777XjmmWeQmZmJ+fPnO57N6d+/P1577TXcf//9eOCBB3DSSSdh+fLl9ZJjyPTll19izZo1YQeLnzt3bp3Li6gxdNddd+Hmm29GZWUlhBD48ssv8eqrr2L27Nn45z//GUmRhBBCSELRhP6KZvtITJo0CZMmTQq7bPHixSHzBg0adMTBTy+//HJcfvnlkVWojmbNmoX7778fp556KtLT02t8kLu2ImoMXXfddVAUBXfffTfKy8sxevRonHDCCXjyySdx1VVXRVSR+pYUKENSIDEHtSOEJB7J0yQYIq/JKPOoKDESKya5JSS5jcSHMockMyi230czcl1owkrAKIQKoQlwI3xeCaio8OvTHlmxRq43yzTD7AMah0cIqLb/uc2we8b0ZIsA4OJ6EkaP8SQrUyrBFD1JJFQFTFOAcM/IMKYnXJSMRIuS20q0qMkeKMZ+A4oGRRMw80mqtmm7inAz64kQAhHkPXZsn4iefPJJ/Otf/8K4ceNiVmbEiXcmTJiACRMmYP/+/dA0Da1atYpZpQghhBBCwuGcY8CAAbEtM9oC0tLSqCFECCGE1JF5myyaVyIyn1+KpYh6hg4cOIAHH3wQq1evDvvwkjmCLCGEEEKql6DtmajceeedGD58OE466SR07tw5ZLD4N998s85lRtQYuuaaa/DLL79g/PjxIQ8vEUIIIeTI4vUA9bHulltuwerVq3HOOeegRYsWMWmDRNQYWrduHdatW4fTTz896goQQgghhNTWyy+/jDfeeAPDhw+PWZkRNYY6deqEioqKmFWCEEIISTQUTRaZ5s2b46STToppmRE9QL1gwQJMmzYNa9euxYEDB1BSUuJ4EUIIIaRmWgxeiSgvLw/Tp09HeXl5zMqMqGeoadOmKC4uDkmDbY5Saw7c2pCwn78Aa5Qc72oQQki94KktgKQUqI30wTMlL4PEg/l8OAvm95E4g1R1lHHjARRNE1AV/b9ZVdWs+YwzCBlgXM9VxDmDX9J/68tljiS3Bp+xnV/RrLxCqnDm8+EsuG83Z/BK+nSSi8Ot+cEq9bsOzF8BFgj+Z8eEBpjBOpzr+YRg5hWyvZc9UIy/8xVFg9/YeUDT62LmHVI1QKvy+DIHQ+Ao5hkikZk/fz5++eUXpKeno127diEPUB8pQWQ4ETWGrr76arjdbixbtoweoCaEEEIiIET4PJJ12T4RjRw5MuZlRtQY+v7777Flyxaceuqpsa4PIYQQkhAomiwy06dPj3mZET0z1Lt3b+zevTvWdSGEEEIIOeoi6hm65ZZbcNttt+Guu+5Ct27dQu7Xde/ePSaVI4QQQo5XFE0WmWbNmoV9PIcxBq/Xi5NPPhnjxo3DddddV+syI2oMjRo1CgBw/fXXOyrRkB+gJoQQQhqSaCPCEjWa7MEHH8QjjzyCYcOGoU+fPhBCYNOmTVi1ahVuvvlm7NixA3//+9+hKAomTJhQqzIjagzt2LEjks0IIYQQQqKybt06PPzww5g4caJj/nPPPYcPP/wQb7zxBrp374758+fXb2Oobdu2kWwWV0JTITTqsSKEHMc4118G804CZ4DEGFxGGLtb5lbYPaCH02vGLRdNFVBVvc9B8avgxnpc5hCaADfKUBUNmhoMpfcrKvyqpC/TBPxGmL3m0ss19+fiHLK+GtwSh9usk1DAKkvBA0Zove8wmP9w+OOUPRDMOE7JDTAOSPrjGgo4KhR9n4omEDCeMvarAqoQVgRW+NB6WKH4R4NAlNFkMavJseWDDz7AY489FjL/vPPOwx133AEAuPDCC3HvvffWusyIGkPvvPNO2Pn2+3Xt27ePpGhCCCEkIWgi2AiNdPtE1Lx5c7z77ru4/fbbHfPfffddNG/eHABw+PBhNGnSpNZlRtQYGjlypPWMkJ39uaGzzjoLb731Fpo1axbJLgghhJDjmkB0vTuJ2RQCHnjgAfz973/H6tWr0adPHzDG8OWXX2LlypV49tlnAQD5+fkYNGhQrcuMKLQ+Pz8fZ555JvLz81FcXIzi4mLk5+ejT58+eO+99/Dpp5/iwIEDuPPOOyMpnhBCCCEkrAkTJmDt2rVo1KgR3nzzTfznP/9BcnIy1q5di/HjxwMA7rjjDixfvrzWZUbUM3Tbbbdh0aJF6N+/vzXvvPPOg9frxY033oitW7di3rx5jmgzQgghhARR0sXIDRgwAAMGDIhZeRH1DP3yyy9ISUkJmZ+SkoJff/0VANCxY0fs378/utoRQgghxysRHJIjklfC3ieD3g65//77MXr0aOzduxcAsGrVKmzdujWi8iJqDPXq1Qt33XUX9u3bZ83bt28f7r77bpx55pkAgO3bt6NNmzYRVYoQQgghJJy1a9eiW7du+OKLL/DGG2+grKwMAPDtt99GPFRHRLfJXnjhBVxyySVo06YNsrKywBjDrl270KFDB7z99tsAgLKyMjzwwAM1ljN79my8+eab+Omnn5CUlIT+/fvjsccec4x5JoTAjBkzsGjRIhw8eBB9+/bFM888gy5dutSpzqKiHIIncDOaEHJcYC43IOth5IxL+mj1AOBtAiF7Aa7/rNvjWxgDXBJzjFpvJzTnqPWaGRavarD+ZlY0QOZW4IzQBDTbfRq1mmmTuUuXFBy13sUBj6yXzyrLwAMVYD49nJ75D0MrPWRsLAGc68cOgEkuPZzeWCYkN1SunxOfosFn1D+gCfiNuiiqPmq9GYGlhs1YKFCpHL1UhhpESHh/XbdPRPfeey8efvhhTJkyxRExds455+DJJ5+MqMyIGkOnnnoqfvzxR3zwwQf43//+ByEEOnXqhCFDhoAbOS5qM6rs2rVrcfPNN+PMM8+EoiiYNm0acnJy8MMPP6BRo0YAgDlz5mDu3LlYvHgxTjnlFDz88MMYMmQItm3bVqewOUIIIaQhoVHrI/Pdd99h2bJlIfNbtmyJAwcORFRmRI0hQA+jv+CCCzB48GB4PJ6w44QcyapVqxzvX3zxRbRq1QqbN2/GwIEDIYTAvHnzMG3aNFx22WUAgJdeegnp6elYtmwZbrrppkirTwghhJBjUNOmTVFYWBiSz3DLli044YQTIiozomeGNE3DQw89hBNOOAGNGze2hud44IEH8MILL0RUEQAoLi4GACtp0o4dO1BUVIScnBxrHY/Hg0GDBmH9+vVhy/D5fCgpKXG8CCGEkIbGjCaL5pWIRo8ejXvuuQdFRUVgjEHTNHz++ee48847ce2110ZUZkSNoYcffhiLFy/GnDlz4Ha7rfndunXDP//5z4gqIoTAlClTcNZZZ6Fr164AgKKiIgBAenq6Y9309HRrWVWzZ89Gamqq9crKyoqoPoQQQkh9iiaSLNpbbMeyRx55BCeeeCJOOOEElJWVoXPnzhg4cCD69++P+++/P6IyI2oMvfzyy1i0aBGuvvpqSJJkze/evTt++umniCoyefJkfPvtt3j11VdDllW9BWdmuQ5n6tSpViLI4uJi7N69O6L6EEIIIaThcblcWLp0KbZv345///vfWLJkCX766Se88sorjjZJXUT0zNCePXtw8sknh8zXNA2BQKDO5d1yyy1455138OmnnzrC8TMyMgDoPUStW7e25u/duzekt8jk8Xjg8XjqXAdCCCHkaKJosuh06NABHTp0gKqq+O6773Dw4MGIhwCLqGeoS5cu+Oyzz0Lmv/766+jRo0etyxFCYPLkyXjzzTfxySefhDwM1b59e2RkZCA/P9+a5/f7sXbtWkf2a0IIIeRYQ7fJIpObm2s9n6yqKgYNGoSePXsiKysLa9asiajMiHqGpk+fjjFjxmDPnj3QNA1vvvkmtm3bhpdffhnvvfdercu5+eabsWzZMrz99tto0qSJ9RxQamoqkpKSwBhDbm4uZs2ahY4dO6Jjx46YNWsWkpOTMXr06DrVefOJQ9GoSRPsL/fjYKXee3VSs+Q6lVGfOGOQuG3azMNh5AYx7wpyBKeFcP5l4FcEfKoKADHJlSExBpek70zVgPKAivKAXn5FQEXB78URldu8sfvIKx0FSW69O9Utcbh4+NuuHlmCR+bwGrlQXJzBJQWnzbwtmhBGDhN9u3O84Z9pI6SumO8wtOID0CqN/DtuL5hs5NvxeMFcek+4MG8PCP27zxhs+XwYXDx4nbtlbuX38cgckszAjGWcM3BjGdcEuDlf5sZvkf6ecWYtkzhz5C6yv+ecQbLVRa9XcD1m/o+uKfrLqL/QbL9hRo4hZuRXEpIbQtLPgXB5IVxJ8BuJgyoVgUrVyC2kCQSML6VfEQhommOkd3uuIfP31x8+AVG9oFHrI/Of//wH11xzDQB9pPpff/0VP/30E15++WVMmzYNn3/+eZ3LjKhn6KKLLsLy5cuxcuVKMMbw4IMP4scff8S7776LIUOG1LqchQsXori4GIMHD0br1q2tl31wtbvvvhu5ubmYNGkSevfujT179uDDDz+kHEOEEEJIAtq/f7/1GM3KlStx5ZVX4pRTTsH48ePx3XffRVRmxHmGhg4diqFDh0a6OQBYmUxrwhhDXl4e8vLyotoXIYQQ0pCoWnWZsGu/fSJKT0/HDz/8gNatW2PVqlVYsGABAKC8vDziB6gj6hnavXs3fv/9d+v9l19+idzcXCxatCiiShBCCCGJxrxNFs2rvhw8eBBjxoyx0tSMGTMGhw4dqnEbIQTy8vKQmZmJpKQkDB48OGTg1MGDB4MZt1vN11VXXVWnul133XW48sor0bVrVzDGrDtSX3zxBTp16lSnskwRNYZGjx6N1atXA9Ajvc4//3x8+eWXuO+++zBz5syIKkIIIYSQhmH06NEoKCjAqlWrsGrVKhQUFGDMmDE1bmMOn/X0009j06ZNyMjIwJAhQ1BaWupYb8KECSgsLLRezz33XJ3qlpeXh3/+85+48cYb8fnnn1sR5JIk4d57763bgRoiuk32/fffo0+fPgCAf//73+jWrRs+//xzfPjhh5g4cSIefPDBiCpDCCGEJAoz8CKa7evDjz/+iFWrVmHjxo3o27cvAOD5559HdnY2tm3b5hhM3VSX4bOSk5OtZ34idfnll4fMGzt2rON9t27dsHLlylolX46oZygQCFgtsY8++ggXX3wxAKBTp04oLCyMpEhCCCEkoehDakRzm0wvp+oQVD6fL6p6bdiwAampqVZDCAD69euH1NTUaofCqsvwWUuXLkVaWhq6dOmCO++8M6TnKFZ27txZ69yHEfUMdenSBc8++yyGDx+O/Px8PPTQQwCAP/74Ay1atIikyKOmiUcOhkZLdR9cNlouboSshgmlD5dUWwg9FNUe+e1czxbOyhjcsv7eIwkrDD7iukrMqq/LzZDskqy/RFQhkNFEbxCX+VWU+RRUGk/z+RQNFca+/Ypmvcz3e0v0L6qqCajGt9kM9bXC3WUOtxHe65Y5XJyjUnGWCQC/H6yI+PiaJulhuo29Mhp7ZSsUWGLBkPmApkFSgUpjG5UzGFG7UG0fiv4XHhAwzsFt3yZmyGusSLaQbQAY0KF5rbbjzBneDQRTQlhpIfwqyioVa9pnXEsSZ5BtIeEz+zSOwZHUkar/cDPVD6bpdRSyF7xpS3AR/rdV8Co/42ZovaZaofQyZ44UEV4p+F1LcsuQXRJkl/5eUzSoCjf2LYIh94w5wulZNekoqtI0/bth9oAIAes7FNAENONvci65IWSvVX8ugk8HM9kFcNk6VuFpBOFO0qddSQgIIGCsrtp6W/QHlIWxLz2sPqAGf8McY3sZP5flMUhLcrRV7fmYPn16VEFHRUVFaNWqVcj8Vq1aVTsUVk3DZ/3222/W+6uvvtrKIfj9999j6tSp+Oabbxz5BOMhosbQY489hksvvRSPP/44xo4di9NPPx0A8M4771i3zwghhBBSvVhFk+3evRspKSnW/OpGYcjLy8OMGTNqLHPTpk0AQofBAmoeCst0pOGzJkyYYE137doVHTt2RO/evfH111+jZ8+eNZZdnyJqDA0ePBj79+9HSUmJI/X1jTfeiOTkYCLDzz//HL1796bhMQghhJAqYpV0MSUlxdEYqs7kyZOPGLnVrl07fPvtt/jzzz9Dlu3bt6/aobAiGT4LAHr27AmXy4Xt27cfe40hQH9qu+oYIO3atXO8HzZsGAoKCtChQ4dId0MIIYSQGEhLS0NaWtoR18vOzkZxcTG+/PJL627PF198geLi4mqHwrIPn2UOy2UOn/XYY49Vu6+tW7ciEAg4GlDxENED1LVVm6SKhBBCSCIyn2+K5lUfTjvtNFxwwQWYMGECNm7ciI0bN2LChAkYMWKEI5KsU6dOWLFiBQA4hs9asWIFvv/+e4wbN84xfNYvv/yCmTNn4quvvsLOnTuxcuVKXHHFFejRowcGDBhQL8dSWxH3DBFCCCEkchrgfIg7gu3ry9KlS3Hrrbda0WEXX3wxnn76acc627ZtQ3FxcIzKu+++GxUVFZg0aRIOHjyIvn37OobPcrvd+Pjjj/Hkk0+irKwMWVlZGD58OKZPn16nzNFHymdopvd57rnnarxFZ0eNIUIIISQO7BG1kW5fX5o3b44lS5bUuE7Vuz9HGj4rKysLa9eujbpuZm+UKRAIYMeOHZBlGSeddJLVGKrLgO7UGCKEEELIMWPLli0h80pKSjBu3DhceumlEZVZr42hI4XgHU3Nk2U0TnZBFQJmYzagCvhU1ZpO9dZ/29DM2+OWgnmGwp2l6tr7Vde151XRuIAq9PdeCUhy6TtQNAGfoiGgRd6pakYtOPK4GNMuI4eJmTvEh2AeoLJKBX5Fs3K5+FXN2g4I5oKROXPkFkpyS9YyF+eQWHBdVRNW+XXRxCMjNdlllW/uy8W5M6eSFMwz5OIMXplbuak4Cx43Z8yRd0nPX6Kv17qpt871Ox6Zf7mafwH3advsCFs4tzPzN5nXT6WqWXliXJKe+woAkl0SPBK3XTPMyiNW6uP6ex7MsdPYo3/X/apm7UviDG6JW5/9K7/p6wKALHEkuySkGts18UhWzh63pOcnchv74wj+9km2HGES1/OJcePbzRQfmOrXFyp+MDUAZubWERqg2abtNGf+MMY1YzUN0BQwVc9PxNQAJMljnQ+3xNDYrdc/xetCarK+Xmq5C4eSXVBVsxzhmLazL1MCqpVzqKJS0c+frH8epZLizBMWUFEe0JeV+RXI3GWcf4FK47NNdiWBa4qVSE3jMpiZV0iSIBgHrPcuQHLr0yz43dTPOYOb2z+LYG43/TrS96cqzl4Z87usHMXRT0WU0WT0XG5QSkoKZs6ciREjRhxx2JBw6vV/f/qgCCGEkPBUWwLKSLcnQYcOHXI8w1QXETWGZs6cibPOOgvnnnuuY/7hw4fxxBNPWPfr6ivFNiGEEEIS0/z58x3vhRAoLCzEK6+8ggsuuCCiMiNqDOXl5cHlcmH27NmYMmWKNb+srAwzZsyggVoJIYSQI4hV0sVE849//MPxnnOOli1bYuzYsZg6dWpEZUZ8m+zll1/G5MmT8e2332LRokVwu92RFkUIIYQknIYcTdaQ7dixI+ZlRpx08ZxzzsHGjRvx5ZdfYvDgwWFTdxNCCCGENHQRNYbMSImTTjoJGzduREpKCnr37o2vvvoqppUjhBBCjlfmbbJoXiQ2IrpNZo8SS0lJwcqVK5Gbm4uRI0fGql4xp4fWMnARHOlX4wIwolRVIVBY6kPA6HYMqJo1DQBaNd2RZmgpt4XSmhq7ZTTxSNa0WwqG37o5g2xbueo1HUnvpxCAZJ82mroBDZC5hMP+upXHWTA8WZ8hHCMsc1uIuUvicBmVNsOdAT2s1q8EQ+2r6xaWjNB6MzTaTv/Cs7DbNfHU/hJu7JWR5NbrluSS4LGF1ntkbn12LkkPxbZPm+ehamoBMx2+Hu6tWfXP6diy1vU6ngS0YOh7paKhPKB/wcr8KsoDKhq7a5dl1krbYKQ50Gzn2Tznku36dHHu/GzC/JnHmV4Xj8yt8OmA5izPXoZHdl4HyS5uhdObYfLmduZLfx9MA6GH1pth3gIQKphmhL5rCmCbZpoCGKH2TAlY60FTIJQAoIT/AjMumRNgmgJhhN4zTYHs0lM8mL899lQEKcZ3p2myC8UVblT49e1URYOqGiHsWvC3T2jCeJnV0qBKwTD7Cj9HaWVA35/MrfLKKhW4OLeuhWQXh181U20w+LiZKoHD7UoCmJlzxPYhMq6H0BvzBA9+75nQIHEJEjPK4YAQ5ueo/3YA+m+iS2JW+hGJMWjGLqwUEFFGd9UVRZM1HBE1hl588UWkpqZa7znnmD9/Pnr27IlPP/00ZpUjhBBCCKlvETWGxo4di48//hgff/wx9u7dCy2KZH6EEEJIIqJosoYjosbQjBkzMHPmTPTu3RutW7d2ZJpuSFmnCSGEkIZK00S1j2DUdnsSGxE1hp599lksXrw4opTXhBBCCNGfDY3muR9qC8VORNFkfr8f/fv3j3VdCCGEEEKOuogaQzfccAOWLVsW67oQQgghCYNC6xuOiG6TVVZWYtGiRfjoo4/QvXt3uFwux/K5c+fGpHKxJHFA5gATzAqhZozbRifX4OIafEbIZyVjgGKMaG8Lu7TKM8rQNAHOmSMs2ywz2SVZoaxmaKs5mrI+an3456vsXZ91GexWA7NC9DUBGJGmYAAUwAolry3GAG6EpTKmh6u6uLkvEUwnwAGXwqww5HKuWtMemcOnaMFQWkVzhMjbRww3w+vN9/ZR5F08GNZsD6cPqAIBLRi671e0sOfVLXO4Je4Ipw+GZbOw4fT2fdtD683H4sxzA5gh5RwBI5ig2KdYocTlARWdWzauxRk/9rkEg2pEeie7hHX9N/FoqFQ0lPmDI66bn71L0j9b+zkPfi85JB5Mh+GRgg+NcsasEHrzc7F/XezruSQGlxlHDQ3BvwM1cxDzsOkx7CHyUg3PQ3IW3E6y/R5InIHZQt0hRDBkXvVbI8xDU/UR5xU9NJ2pfoiAT1+m+CF8lXp4vbXD4HeZqXr5PKmRHkjOKwEAIuACl/TfZpm7IXMGt6xXzCtzuKTgqPJumVtpJ3y+4G8Y48HrXNWM/4CNz03TBBTjGpdkDtWWQqPCr6Dc+OyT3BICmmalM/ApwfQLiias31e/KiDJHjiSL4haBOcIDYwFn1fVp62FR94+jlQRTO0Q6fYkNiJqDH377bc444wzAADff/+9Yxk9QE0IIYSQY0lEjaHVq1fHuh6EEEJIQqFosoYj4oFaCSGEEBI5FVFmoI5ZTUjEA7USQgghhBwPqGeIEEIIiQPKQN1wUGOIEEIIiQOKJms46DYZIYQQQhJawvQMeY1cJpoI5u6RNUDR9FQAMmfwyNzKf+FTVVQqelsxoOpdmYEantwPl6Mm2SXBbebykBg8Erfy9NSUZwiw5xpitc41pIlgVg39OPVplTMENAFV1C3tgWTPqcOq5j9icHF9hltjSHYJK6+OR+YoD+j5QTyKioBLwGfkH6lUgnlDtCp/FUnMll9GYlZeFxdn4JwBRr4TewSFxAQkFVZOoiRXcBm3pXkw8wUF8wwxK8+KPh2a18heD2bljXHmXjLJgsMtAargxr5VK49OQNXQ2J0Yf3cENGHlBFJq+L6omoDGg3mGzM8A0D9Lew4rzhi4LfmMWaz98zUnzX+rfmUkFsz9o3Fm3V7QOIOZJY1z/foz1/PIkvVd9socyS4JXuML7JU43FIwZ5hbCtafIZifiGlqMK+QEHreHDN3jqbp+YWg5yBiit9aVwR8EL4Kfdpfqb8CRp4hzfbYrKaCJTWy1uNJjcDN8hmHZlzHHq8Mr8TgM675xm4JjY28QqnJLjQtd6HCr++7wq9C8etlqKoG1frOcus8mf+yan7DJM6DOZq4/h2ytos0/YrtQ2WaAqH69WkAnHG4uP5Jqpqw8k9Jglm/MQ0x64umCUfetUi2J7GRMI0hQgghpCFRo2wMRbMtcaLGECGEEBIH1BhqOBKj754QQgghpBrUM0QIIYTEgapF17uj1mLoNlI71BgihBBC4oBukzUcdJuMEEIIIQktYXqGzPBXe8i5ZIScA8Ewe9kK92Vwcb0PMqBpUDX9X8AZYm4KhtYHw7K9cjD81mOE4rolW7i4qGZkGcbNKHIIFgwpPxIhghlJBYJdqKoAJAYIUbe2L2PB1jJjzhB/zVa+zPXwVfO4k10akl36Qp8ioVLR4FODofVWWLMmHOPySLbD5JxZ55Sz0DQE5l9EHiGgCslRJg8T7muG0odLgeCROVycB0OjGaywfok7w7IlzqxzYq9TwPgLz0zVoMoCPiOMvzzAsGbnQRyq0EOj95X4rGm/okHVBPyKfi24ZQlJRshzkktCE6/+FW3e2I2mXhf+dnJSyLHFjNBwiDWq0yaq0L8PVvgyANWWjoExW7oChTky5prXj8ThOP/cntIBLExIdHBGddkp9O+5sbDKr1xAE6g0CuWqZoX4m9eZGfrtlTk8UvC77HUFv88y1697QL9uJRaslcQZmHk+hPM+BrOF1tun9ZB7AZhh+Iofwl+pL6osh/BVBN/bQvKhqWDGfOb26uH1qhGuzzg4M2PM3fDIjeAxvnDJLgmN3bIxrSDJLSHJeJ/kVuAzUkHIAckKn9eMEHvZSC/AZQ7JOD9cYpBkDrdxzbvlYBoLc9p+Ls1lsu17LnMGDmE7NiX4Yy00x/kSXAZTjTQEMMLrXWYaE26lGBH2FCNCwCW4dT3Yr0U9dQgD14T1uR4N1DPUcCRMY4gQQghpSCjPUMNBt8kIIYQQktCoMUQIIYTEgSqEdassolc9jk128OBBjBkzBqmpqUhNTcWYMWNw6NChGrd58803MXToUKSlpYExhoKCgpB1fD4fbrnlFqSlpaFRo0a4+OKL8fvvv9fPQdQBNYYIIYSQOIiqIRTlLbYjGT16NAoKCrBq1SqsWrUKBQUFGDNmTI3bHD58GAMGDMCjjz5a7Tq5ublYsWIFXnvtNaxbtw5lZWUYMWIEVLWaZ2iPEnpmiBBCCCGWH3/8EatWrcLGjRvRt29fAMDzzz+P7OxsbNu2DaeeemrY7czG0s6dO8MuLy4uxgsvvIBXXnkF559/PgBgyZIlyMrKwkcffYShQ4fG/mBqiXqGCCGEkDhoqD1DGzZsQGpqqtUQAoB+/fohNTUV69evj7jczZs3IxAIICcnx5qXmZmJrl27RlVuLFDPECGEEBIHiiYgRdGgUYxtS0pKHPM9Hg88Hk/E5RYVFaFVq1Yh81u1aoWioqKoynW73WjWrJljfnp6elTlxkLCNIa4LReIamQEYRBWPhnBAMaElbeEMVj5RvT8ORrMjjRHrhShl+GSgutyR44aOKbN91yoYGZOkXDM/CCs9p13jHErJ4gQtiKEftxG+po6CeZ7Aez5XTQAwtiX/iAfg8rNnE3cysHjlTk8igafkaPEIwXzDAXC/GVjz90TPP+heYZMqiagCWe+Iqss2yYuiYMzWLmQ7PmgXBLTcwmZKVmqTrNgvSSm51yqWr7EgABj4EyviF8NXgeaENA0gQq/fk+83K9a035FNfITCev4VS34mVv7NfLf8PKDYc9DtASXAS5B8jau24aa0K8RLXihCPNYbImqOBi4y3b9OHK8MEduJz0/UXA7xoK5YuxC8w/ZjkcAmpVtRs8tY98njDw3EkNIriv7dWd+rz0yN66FYC6k4G+FsyJCBL8pgnFHriHBuJV7KbTSwfxBIhCAUPRcVMJXAc3INQQAUAIQ5nqaBh7Q12OaBg5AyG69jo38EOZvjKboxwazzvZrmsEtc7iNi17iLHiNy9z6PAVn4BKzfmM403MLmevZcwtJnDlyDul5pJzfN/N8W7+JDGCaEjxfWpicTLb35jlg5nk1jlWSPZDN3EKasMp3cT1XmgYz95sEQC+Da3oOLP034tjLM5SVleWYP336dOTl5YWsn5eXhxkzZtRY5qZNmwCEXtcAIIQIOz9a9VVuXSRMY4gQQgg5Hu3evRspKSnW++p6hSZPnoyrrrqqxrLatWuHb7/9Fn/++WfIsn379iE9PT3iemZkZMDv9+PgwYOO3qG9e/eif//+EZcbC9QYIoQQQuIgVkkXU1JSHI2h6qSlpSEtLe2I62VnZ6O4uBhffvkl+vTpAwD44osvUFxcHFWjpVevXnC5XMjPz8eVV14JACgsLMT333+POXPmRFxuLFBjiBBCCIkDVUSXK6i+8gyddtppuOCCCzBhwgQ899xzAIAbb7wRI0aMcESSderUCbNnz8all14KAPjrr7+wa9cu/PHHHwCAbdu2AdB7hDIyMpCamorx48fjjjvuQIsWLdC8eXPceeed6NatmxVdFi8UTUYIIYQQh6VLl6Jbt27IyclBTk4OunfvjldeecWxzrZt21BcXGy9f+edd9CjRw8MHz4cAHDVVVehR48eePbZZ611/vGPf2DkyJG48sorMWDAACQnJ+Pdd9+FJEXwUGsMUc8QIYQQEgcNeaDW5s2bY8mSJTWuI6r0TI0bNw7jxo2rcRuv14unnnoKTz31VLRVjClqDBFCCCFx0JAbQ4kmYRpDmtBfqgi2ZoUI3nPVhNDDcY1rS5/W3+jjxzjf28sFBLhmhpsKW0h1cP/mJtasmkLmGYeoTUh9lXUEY9Z+NCGsfQljWrbC7gXMYF9VQwh7eoHqcASjqRljkCCs45UYg8tWNRfn0CTz3DFowixYs85VVfYQZz2svJp6SAwAQ3W/CeZ2ZvoDe7oEM2xa5sxIfWAL97WFHZtpGcy6mFWxh/urQv/s7YcTvF70NAJ+I71ARUBFhV8PA1aqJE/zyNyaVjURTFEgcTR2SxBy5LlDaiJkN8Aj+zkQVb5T4TBmT8wQPNdAMHxesoXh27fj+kdsMT/rcNdETf83cCssHlYKBH2eM8xfsoeO1/AlCP5WCGiCWaVoQljh5wzc9j0NpucAjHDwKmUKzQwrVwEztF4JQPgqIPyV+qKAAmF8cbWAYv2ISy4XhOKyQs7NMP3q1PY/UutYjO+t9d4Wgs+M82b/3tjTQujz9PLMVArmtLWfqvsVmiMtgYMtzB6COdISME0FZ8EQf+OnB0zT06CYZ0XiAi7BjXrov19cC6bcIIklYRpDhBBCSENCPUMNBzWGCCGEkDhQhQZVq6b3q5bbk9ig/kBCCCGEJDTqGSKEEELiIFZJF0n0qDFECCGExIGqCXB6ZqhBoMYQIYQQEgeKpke5RbM9iY24PjP06aef4qKLLkJmZiYYY3jrrbccy4UQyMvLQ2ZmJpKSkjB48GBs3bo1on2ZI4Orxgjnqgg+ya+Puh5Mja4KgYAqENA0/WVNC/2l2l+aY12fosGnqvCpaui+RDDEXzAGweUaXpL10lg1LzDHS9WE7Rhg1TG4f9vxa/pLCBHyCp4XM2waweMwXhqcZdi/k8J+nGG+5/YICk2IsC9VBJfpI9PD8TJVfR8J8xitl2Oes3BnugTnedPs15QQqFQ0VCr6NVHmU1Baqb/KKgO2aQUVxij2FX4V5X4VfsV4qZo1v1LVUBFQIWR3vbxgXHeO70RtXrZr2/oOGdeFKoTjOqjuZY4uX/V91WtJE3BekxpCrgt7GfZpMzVG8GVuE6y7eT2ax6bZfg/M1Bv23wjH98nx2espExRNHyFdk1zQJBcElwEuWd9xSPp7cCk0TYamQqj6C5oKaBq0gGKF1QvNeIXJjcG4BGYvl3GAy87vsGb/rulpH/yq/nJc75qAsL30utmmjWv/SKTqMxRUSxgpRhxpRszjOULqEWZ7mbiVBsBM2cCsl54ORE+34YpvImQSJ3FtDB0+fBinn346nn766bDL58yZg7lz5+Lpp5/Gpk2bkJGRgSFDhqC0tPQo15QQQgiJrTr/8RHmRWIjrrfJhg0bhmHDhoVdJoTAvHnzMG3aNFx22WUAgJdeegnp6elYtmwZbrrppqNZVUIIISSm6JmhhqPBhtbv2LEDRUVFyMnJseZ5PB4MGjQI69evr3Y7n8+HkpISx4sQQgghpDoNtjFUVFQEAEhPT3fMT09Pt5aFM3v2bKSmplqvrKyseq0nIYQQEgm6TdZwNNjGkIlVGRtICBEyz27q1KkoLi62Xrt3767vKhJCCCF1pkXZEKI8Q7HTYEPrMzIyAOg9RK1bt7bm7927N6S3yM7j8cDjqZ/BLAkhhBBy/GmwPUPt27dHRkYG8vPzrXl+vx9r165F//7941gzQgghJHp0m6zhiGvPUFlZGX7++Wfr/Y4dO1BQUIDmzZvjxBNPRG5uLmbNmoWOHTuiY8eOmDVrFpKTkzF69Og678uRX8OcZ+QEAfS8IAHbxWXmF9Kn9fkB24WnOXJrCGhCv3XnkjhUY5lHEnBxfVrlDIomwI07fJwBMtcTWlRN06GZCVIAhLvUq7v+zVw35nbmtGrkSLGWCeHIq1KVlY8DwfXCtZrN82jlX9GC+zPPQUAV8KkqKo3sYHpOJnOZZu3f3I89H4lZD4kzcM15a9S+nlrN+ahalir0XCLB2hvTEgCNAcZnpWn6WxizNQCaURfOBIyP2nG7NqCZuWX09+UBFT7jhJQHjDxCAVV/71dRUakY5y6YuwUAyqocQ5KR9KSsUkGySwJ4/XxlzRw4qlq37ew5uvT3zmkzZ5CZtyociQPggBDBPDCqsR1ncHwJql77vMod8+A1Hty3X6ndNcgZg1R1h3YyEPwmhFsneI1ItutHsr7zEjjjwdw3QtPPOwBwVc8PJLv0kmQ3mGT8PnAJ4BxMCv0WcrcMbmwD2Q3m9oK5vfp2khtCchvTLus3DoCVAwsAfIqm5xky3lf4VWjGh6UpwfMjNCOnli3fkHmbRlOdZagi+Ftqz0MFwMrZZE5rxhkR0HMLmTmEGA9OC30GmDEwqX29I+UcstPzCwWnrfPIGDQhIBl5h44W+/mMdHsSG3FtDH311Vc455xzrPdTpkwBAIwdOxaLFy/G3XffjYqKCkyaNAkHDx5E37598eGHH6JJkybxqjIhhBBCjjNxbQwNHjy4xpYtYwx5eXnIy8s7epUihBBCjgItyoeg6QHq2GmwD1ATQgghx7PaDmdS0/YkNqgxRAghhMSBfZy3SLcnsdFgo8kIIYQQQo4G6hkihBBC4oCeGWo4EqYxFLCFzpuXjz0M2FxmDzc1pzXhDLu3h6OrQg+dVY1YbPM9APhkFW5jvqwJMBYM5wwXvGm/rs17wXW51u3h9M7w+WB4vVl/s9hw5atWqHGwnuEiru1lmOH1gH4u/YozRYGZpsCnagioZvgtoNimJQYotvK5EQNrhtVLNUS82sPrqwvP1wRDgOkrujRmpT3QpzlckrkfBmEsE4xBQFih3hJn1rmQePD8KZqA3xay7VM0lBuh9JWKirJKBWWVAQB6mHzApy+zPmfbB2EPr09y62ekiV9GeUCFkOsnoahgHIJLCPiUI69sU3NofTCcXv8OhY+t5xpzhDRLHI7wZsac6Sfs37+qYdCarR7mdKWiwadqttB6zfqcFFULuXbM607VhFVGQNOv4WQjit0NZvs+wZG6QuJwXCP2aYkBkqQXwoVmhYpDaBCyG0zVrxHmclkh8izgB1MC4Ob501QIzbh+NA3MY6zn9oJ5vNZ7yC4Il369aLIH/koVfjV4fZqpHyoCqp7uwa9/9n5FgxIwvpeqBtX8HVSFPu0Oni/zPxBV4lAUDT5jXXuYvV/RjN+BYGoD6xoRLJiSQxOQZQnMSDkCLgPcvB4l/RwJM5yeBcPuJVlf1xZqb3429t9EM6Tfnn7BFEzxIcKmG6kvQtNf0WxPYoNukxFCCCEkoSVMzxAhhBDSkFA0WcNBjSFCCCEkDuiZoYaDbpMRQgghJKFRzxAhhBASB5RnqOGgxhAhhBASD1E2huoUbkxqRLfJCCGEEJLQEqZnSBECiiasnCCAnlPCzDdi5hgy82RUKsFcJAFVs3INAaEPrSkI5ibRhLByn3gUDR7JyGXDhZ6PyFimMjiT49hUzRdUWxpQJfeJmTtDr5d9d9Z6cJYvRDAXkioAXiUjkj2ti/08mrmMAMCvBHPKmPmazJwmlYrmyC1krlf1nHLOrAQt9hw0dWXmHOKcwcUZXJLe/tcEg2akM9GnBTQjh4lLYtCM41YBSEKvg3msku38mMwcQ37bcZrXUlmlgnK/itJKPWdKwKc48vloIvxfh2UAkt163plSj4zGXhmakaMm1oTQvwNKHf/SND93M1eMogVzSgU0zZH3p7o8Q+bna3w0Vl4p+3LV9j0IlweGM6Zf47a8RuY2Va9Bn2LLeaMF17PqYew+IEvWd97FNaguydp3spAgZPNactZFtV0vGoT1F6cAIFgwP5dLcge/REID1ACE5AcAMG8jsICRc0jR8wwFT4AKZuYZUlUwbyP9HCQ1Avc2AvMk66vJXghZzzlkXp/m51seUK08WBV+1co1BOjXp2JMKwEVqpEzTFOMz9Nv1MOWb4hxBtnNrdxCFX4F5X79v5fGxnfB+j21XSOqLGz5yZiej00yChYimEhHaIAWzMskGAe4ecHIEFyGML4bGhhU41pTNeH4HVRt10VADf5OOa7TcEnV6okmBFgUEWFHMyfS8S5hGkOEEEJIQyKq+UOoLtuT2KDGECGEEBIH9AB1w0HPDBFCCCHE4eDBgxgzZgxSU1ORmpqKMWPG4NChQzVu8+abb2Lo0KFIS0sDYwwFBQUh6wwePBiMMcfrqquuqp+DqANqDBFCCCFxoGnBxIuRveqvbqNHj0ZBQQFWrVqFVatWoaCgAGPGjKlxm8OHD2PAgAF49NFHa1xvwoQJKCwstF7PPfdcLKseEbpNRgghhMRBQx2O48cff8SqVauwceNG9O3bFwDw/PPPIzs7G9u2bcOpp54adjuzsbRz584ay09OTkZGRkZM6xwt6hkihBBCjmElJSWOl8/ni6q8DRs2IDU11WoIAUC/fv2QmpqK9evXR1tdLF26FGlpaejSpQvuvPNOlJaWRl1mtBKmZyigCvjVMKH1tjBgMwQXAHyqM/xW04Kh9ea2dpIRDqxxZoXZ+xQNPlmP03RrDIwBnOnbcaaH2drZezztIfK1JYSwyhDCFi5qHLMZRq8vc+6nOowFV+AMsEfiW2HMEBAC1rn0qap1HgOqgE+1nVdFc4TTW6kNqlZEDYYn28Odq2MPcw+3rkvi0DizhUozuIxpj8ShCoaAcawujcHFnWH2ZrStxI20CHD+JWGG1ZvHWR4IngMzdLnCClfWoBjxu5oR+mtGEMsuCcy4fhp7ZaQm62HGrVI8aNXYU+fQ99rSjND6QB3L10Py4QhX9qmqNW3O1wSs71M4emi9+XkH59tTGtjrWh3VTH9hSyVRHlD176Ki16tS1awQcL8SnJY4s14AkOTW4FX0T9kj62H1mpCC+zLD7F2SdS70cgDV+KJIgjnC7DUjBQAAMIlBNlMlCA2QFQjNSLmgqWBJRsi8pgKaBmFck0LTACO0nmnB0HrmTQZLagQhe/T1ZA9glK9o+u+fGU5fNfVDWWXAcX36jdQPgUrVqq+maFBVDcI8Xk1AGFHwjKsI+Dh8Rn6Ecpmjwha67/c605aY14hX5VC4sOqoaLAuAFlyWaH1TGiABAhhu4aYcT64DHAJguv10kPm9VUCGqxrWjGub78S/J2yQvxt11d1KSDqg9CC2QMi3R4AsrKyHPOnT5+OvLy8iMstKipCq1atQua3atUKRUVFEZcLAFdffTXat2+PjIwMfP/995g6dSq++eYb5OfnR1VutBKmMUQIIYQ0JJomwGIwUOvu3buRkpJizfd4PGHXz8vLw4wZM2osc9OmTQAAFia3mxAi7Py6mDBhgjXdtWtXdOzYEb1798bXX3+Nnj17RlV2NKgxRAghhBzDUlJSHI2h6kyePPmIkVvt2rXDt99+iz///DNk2b59+5Cenh5xPcPp2bMnXC4Xtm/fTo0hQgghJNEc7TxDaWlpSEtLO+J62dnZKC4uxpdffok+ffoAAL744gsUFxejf//+EdW1Olu3bkUgEEDr1q1jWm5d0QPUhBBCSByYjaFoXvXhtNNOwwUXXIAJEyZg48aN2LhxIyZMmIARI0Y4Isk6deqEFStWWO//+usvFBQU4IcffgAAbNu2DQUFBdZzRr/88gtmzpyJr776Cjt37sTKlStxxRVXoEePHhgwYEC9HEttUWOIEEIIIQ5Lly5Ft27dkJOTg5ycHHTv3h2vvPKKY51t27ahuLjYev/OO++gR48eGD58OADgqquuQo8ePfDss88CANxuNz7++GMMHToUp556Km699Vbk5OTgo48+giRJiCe6TUYIIYTEQUMeqLV58+ZYsmRJjetUzXM0btw4jBs3rtr1s7KysHbt2lhUL+YSpjEUMMIq7SHn9lGLKxXNCgM33ytVRrY2wzDtF6AZkmmGYgcYrJHRKyUNHiOc1CMJcDD4bbHpsi2G2H5R2Uefr7q/mtjXso8ib4Y/20Prq5Ztj3qWbP2FNY0Wb99WE85zaQ+jDWjCeu9TVCvU1W8LcQ5Hsp0f+3Q4qq27ONx2AU04R63nzAq9VjUBl8bh4mYYN4NqnIOApn+2Lim4zDwlEguey4CmOY5bv96CI2f7FRWKsUw1QpQBczBuZ3e3bIQuN012o4lH/4q6jRHSP/r1EADAK3N4jHlemePElPDRI+GEiwYxT5lSxxG7ze+FeaxVp+3pHaqG1pvLzLB6c7T6mtIoqEf4XpjXQUAL7tunaCgPqI5QbzOM3K9oVroCuUpovV/R4Hfrn0UjEbo/ezi2V+YQQv88JNuo9QLCSqGhj2YPuMzB1hmskddl2QOmKRCqMTq9SwE346bNUeqNdZmmQRih6dBU8KTgqPXMkwxN1uPdhcsLleuh9f6ACsX2PawIqCgzwufL/fqI9QHjvd+nQDFi05WAal2rqqJBaKp1rQqXFEwTwAFJ4vAbH16FzFHhN8uXUVapoJFxXfsUjkojZUGyS4OsGedAE5Bs1x+XJHAjTYAVg27/DIxQesE4BJesz1EP0Q9O+23XRGUgfPoUkyqAihp+k2KNxiZrOBKmMUQIIYQ0JDRqfcNBzwwRQgghJKFRzxAhhBASB8IY3SCa7UlsUGOIEEIIiYOGOlBrIqLbZIQQQghJaNQzRAghhMQBRZM1HNQYIoQQQuJA04SeByWa7UlMJExjyK8I+BU9B4ozz5A5rVk5cQA9N4nPSLqiCj2PjJnDRNWEI68NAPi5npvCLXOrDHteGxdXIXGAMSNXCAvNW1I1TxDgTKtxJBqEtb4mgtuqQs+5YqbU0ISwcqSEzWFkz/VRJSeNZHsfzKNj5hnSy9JzNgVzefiUYG6PSkW1cgvp+XeC01WZ+V7C5Rgy54XbLtx6bpnDzxnc9s/GzEXCmZWHCICRc0hY27u4gMvIgcMZs86BS2LWOfWpqiPPUEVARVmlnmeltFJBaaUCv5HHJeBTEKjUT7ImnGn1Az7FyvdyqNyPJCPPTeNKBUkuyaqj/hnCmIZ17msnmN/HjrHgZ1pbZl4hMwdXQBPWZx+wfU/MvD/V/Xhzzqz6HCnPUE15tzTb/sxrvDyg5xUyP48Kv+r4nMw6mjmGzM/Xrzi/85on+HOpitCcR8kucxmzjkESweOROCBY+O80lyQwyQ249DoyTYGQjGlPMrimwv7JMM3MU6WCeZP1ed5GEJIbQvbqyyQ3/MZn4VcF/KpAuZFrqVLVrFxLZT4FZZUK/D79vVIl55Cm+K19aQE/hCfJONduyJp+fXLGwBgDN3Jf+XwKSiv1ZUluBcluCYeNfXtkCR5Zr5dXVoPfcyaMc2+eIA2ykVuJcwmMwZGgUJi5nITxW6Ka+cuELZeZsHJnmTmGzHNQNc+Q+Xmay0liSZjGECGEENKQ6EksI298RbMtcaLGECGEEBIH1BhqOCiajBBCCCEJjXqGCCGEkDgQmhZlz9DRG0fteEeNIUIIISQOhKoGB92NcHsSG9QYIoQQQuJAiCifGRLUGIqVhGkMVQQ08IDqCCsPqAI+MwxY1cPqfVYIuIZKM7TeCAG3h9mazGm3EVLqVzRr2sUZZCk4LTme0OLBMGk4Y22FiEVofTCU3kwnED60vuYyw0S1A9BD7AP2sOMqofWKsbNKI7S+wghXrfCHD61XwlREtu08XHh9bdjD890ytz4bt8xDwuwVY117mL0eWs/g0owQXxZML8CVYJ18RmoGMx1DuS203gxdDhihy36faoXZm6NWmyHhfp8KX4WxnUdBWWUAAHDIJcEtcyv8XA8d1/etCQElot7y4Dk3o+zrGlZspqewh9Pbp6uGutcUWm+dV1b9Z22/dqurT9X1yir1819uhJJXGKH2AOBXgmH2shlab6ZtEC7rujxSCgf7YhcPfk4uKTTM3rgEwaqEkXtlDyCMkHlVsaYhBJi3kfWAp703gGkaeFIjfb7shXB5IFwe470Hfn/wsygPqNbnW2pck/r5CThSOvgrgtNKRZkVWq8pfj283ngvuZMgtKRgXTiDJOvbcc5QZqQJSHYHkOSSrDQRXllCsks/mvIAh8tISyIxBolpECL4+ZvnlTOhh+7bLg3N9tmoIvgbUjW03jxm8/jNNB96aH1oipFKCq1PSAnTGCKEEEIaEoomazioMUQIIYTEATWGGg4KrSeEEEJIQqOeIUIIISQOqGeo4aDGECGEEBIHlGeo4aDbZIQQQghJaNQzRAghhMSBpqlAFD1DGt0mi5mEaQyVKyqYlWdInxdQNVueIYGAplk5R+y5SFRNOHLi2HOOmLktPEbyEHueEokzuBx5hpz5U4TQl4XPM2Tm0HAeh3aExEPB/EFV8wwF620/B1XLUzURNqdPuNwvwTrqeT0UW36ZSitfk+rILVThD+Z18Ssa/LYDrJrLxX4epWpyz9SUc8a+jVvmkI1cQ+Z7czrJLcGtCVtuGA0ubnxukp5niBt1dkncyhtjPyflARU+NXj9FFcEcKhczxFUGpLHJQB/RQWA4D1/M3dMIMmFgE/PxxLwKVYZSW4ZyZWSVWdNSNaxKyqHX635uqhO1dNaHqhbt7uZn8uZZ8jMLaSF5BmqLl9P1c+46vVmv06r+8zN7ykAR14wM8dQmXH+K/zBnEN+RbOuTalqniFNQPW6QsquShMCmpBsdbddPxpzXEsSA4Jn2JlTR+IMLtnIEaTZ8wzp/zKv/pYB1n+gQtMgXHquHz3HUBKErK/o02BdFz5FoMyvWp9vWaWCQxVGDqvyAHwV9jxYCvyHSwEAgfJiqEZeIaGp0AJ+SB59f5rit3IOCa0xOGdgxrljnEE2cgmVVkpwywEkG3mGktwSvLKZtyuYO0if5sHfJgAuY5oxgEMYuZmM02L+1kH/nTR/SxTbcTtyK/n1afM76lPUYK402zVVEVBwtNAzQw0H3SYjhBBCSEJLmJ4hQgghpCGhnqGGgxpDhBBCSDyoKgSPokFDA7XGDDWGCCGEkDgQIroHqGmg1tihZ4YIIYQQktCoZ4gQQgiJA6Fp0fUMUdLFmEmYxtBhvwLhV6DawtY1TaCySmi9GU5f4XeG1iv20Hp7mK8VyhsMrTfD7MsqFbhrCK33GNG4Voi6rdxIQuud28MKdzaPuabQei1M2DAPE2JvLWPMCqU3yzf3V6kGz6Nf0afNUOaKQDDM3q8Ep2sihTl3juOuJiTfzi3rYemSnxnvuRXq61c0R6i9xJnjc3NJ3BF2b05Ltt34FA2VttD6skrFCuUuNkKXfRVGaL1PgVJRBiD4AKX5IKQvqTFcHv1r6atQUO6SjDL8SHIFQ+tVTUA1wrk1WyqDupKq9A2bYci1FQytD4bT26ft6Siqftbm51b1863tZ22fljirNrS+1PgsKvz6+S+3fbeVgAphrKdwBsaY47o3yzBD7MPWyZZiAtDTL7i4Ma2xKtMcboQ/PokLSLL+mTLZYwutF8FpQJ82fjuY0KC5jHB82Qvh8lqh9v6AgN+oU6WioTygosw4B2WVCsoq9dD6yooAfMYLAPwVFQiUF+vTh4ut8HlNCUBoKlR/pV5ftxeSLexel2xV0/yeMOPzDZfWgjNbKhLGAMhW2L0qBFRjGWfMCq83mWdE/y4E05z4VWFdx/ox69NlPgWVqmYts6f8MMsBgMrDgaofTb0RUeYZogeoY4dukxFCCCEkoSVMzxAhhBDSkOi3ySK/1UW3yWKHeoYIIYSQOLDfJo/0VV8OHjyIMWPGIDU1FampqRgzZgwOHTpU7fqBQAD33HMPunXrhkaNGiEzMxPXXnst/vjjD8d6Pp8Pt9xyC9LS0tCoUSNcfPHF+P333+vtOGqLGkOEEEIIcRg9ejQKCgqwatUqrFq1CgUFBRgzZky165eXl+Prr7/GAw88gK+//hpvvvkm/ve//+Hiiy92rJebm4sVK1bgtddew7p161BWVoYRI0ZAjXPOJLpNRgghhMRBQ32A+scff8SqVauwceNG9O3bFwDw/PPPIzs7G9u2bcOpp54ask1qairy8/Md85566in06dMHu3btwoknnoji4mK88MILeOWVV3D++ecDAJYsWYKsrCx89NFHGDp0aL0cT21QzxAhhBASB5qmRv0CgJKSEsfL5/NFVa8NGzYgNTXVaggBQL9+/ZCamor169fXupzi4mIwxtC0aVMAwObNmxEIBJCTk2Otk5mZia5du9ap3PpwTPQMLViwAI8//jgKCwvRpUsXzJs3D2effXadyjjsV6H5VahCOEbSNkc6NkPAzVDLcr+KikDVUeuD703mdDAsOxg2qr8Phoba11c1CQHZGVJvjxC3h8Hr6xz5GGsKnw+owhHCbw+lj2TAc4nBMeKzPXTanpbAp2ioCKi2lAWKY9T64PmoYfT5I4TWV90+fGg9h0fm1jK3LKEioMcnuyV9mSO0vkoYsLmdi9tGrbftp+pxHjjsx4Ey/Qep8nAAleX+YOhy6V/wlf0FIDhavfkXnuROQqWrJQBAdnFIRj0Oyc7rqolXDqYocEtWyHRdVB0ZHoCVDqC2zBHrA1ZYs2ZLnaCFhLrbPyczFFo+Qmi9GTYPhH73pCph8Ip9f8IctT6A0kolmO7Br0IJmKH1mhVaz7geVm+OjK7ZrmklzKj15vvGXhmaJqAZaRACmoDLvF600DD7gKYvEy4J5mD3AoCkCjAjYDzJ5QGvmkaD+42VNSvUXgDWKPXC5YGQvQgYm/lVgUrFOAd+Pb1AsXEN6tenXp6vQoG/QkHlYT1k3l/6F3yl+vXpLy+BFjBD6/0Qmgouu/XPxZME2Qiz1wJ+xzMsmjGKvXlei20h9G6JV/t9VoVAQNNPilfmUCUzBF8YofXB7TQE04+oQsCvhI5Ubw+tLw+oOOwPXgdllcHfImv/moCv3B+2bg1ZVlaW4/306dORl5cXcXlFRUVo1apVyPxWrVqhqKioVmVUVlbi3nvvxejRo5GSkmKV63a70axZM8e66enptS63vjT4nqHly5cjNzcX06ZNw5YtW3D22Wdj2LBh2LVrV7yrRgghhERMqBqEqkbx0htzu3fvRnFxsfWaOnVq2P3l5eWBMVbj66uvvgIA648CR32FCDu/qkAggKuuugqapmHBggVHPg+1LLc+Nfieoblz52L8+PG44YYbAADz5s3DBx98gIULF2L27Nlxrh0hhBASmViNTZaSkmL1vtRk8uTJuOqqq2pcp127dvj222/x559/hizbt28f0tPTa9w+EAjgyiuvxI4dO/DJJ5846pWRkQG/34+DBw86eof27t2L/v37H7H+9alBN4b8fj82b96Me++91zE/Jyen2vuLPp/Pcb+0pKSkXutICCGEREJoKsCO3gPUaWlpSEtLO+J62dnZKC4uxpdffok+ffoAAL744gsUFxfX2GgxG0Lbt2/H6tWr0aJFC8fyXr16weVyIT8/H1deeSUAoLCwEN9//z3mzJlTp2OJtQZ9m2z//v1QVTWkJVrT/cXZs2dbeRFSU1ND7qUSQgghpHqnnXYaLrjgAkyYMAEbN27Exo0bMWHCBIwYMcIRSdapUyesWLECAKAoCi6//HJ89dVXWLp0KVRVRVFREYqKiuD3689hpaamYvz48bjjjjvw8ccfY8uWLbjmmmvQrVs3K7osXhp0Y8hU9V5iTfcXp06d6rh3unv37qNRRUIIIaROGnLSxaVLl6Jbt27IyclBTk4OunfvjldeecWxzrZt21BcrI9j9/vvv+Odd97B77//jjPOOAOtW7e2XvY7Of/4xz8wcuRIXHnllRgwYACSk5Px7rvvQpKkejuW2mjQt8nS0tIgSVJIL9DevXurvW/p8Xjg8XiORvUIIYSQiB3t22R10bx5cyxZsqTm/dsiHtu1a+d4Xx2v14unnnoKTz31VNR1jKUG3Rhyu93o1asX8vPzcemll1rz8/Pzcckll9SqDPPDqTisjxLuCK23jbTuVzRU+jXrvc+vwl81tF41w0bDjJxthmUzbk37hAuVTA9DrRAuSH4Jwgi/FS7JChu1Qutt9TbLFTEKrVdqCq0/ctEhJOjnz16eGYZc6dfgCwRD6/0BFX4jnDUQUBAwQmADimbVo6bQesEZtCOE1tuPJ9y6TObgsq0cSYKkGJ+FpH9mwvoMGTRjWpP1aTNMWOHcHDDcGVqvaqgMqKj0G9dTeQUCFRX6NpWVUH2V0Pz6s2xaoAJaQA9JhhlabzwIqQUqoPnL9UU+DYpLD3VXXAr8rgB8TA+NdmsymJEagAU4DpfWvZM3XGh9eVlFncpQzNB641oIOELrg9djQK0+tF49Umg9YyEjw5vT1YXWB2yh9X5fAIFKFYptpPrahNYzIYGrRri8kOHXZPiEPnq9W5Mhq/rPp6RKEJwDxndblngwtF7ikK20DPqo9cZq0FwS3JK5HoMicfiM9wEXBzeuEab4wAIVYKoxmrottB4AhKzPFy4FwqXAL+l/DJb6NCus/PDhAMrLKoPh8+WHoVTo15lSWWFcn/p7LVABoejXqlB8EMZ+hWqEzxunXChcP24AIiBBC7ih+d3GsXGoPuMcywEocgAB41r2u1RUSnqZFcwFd0A/py5FBnNJEC5ubMfhtkLrUevQ+oqAhnIjDYojrYeiotKvWN9Rny98aL2//LB+TLX4jz1qagBR7cW8JkjUGnRjCACmTJmCMWPGoHfv3sjOzsaiRYuwa9cuTJw4sVbbl5aW6uUM73uENQkhhBBdaWkpUlNT66Vst9uNjIwMFP3w76jLysjIgNvtjkGtEluDbwyNGjUKBw4cwMyZM1FYWIiuXbti5cqVaNu2ba22z8zMxA8//IDOnTtj9+7dtQo/TBQlJSXIysqi8xIGnZvq0bkJj85L9Y6lcyOEQGlpKTIzM+ttH16vFzt27LAeLI6G2+2G1+uNQa0SGxNHpS8wvkpKSpCamori4uIG/0U8mui8VI/OTfXo3IRH56V6dG5IQ3dMRJMRQgghhNQXagwRQgghJKElRGPI4/Fg+vTpFHJfBZ2X6tG5qR6dm/DovFSPzg1p6BLimSFCCCGEkOokRM8QIYQQQkh1qDFECCGEkIRGjSFCCCGEJDRqDBFCCCEkoR33jaEFCxagffv28Hq96NWrFz777LN4V+moy8vLA2PM8crIyLCWCyGQl5eHzMxMJCUlYfDgwdi6dWsca1w/Pv30U1x00UXIzMwEYwxvvfWWY3ltzoPP58Mtt9yCtLQ0NGrUCBdffDF+//33o3gU9eNI52bcuHEh11C/fv0c6xyP52b27Nk488wz0aRJE7Rq1QojR47Etm3bHOsk4nVTm/OSqNcMOTYd142h5cuXIzc3F9OmTcOWLVtw9tlnY9iwYdi1a1e8q3bUdenSBYWFhdbru+++s5bNmTMHc+fOxdNPP41NmzYhIyMDQ4YMscZ1O14cPnwYp59+Op5++umwy2tzHnJzc7FixQq89tprWLduHcrKyjBixAioav2NHn00HOncAMAFF1zguIZWrlzpWH48npu1a9fi5ptvxsaNG5Gfnw9FUZCTk4PDhw9b6yTidVOb8wIk5jVDjlHiONanTx8xceJEx7xOnTqJe++9N041io/p06eL008/PewyTdNERkaGePTRR615lZWVIjU1VTz77LNHqYZHHwCxYsUK631tzsOhQ4eEy+USr732mrXOnj17BOdcrFq16qjVvb5VPTdCCDF27FhxySWXVLtNopybvXv3CgBi7dq1Qgi6bkxVz4sQdM2QY8tx2zPk9/uxefNm5OTkOObn5ORg/fr1capV/Gzfvh2ZmZlo3749rrrqKvz6668AgB07dqCoqMhxnjweDwYNGpRQ56k252Hz5s0IBAKOdTIzM9G1a9eEOFdr1qxBq1atcMopp2DChAnYu3evtSxRzk1xcTEAoHnz5gDoujFVPS8mumbIseK4bQzt378fqqoiPT3dMT89PR1FRUVxqlV89O3bFy+//DI++OADPP/88ygqKkL//v1x4MAB61wk+nmqzXkoKiqC2+1Gs2bNql3neDVs2DAsXboUn3zyCZ544gls2rQJ5557Lnw+H4DEODdCCEyZMgVnnXUWunbtCoCuGyD8eQHomiHHFjneFahvjDHHeyFEyLzj3bBhw6zpbt26ITs7GyeddBJeeukl64FGOk+6SM5DIpyrUaNGWdNdu3ZF79690bZtW/z3v//FZZddVu12x9O5mTx5Mr799lusW7cuZFkiXzfVnRe6Zsix5LjtGUpLS4MkSSF/Yezduzfkr7hE06hRI3Tr1g3bt2+3osoS/TzV5jxkZGTA7/fj4MGD1a6TKFq3bo22bdti+/btAI7/c3PLLbfgnXfewerVq9GmTRtrfqJfN9Wdl3AS7Zohx5bjtjHkdrvRq1cv5OfnO+bn5+ejf//+capVw+Dz+fDjjz+idevWaN++PTIyMhznye/3Y+3atQl1nmpzHnr16gWXy+VYp7CwEN9//31CnSsAOHDgAHbv3o3WrVsDOH7PjRACkydPxptvvolPPvkE7du3dyxP1OvmSOclnES5ZsgxKj7PbR8dr732mnC5XOKFF14QP/zwg8jNzRWNGjUSO3fujHfVjqo77rhDrFmzRvz6669i48aNYsSIEaJJkybWeXj00UdFamqqePPNN8V3330n/va3v4nWrVuLkpKSONc8tkpLS8WWLVvEli1bBAAxd+5csWXLFvHbb78JIWp3HiZOnCjatGkjPvroI/H111+Lc889V5x++ulCUZR4HVZM1HRuSktLxR133CHWr18vduzYIVavXi2ys7PFCSeccNyfm7///e8iNTVVrFmzRhQWFlqv8vJya51EvG6OdF4S+Zohx6bjujEkhBDPPPOMaNu2rXC73aJnz56O0M9EMWrUKNG6dWvhcrlEZmamuOyyy8TWrVut5ZqmienTp4uMjAzh8XjEwIEDxXfffRfHGteP1atXCwAhr7FjxwohanceKioqxOTJk0Xz5s1FUlKSGDFihNi1a1ccjia2ajo35eXlIicnR7Rs2VK4XC5x4oknirFjx4Yc9/F4bsKdEwDixRdftNZJxOvmSOclka8ZcmxiQghx9PqhCCGEEEIaluP2mSFCCCGEkNqgxhAhhBBCEho1hgghhBCS0KgxRAghhJCERo0hQgghhCQ0agwRQgghJKFRY4gQQgghCY0aQ4QQQghJaNQYIoTERF5eHs4444w6bePz+XDLLbcgLS0NjRo1wsUX///27jQkqu+NA/h3qlksx8kRM7EywzVzLIYWbRmi1AL59aI9MzHT3rSZSVHQQrSBRSERJWVFRiBmb5ShBSzUMiwnSanIhamstFzSMMP8/l9Elya1bKHl7/OBwbnnPOe5595583DvPd7/8PTpU4eYpqYmxMbGwmAwwGAwIDY2Fs3NzQ4x69evh9lshlar/e45CCGEFENCiD9mw4YNyM3NxYULF1BYWIi2tjZER0fjw4cPSsyyZctgs9lgtVphtVphs9kQGxvrkIckVq5cicWLF//uQxBC/D/4w68DEeKvY7FYuHbtWqamptLV1ZUeHh7csWMHyY/v8FKr1bxx44YSn5aWRjc3N9bV1X0zd3Z2NseNG0edTkej0chZs2axra1N6T916hQDAwOp1WoZEBDAo0ePOowvKipiaGgotVotzWYzc3NzCYBlZWXK/ADQarVy/Pjx1Ol0nDlzJl++fMn8/HwGBgZSr9dzyZIlfPv2rZK3q6uLBw4coI+PD3U6HU0mE7Ozs5X+T3mvXr1Ks9lMJycnhoWF8cGDByTJzMzMr76/qyfNzc1Uq9W8cOGC0vbs2TMOGDCAVquVJFlZWUkAvHXrlhJz8+ZNAlD2/bkdO3YwNDT06z+CEEJ8QYohIb5gsVjo4uLCnTt38tGjRzxz5gxVKhUvX75MkkxNTaW3tzebm5tps9mo1Wp58eLFb+atq6vjoEGDeOjQIdbU1LC8vJxHjx5la2srSfLEiRP09PRkTk4Oq6urmZOTQ6PRyNOnT5Mk37x5Q6PRyOXLl7OiooL5+fn09/fvsRiaMmUKCwsLeffuXfr6+tJisTAyMpJ3797ljRs36Obmxv379ytz27p1KwMDA2m1WllVVcXMzExqtVoWFBQ45J08eTILCgpYUVHB6dOnMzw8nOTHF3OmpKQwODi4xze79+TatWsEwMbGRod2k8nE7du3kyRPnjxJg8HQbazBYOCpU6e6tUsxJIT4EVIMCfEFi8XCadOmObRNnDiRmzdvJkl2dHRwwoQJXLRoEYODg7lq1ao+5b1z5w4BsLa2tsf+kSNH8vz58w5tu3fvZlhYGEny2LFjdHNzY3t7u9KfkZHRYzF09epVJWbfvn0EwKqqKqVt9erVjIqKIkm2tbVRp9OxuLjYYd8JCQlcunRpr3nz8vIIQJnP9xYiWVlZ1Gg03dojIiKYlJREktyzZw/9/Py6xfj5+XHv3r3d2qUYEkL8iEG/+a6cEP8Ek8nksO3p6Yn6+noAgEajwblz52AymeDt7Y3Dhw/3KWdoaChmzZqFkJAQREVFITIyEgsWLICrqysaGhrw5MkTJCQkIDExURnT2dkJg8EAAHj48CFMJhN0Op3SP2nSpG/O38PDA4MHD8aYMWMc2m7fvg0AqKysxLt37xAREeGQ4/3795gwYUKveT09PQEA9fX1GDVqVJ/OQV+QhEqlUrY//95bjBBC/AwphoTogVqtdthWqVTo6upStouLiwEAjY2NaGxsxJAhQ76Zc+DAgbhy5QqKi4tx+fJlpKenY9u2bSgpKcHgwYMBABkZGZg8eXK3cUDPBQDJb85fpVJ99Xg+/c3Ly4OXl5dDnFar/Wrez8d/r+HDh+P9+/doamqCq6ur0l5fX4/w8HAl5uXLl93GNjQ0wMPD44f2K4QQX5LVZEJ8p6qqKiQnJyMjIwNTpkzBihUr+lwQqFQqTJ06Fbt27UJZWRk0Gg1yc3Ph4eEBLy8vVFdXw9fX1+Hj4+MDAAgMDER5eTk6OjqUfKWlpT99PGPHjoVWq4Xdbu+275EjR/Y5j0ajcVgF9i1msxlqtRpXrlxR2p4/f4779+8rxVBYWBhaWlqUq1gAUFJSgpaWFiVGCCF+llwZEuI7fPjwAbGxsYiMjER8fDzmzp2LkJAQHDx4EKmpqV8dW1JSgmvXriEyMhLDhg1DSUkJGhoaEBQUBODj/+lZt24dXFxcMHfuXHR0dKC0tBRNTU3YuHEjli1bhm3btiEpKQlbtmyB3W5HWloagJ5vJfWVXq/Hpk2bkJycjK6uLkybNg1v3rxBcXExnJ2dERcX16c8o0ePRk1NDWw2G0aMGAG9Xt/tytLnDAYDEhISkJKSAjc3NxiNRmzatAkhISGYPXs2ACAoKAhz5sxBYmIijh8/DgBISkpCdHQ0AgIClFyPHz9GW1sbXrx4gfb2dthsNgAfCz2NRvODZ0YI0W/82UeWhPj7WCwWrl+/3qFt3rx5jIuL465du+jp6clXr14pfZcuXaJGo1EeYu5NZWUlo6Ki6O7uTq1WS39/f6anpzvEZGVlcfz48dRoNHR1deWMGTMcVqoVFRXRZDJRo9HQbDbz/PnzDsvMPz3o3NTUpIzJzMzstiLryweNu7q6eOTIEQYEBFCtVtPd3Z1RUVG8fv16r3nLysoIgDU1NSTJd+/ecf78+Rw6dGifltaTZHt7O9esWUOj0UgnJydGR0fTbrc7xLx+/ZoxMTHU6/XU6/WMiYlxmAf58TfDF0v7P5+bEEJ8jYrs5aEDIcRfLysrC/Hx8WhpaYGTk9Ofno4QQvyT5DaZEP+Qs2fPYsyYMfDy8sK9e/ewefNmLFq0SAohIYT4CfIAtRC/iN1uh7Ozc68fu93+0/t48eIFli9fjqCgICQnJ2PhwoU4ceLEL5j9r5eVldXruQgODv7T0xNCCIXcJhPiF+ns7ERtbW2v/aNHj8agQf3nYmxra2uPy+KBj0v0vb29f/OMhBCiZ1IMCSGEEKJfk9tkQgghhOjXpBgSQgghRL8mxZAQQggh+jUphoQQQgjRr0kxJIQQQoh+TYohIYQQQvRrUgwJIYQQol+TYkgIIYQQ/dr/APwYr+nxLTlbAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "expt.segment_001.u_segment_001.isel(time = 5).plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 6: Create tidal forcing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "nbval-skip" + ] + }, + "outputs": [], + "source": [ + "# If you have downloaded the TPXO tidal data and wish to include tidal forcing at the boundary, run this cell\n", + "expt.setup_boundary_tides(\n", + " tide_h_path,\n", + " tide_u_path,\n", + " tidal_constituents=[\"M2\"],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Step 7: Run the FRE tools\n", "\n", "This is just a wrapper for the FRE tools needed to make the mosaics and masks for the experiment. The only thing you need to tell it is the processor layout. In this case we're saying that we want a 10 by 10 grid of 100 processors. " ] @@ -324,14 +434,14 @@ "metadata": {}, "outputs": [], "source": [ - "expt.FRE_tools(layout=(10, 10)) ## Here the tuple defines the processor layout" + "expt.run_FRE_tools(layout=(10, 10)) ## Here the tuple defines the processor layout" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 7: Set up ERA5 forcing:\n", + "## Step 8: Set up ERA5 forcing:\n", "\n", "Here we assume the ERA5 dataset is stored somewhere on the system we are working on. \n", "\n", @@ -358,7 +468,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "tags": [ "nbval-skip" @@ -373,7 +483,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 8: Modify the default input directory to make a (hopefully) runnable configuration out of the box\n", + "## Step 9: Modify the default input directory to make a (hopefully) runnable configuration out of the box\n", "\n", "This step copies the default directory and modifies the `MOM_layout` files to match your experiment by inserting the right number of x, y points and CPU layout.\n", "\n", @@ -386,14 +496,15 @@ "metadata": {}, "outputs": [], "source": [ - "expt.setup_run_directory(surface_forcing = \"era5\")" + "expt.setup_run_directory(surface_forcing = \"era5\", with_tides = False)\n", + "# To turn on tides (assuming you ran step 6), set `with_tides = True`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 9: Run and Troubleshoot!\n", + "## Step 10: Run and Troubleshoot!\n", "\n", "To run the regional configuration first navigate to your run directory in terminal and use your favourite tool to run the experiment on your system. \n", "\n", @@ -403,20 +514,13 @@ "\n", "Another thing that can go wrong is little bays that create non-advective cells at your boundaries. Keep an eye out for tiny bays where one side is taken up by a boundary segment. You can either fill them in manually, or move your boundary slightly to avoid them" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python [conda env:analysis3-24.04] *", "language": "python", - "name": "python3" + "name": "conda-env-analysis3-24.04-py" }, "language_info": { "codemirror_mode": { @@ -428,7 +532,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.10.14" } }, "nbformat": 4, diff --git a/docs/angle_calculation.md b/docs/angle_calculation.md new file mode 100644 index 00000000..63cf893a --- /dev/null +++ b/docs/angle_calculation.md @@ -0,0 +1,35 @@ +# Rotation and angle calculation in regional-mom6 using MOM6 Angle Calculation + +Here we explain the implementation of MOM6 angle calculation in regional-mom6, which is the process by which regional-mom6 calculates the angle of curved horizontal grids (``hgrids``). + +**Issue:** On a curved hgrid, we have to rotate the boundary conditions according to the angle the grid is rotated from lat-lon coordinates (true north vs model north). Although horizontal grids supplied by users will contain an `angle_dx` field, MOM6 ignores this field entirely and calculates its own grid angles internally. + +**Solution:** To be consistent with MOM6's treatement of grid angles, when we rotate our boundary conditions, we implemented MOM6 angle calculation in a file called "rotation.py", and included this in the the boundary regridding functions by default. + + +## Boundary rotation algorithm +Steps 1-5 replicate the angle calculation as done by MOM6. Step 6 is an additional step required to apply this algorithm to the boundary points. + +1. Figure out the longitudinal extent of our domain, or periodic range of longitudes. For global cases it is len_lon = 360, for our regional cases it is given by the hgrid. +2. At each ``t``-point on the `hgrid`, we find the four adjacent ``q``-points. We adjust each of these longitudes to be in the range of len_lon around the point itself. (module_around_point) +3. We then find the lon_scale, which is the "trigonometric scaling factor converting changes in longitude to equivalent distances in latitudes". Whatever that actually means is we add the latitude of all four of these points from part 3 and basically average it and convert to radians. We then take the cosine of it. As I understand it, it's a conversion of longitude to equivalent latitude distance. +4. Then we calculate the angle. This is a simple arctan2 so y/x. + 1. The "y" component is the addition of the difference between the diagonals in longitude (adjusted by modulo_around_point in step 3) multiplied by the lon_scale, which is our conversion to latitude. + 2. The "x" component is the same addition of differences in latitude. + 3. Thus, given the same units, we can call arctan to get the angle in degrees + +5. **Additional step to apply to boundaries** +Since the boundaries for a regional MOM6 domain are on the `q` points and not on the `t` points, to calculate the angle at the boundary points we need to expand the grid. This is implemented in the `create_expanded_hgrid` method. + +## Convert this method to boundary angles - 2 Options +1. **EXPAND_GRID**: Compute grid angle replicating MOM6 calculations. Calculate another boundary row/column points around the hgrid using simple difference techniques. Use the new points to calculate the angle at the boundaries. This works because we can now access the four points needed to calculate the angle, where previously at boundaries we would be missing at least two. +2. **GIVEN_ANGLE**: Don't calculate the angle and use the user-provided field in the hgrid called `angle_dx`. + + +## Force the usage of the provided angle_dx values + +To use the provided angles instead of the default algorithm, when calling the regridding functions `regrid_velocity_tracers` and `regrid_tides`, set the optional argument `rotational method = given_angle` + +## Code structure + +Most calculation code is implemented in the `rotation.py`, which is called by the regridding functions if rotation is required. diff --git a/docs/api.rst b/docs/api.rst index 3db049aa..51d45032 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,22 +1,45 @@ -=============== - API reference -=============== +API reference +============= +Submodules +---------- -+++++++++++++++++++ - ``regional_mom6`` -+++++++++++++++++++ +regional\_mom6.regional\_mom6 module +------------------------------------ .. automodule:: regional_mom6.regional_mom6 :members: :undoc-members: - :private-members: + :show-inheritance: +regional\_mom6.regridding module +-------------------------------- -+++++++++++ - ``utils`` -+++++++++++ +.. automodule:: regional_mom6.regridding + :members: + :undoc-members: + :show-inheritance: + +regional\_mom6.rotation module +------------------------------ + +.. automodule:: regional_mom6.rotation + :members: + :undoc-members: + :show-inheritance: + +regional\_mom6.utils module +--------------------------- .. automodule:: regional_mom6.utils :members: :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: regional_mom6 + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/conf.py b/docs/conf.py index 6117ddf0..a9d956f1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,3 +27,6 @@ "repository_url": "https://github.com/COSIMA/regional-mom6", "use_repository_button": True, } + +# Disable demo notebook execution by nbsphinx (and therefore readthedocs notebook execution) +nbsphinx_execute = "never" diff --git a/docs/contributing.md b/docs/contributing/contributing.md similarity index 100% rename from docs/contributing.md rename to docs/contributing/contributing.md diff --git a/docs/contributing/docker_image_dev.md b/docs/contributing/docker_image_dev.md new file mode 100644 index 00000000..43340b24 --- /dev/null +++ b/docs/contributing/docker_image_dev.md @@ -0,0 +1,48 @@ +# Docker Image & Github Testing + +regional-mom6 uses a docker image in Github actions for holding large data. Here, we explain how contributors can use the docker image. + +First things first, install Docker by following [instructions at the docker docs](https://docs.docker.com/get-started/). To ensure everything is working correctly, start the docker engine, and check that the following simple command doesn't output any errors. + +```bash +docker info +``` + +The docker image lives at: +[https://github.com/COSIMA/regional-mom6/pkgs/container/regional-test-env](https://github.com/COSIMA/regional-mom6/pkgs/container/regional-test-env) + +For local development of the image, e.g., to add data to it that will be used in the packages tests, first we need to pull it. + +```bash +docker pull ghcr.io/cosima/regional-test-env:updated +``` + +Then to test the image, we go into the directory of our locally copy of regional-mom6, and run: + +```bash +docker run -it --rm \ -v $(pwd):/workspace \ -w /workspace \ ghcr.io/cosima/regional-test-env:updated \ /bin/bash +``` + +The above command mounts the local copy of the package in the `/workspace` directory of the image. + +The `-it` flag is for shell access; the workspace stuff is to get our local code in the container. +We need to download conda, python, pip, and all that business to properly run the tests. + +To add data, we create a directory and add both the data we want and a file called `Dockerfile`. +Within `Dockerfile`, we'll get the original image, then copy the data we need to the data directory. + +```bash +# Use the base image +FROM ghcr.io/cosima/regional-test-env: + +# Copy your local file into the /data directory in the container +COPY /data/ +``` + +Then, we need to build the image, tag it, and push it up. + +```bash +docker build -t my-custom-image . # IN THE DIRECTORY WITH THE DOCKERFILE +docker tag my-custom-image ghcr.io/cosima/regional-test-env: +docker push ghcr.io/cosima/regional-test-env: +``` diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst new file mode 100644 index 00000000..9ebd2757 --- /dev/null +++ b/docs/contributing/index.rst @@ -0,0 +1,10 @@ +Contributing +============ + +Instructions for contributors. + +.. toctree:: + :maxdepth: 1 + + contributing + docker_image_dev diff --git a/docs/demos.rst b/docs/demos.rst index 4a745a8a..170cf4bf 100644 --- a/docs/demos.rst +++ b/docs/demos.rst @@ -6,5 +6,6 @@ Demos :name: demo-gallery demo_notebooks/reanalysis-forced.ipynb + demo_notebooks/BYO-domain.ipynb Another demonstration that uses model output from the Consortium of Ocean Sea Ice Modeling in Australia (`COSIMA `_) for boundary forcing is the `recipe found in the COSIMA Cookbook `_. diff --git a/docs/index.rst b/docs/index.rst index 531ad99c..feb412e6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,7 @@ In brief... Users just need to provide some information about where, when, and how big their domain is and also where raw input forcing files are. The package sorts out all the boring details -and creates a set of MOM6-friendly input files along with setup directories ready to go! +and creates a set of MOM6-friendly input files along with setup directories ready to go! The idea behind this package is that it should let the user sidestep some of the tricky issues with getting the model to run in the first place. This removes some of the steep @@ -20,10 +20,12 @@ stability issues or fiddling with bathymetry to deal with very narrow fjords or Features -------- -- Automatic grid generation at chosen vertical and horizontal grid spacing. +- Automatic grid generation at chosen vertical and horizontal grid spacing *or* reads in existing custom grids provided by the user. +- Handles rotation of the input files when the grid is rotated or curved relative to constant latitude & longitude lines. - Automatic removal of non-advective cells from the bathymetry that cause the model to crash. -- Handle slicing across 'seams' in of the forcing input datasets (e.g., when the regional +- Handles slicing across 'seams' in of the forcing input datasets (e.g., when the regional configuration includes longitude 180 and the forcing longitude is defined in [-180, 180]). +- Handles TPXO tidal forcing at the boundaries. - Handles metadata encoding. - Creates directory structure with the configuration files as expected by MOM6. - Handles interpolation and interpretation of input data. No pre-processing of forcing datasets @@ -31,21 +33,11 @@ Features related to the machine's available memory.) -Limitations ------------- - -- Only generates regional horizontal grids with uniform spacing in longitude and latitude. - However, users can provide their own non-uniform grid, or ideally `open a pull request`_ - with a method that generates other types of horizontal grids. -- Only supports boundary segments that are parallel to either lines of constant longitude or lines of - constant latitude. - - What you need to get started ---------------------------- 1. a cool idea for a new regional MOM6 domain, -2. a working MOM6 executable on a machine of your choice, +2. a working MOM6 executable on a machine of your choice, 3. a bathymetry file that at least covers your domain, 4. 3D ocean forcing files *of any resolution* on your choice of A, B, or C Arakawa grid, 5. surface forcing files (e.g., from ERA or JRA reanalysis), and @@ -56,7 +48,7 @@ Browse through the `demos `_. Citing ------ -If you use regional-mom6 in research, teaching, or other activities, we would be grateful +If you use regional-mom6 in research, teaching, or other activities, we would be grateful if you could mention regional-mom6 and cite our paper in JOSS: Barnes et al., (2024). regional-mom6: A Python package for automatic generation of regional configurations for the Modular Ocean Model 6. *Journal of Open Source Software*, **9(100)**, 6857, doi:`10.21105/joss.06857 `_. @@ -85,15 +77,17 @@ The bibtex entry for the paper is: .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :caption: Contents: installation demos mom6-file-structure-primer + regional-mom6-workflow + angle_calculation api - contributing - + contributing/index + Indices and tables ================== diff --git a/docs/mom6-file-structure-primer.md b/docs/mom6-file-structure-primer.md index 708fdebd..d58fc1da 100644 --- a/docs/mom6-file-structure-primer.md +++ b/docs/mom6-file-structure-primer.md @@ -13,7 +13,7 @@ These files are: * `input.nml`: High-level information that is passed directly to each component of your MOM6 setup. The paths of the `SIS` and `MOM` input directories and outputs are included. - The `coupler` section turns on or off different model components, and specifies how long to run the experiment for. + The `coupler` section turns on or off different model components, and specifies how long to run the experiment for. * `diag_table`: The diagnostics to output at model runtime. @@ -36,7 +36,7 @@ These files are: * `data_table`: The data table is read by the coupler to provide the different model components with inputs. - Instructions for how to format the `data_table` are included in the [MOM6 documentation](https://mom6.readthedocs.io/en/dev-gfdl/forcing.html). + Instructions for how to format the `data_table` are included in the [MOM6 documentation](https://mom6.readthedocs.io/en/dev-gfdl/forcing.html). * `field_table`: The field table defines tracer fields. @@ -48,7 +48,7 @@ These files are: There's too much in these files to explain here. The aforementioned vertical diagnostic coordinates are specified here, as are all of the different parameterisation schemes and hyperparameters used by the model. Some of these parameters are important, e.g., the timesteps, which will likely need to be fiddled with to get your model running quickly but stably. - However, it can be more helpful to specify these in the `MOM_override` file instead. + However, it can be more helpful to specify these in the `MOM_override` file instead. Another important part section for regional modelling is the specification of open boundary segments. A separate line for each boundary in our domain is included and also any additional tracers need to be specified here. @@ -60,14 +60,14 @@ These files are: This file provides information on the model grid, processor layout and I/O layout. * `config` file: - This file is machine dependent and environment dependent. For instance, if you're using Australia's National Computational Infrastructure (NCI), then you're likely using the [`payu`](https://payu.readthedocs.io/en/latest/) framework, and you'll have a `config.yaml` file. Regardless of what it looks like, this file should contain information that points to the executable, your input directory (aka the `mom_input_dir` you specified), the computational resources you'd like to request and other various settings. + This file is machine dependent and environment dependent. For instance, if you're using Australia's National Computational Infrastructure (NCI), then you're likely using the [`payu`](https://payu.readthedocs.io/en/latest/) framework, and you'll have a `config.yaml` file. Regardless of what it looks like, this file should contain information that points to the executable, your input directory (aka the `mom_input_dir` you specified), the computational resources you'd like to request and other various settings. The package does come with a premade `config.yaml` file for payu users which is automatically copied and modified when the appropriate flag is passed to the `setup_rundir` method. If you find this package useful and you use a different machine, I'd encourage you to provide an example config file for your institution! ## `input` directory The `mom_input_dir` directory stores mostly netCDF files that are read by MOM6 at runtime. -These files can be big, so it is usually helpful to store them somewhere without any disk limitations. +These files can be big, so it is usually helpful to store them somewhere without any disk limitations. * `hgrid.nc` The horizontal grid that the model runs on. Known as the 'supergrid', it contains twice as many points in each @@ -75,7 +75,7 @@ These files can be big, so it is usually helpful to store them somewhere without points on the Arakawa C grid are included: both velocity and tracer points live in the 'supergrid'. For a regional configuration, we need to use the 'symmetric memory' configuration of the MOM6 executable. This implies that the horizontal grid's boundary must be entirely composed of cell edge points (i.e. those used by velocities). Therefore, - for example, a model configuration that is 20 degrees wide in longitude and has 0.5 degrees longitudinal resolution, would have 40 cells in the `x` dimension and thus a supergrid with `nx = 41`. + for example, a model configuration that is 20 degrees wide in longitude and has 0.5 degrees longitudinal resolution, would have 40 cells in the `x` dimension and thus a supergrid with `nx = 41`. The `nx` and `ny` points are where data is stored, whereas `nxp` and `nyp` here define the spaces between points used to compute area. The `x` and `y` variables in `hgrid` refer to the longitude and latitude. Importantly, `x` @@ -88,7 +88,7 @@ These files can be big, so it is usually helpful to store them somewhere without coordinates may be provided after appropriate adjustments in the `MOM_input` file. Users who would like to customise the vertical coordinate can initialise an `experiment` object to begin with, then modify the `vcoord.nc` file and save. Users can provide additional vertical coordinates (under different names) for diagnostic purposes. - These additional vertical coordinates allow diagnostics to be remapped and output during the model run. + These additional vertical coordinates allow diagnostics to be remapped and output during the model run. * `bathymetry.nc` Fairly self-explanatory, but can be the source of some difficulty. The package automatically attempts to remove "non-advective cells". These are small enclosed lakes at the boundary that can cause numerical problems whereby water might flow in but have no way to flow out. Likewise, there can be issues with very shallow (only 1 or 2 layers) or very narrow (1 cell wide) channels. If your model runs for a while but then gets extreme sea surface height values, it could be caused by an unlucky combination of boundary and bathymetry. @@ -99,10 +99,13 @@ These files can be big, so it is usually helpful to store them somewhere without executing the `setup_bathymetry` method. * `forcing/init_*.nc` - The initial conditions bunched into velocities, tracers, and the free surface height. + The initial conditions bunched into velocities, tracers, and the free surface height. * `forcing/forcing_segment*` The boundary forcing segments, numbered the same way as in `MOM_input`. The dimensions and coordinates are fairly confusing, and getting them wrong can likewise cause some cryptic error messages! These boundaries do not have to follow lines of constant longitude and latitude, but it is much easier to set things up if they do. For an example - of a curved boundary, see this [Northwest Atlantic experiment](https://github.com/jsimkins2/nwa25/tree/main). + of a curved boundary, see the [Northwest Atlantic experiment](https://github.com/jsimkins2/nwa25/). + +* `forcing/{tz/tu}_segment**` + The boundary tidal segments, numbered the same way as in `MOM_input`. See the previous bullet point for more information on these type of files. diff --git a/docs/regional-mom6-workflow.md b/docs/regional-mom6-workflow.md new file mode 100644 index 00000000..746369df --- /dev/null +++ b/docs/regional-mom6-workflow.md @@ -0,0 +1,28 @@ +# regional-mom6 workflow + +regional-mom6 sets up all the data and files for running a basic regional configuration case of MOM6. +This includes: + +1. Run files like ``MOM_override``, ``MOM_input``, and ``diag_table``. +2. Boundary condition files like velocity, tracers, tides. +3. Basic input files like horizontal grid (``hgrid``) and the bathymetry. +4. Initial condition files. + +regional-mom6 provides the user methods for grabbing and organising the files. + +regional-mom6 organizes all files into two directories: an ``input`` directory and a ``run`` directory. +The input directory includes all of the data we need for our regional case. The run directory includes all of the parameters and outputs (``diags``) we want for our model. Please see the structure primer document for more information. The rest of the directories include the data like the initial and the boundary conditions. + +Therefore, to start for the user to use regional-mom6, they should have two (empty or not) directories for the input and run files, as well as directories for their input data. + +The user may also need to provide a path to ``FRE_tools``. (This depends on the HPC machine used, e.g., on Australia's Gadi this is required, on NCAR-Derecho/Casper this is not required.) + +To create all these files, regional-mom6 uses a class called ``Experiment`` to hold all of the parameters and functions. Users can follow a few quick steps to setup their cases: +1. Initalise the experiment object with all the directories and parameters wanted. The initalisation can also create the horizontal grid and vertical coordinate or read two files called ``hgrid.nc`` and ``vcoord.nc`` from the ``input`` directory. +2. Call different ``setup_this_and_that`` functions to setup all the data needed for the case (bathymetry, initial condition, velocity, tracers, tides). +3. Finally, call ``setup_run_directory`` to setup the run files like ``MOM_override`` for their cases. +4. Based on how MOM6 is configured on the machine used, there may be follow-up steps unique to each situation. regional-mom6 provides all of what the user needs to run MOM6. + +There are a few convenience functions to help support the process. +1. Very light read and write config file functions to easily save experiments +2. A ``change_MOM_parameter`` method to adjust ``MOM_parameter`` values from within Python. diff --git a/pyproject.toml b/pyproject.toml index 146ad485..767d3178 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,9 +14,10 @@ dependencies = [ "netCDF4", "numpy >= 1.17.0, < 2.0.0", "scipy >= 1.2.0", - "xarray <= 2024.7.0", + "xarray", "xesmf >= 0.8.4", "f90nml >= 1.4.1", + "copernicusmarine >= 2.0.0,<2.1.0" ] [build-system] diff --git a/regional_mom6/regional_mom6.py b/regional_mom6/regional_mom6.py index 55d6120b..9aaf755a 100644 --- a/regional_mom6/regional_mom6.py +++ b/regional_mom6/regional_mom6.py @@ -1,12 +1,10 @@ import numpy as np -from pathlib import Path import dask.array as da import xarray as xr import xesmf as xe import subprocess from scipy.ndimage import binary_fill_holes import netCDF4 -from dask.diagnostics import ProgressBar import f90nml import datetime as dt import warnings @@ -14,7 +12,21 @@ import os import importlib.resources import datetime -from .utils import quadrilateral_areas +import pandas as pd +from pathlib import Path +import glob +from collections import defaultdict +import json +import copy +from regional_mom6 import regridding as rgd +from regional_mom6 import rotation as rot +from regional_mom6.utils import ( + quadrilateral_areas, + ap2ep, + ep2ap, + is_rectilinear_hgrid, + rotate, +) warnings.filterwarnings("ignore") @@ -22,12 +34,141 @@ __all__ = [ "longitude_slicer", "hyperbolictan_thickness_profile", - "rectangular_hgrid", + "generate_rectangular_hgrid", "experiment", "segment", + "create_experiment_from_config", + "get_glorys_data", ] +## Mapping Functions + + +def convert_to_tpxo_tidal_constituents(tidal_constituents): + """ + Convert tidal constituents from strings to integers using a dictionary. + + Parameters: + tidal_constituents (list of str): List of tidal constituent names as strings. + + Returns: + list of int: List of tidal constituent indices as integers. + """ + tpxo_tidal_constituent_map = { + "M2": 0, + "S2": 1, + "N2": 2, + "K2": 3, + "K1": 4, + "O1": 5, + "P1": 6, + "Q1": 7, + "MM": 8, + "MF": 9, + # Only supported tidal bc's + } + + try: + constituent_indices = [ + tpxo_tidal_constituent_map[tc] for tc in tidal_constituents + ] + except KeyError as e: + raise ValueError(f"Invalid tidal constituent: {e.args[0]}") + + return constituent_indices + + +## Load Experiment Function + + +def create_experiment_from_config( + config_file_path, + mom_input_folder=None, + mom_run_folder=None, + create_hgrid_and_vgrid=True, +): + """ + Load an experiment variables from a configuration file and generate the hgrid/vgrid. + Computer-specific functionality eliminates the ability to pass file paths. + Basically another way to initialize. Sets a default folder of "mom_input/from_config" and "mom_run/from_config" unless specified. + + Arguments: + config_file_path (str): Path to the config file. + mom_input_folder (str): Path to the MOM6 input folder. Default is "mom_input/from_config". + mom_run_folder (str): Path to the MOM6 run folder. Default is "mom_run/from_config". + create_hgrid_and_vgrid (bool): Whether to create the hgrid and the vgrid. Default is True. + + Returns: + experiment: An experiment object with the fields from the config loaded in. + """ + print("Reading from config file....") + with open(config_file_path, "r") as f: + config_dict = json.load(f) + + print("Creating Empty Experiment Object....") + expt = experiment.create_empty() + + print("Setting Default Variables.....") + expt.expt_name = config_dict["expt_name"] + + if ( + config_dict["longitude_extent"] != None + and config_dict["latitude_extent"] != None + ): + expt.longitude_extent = tuple(config_dict["longitude_extent"]) + expt.latitude_extent = tuple(config_dict["latitude_extent"]) + else: + expt.longitude_extent = None + expt.latitude_extent = None + try: + expt.date_range = config_dict["date_range"] + expt.date_range[0] = dt.datetime.strptime( + expt.date_range[0], "%Y-%m-%d %H:%M:%S" + ) + expt.date_range[1] = dt.datetime.strptime( + expt.date_range[1], "%Y-%m-%d %H:%M:%S" + ) + except IndexError: + expt.date_range = None + + if mom_input_folder is None: + mom_input_folder = Path("mom_run" / "from_config") + if mom_run_folder is None: + mom_run_folder = Path("mom_input" / "from_config") + expt.mom_run_dir = Path(mom_run_folder) + expt.mom_input_dir = Path(mom_input_folder) + expt.mom_run_dir.mkdir(parents=True, exist_ok=True) + expt.mom_input_dir.mkdir(parents=True, exist_ok=True) + + config_params = [ + "resolution", + "number_vertical_layers", + "layer_thickness_ratio", + "depth", + "hgrid_type", + "repeat_year_forcing", + "minimum_depth", + "tidal_constituents", + "boundaries", + ] + for param in config_params: + setattr(expt, param, config_dict[param]) + + expt.ocean_mask = None + expt.layout = None + + if create_hgrid_and_vgrid: + print("Creating hgrid and vgrid....") + expt.hgrid = expt._make_hgrid() + expt.vgrid = expt._make_vgrid() + else: + print("Skipping hgrid and vgrid creation....") + + print("Done!") + return expt + + ## Auxiliary functions @@ -58,12 +199,13 @@ def longitude_slicer(data, longitude_extent, longitude_coords): - Finally re-add the correct multiple of 360 so the whole domain matches the target. - Args: + Arguments: data (xarray.Dataset): The global data you want to slice in longitude. longitude_extent (Tuple[float, float]): The target longitudes (in degrees) we want to slice to. Must be in increasing order. longitude_coords (Union[str, list[str]): The name or list of names of the longitude coordinates(s) in ``data``. + Returns: xarray.Dataset: The sliced ``data``. """ @@ -77,11 +219,11 @@ def longitude_slicer(data, longitude_extent, longitude_coords): ## Find a corresponding value for the intended domain midpoint in our data. ## It's assumed that data has equally-spaced longitude values. - λ = data[lon].data - dλ = λ[1] - λ[0] + lons = data[lon].data + dlons = lons[1] - lons[0] assert np.allclose( - np.diff(λ), dλ * np.ones(np.size(λ) - 1) + np.diff(lons), dlons * np.ones(np.size(lons) - 1) ), "provided longitude coordinate must be uniformly spaced" for i in range(-1, 2, 1): @@ -145,9 +287,6 @@ def longitude_slicer(data, longitude_extent, longitude_coords): return data -from pathlib import Path - - def get_glorys_data( longitude_extent, latitude_extent, @@ -159,37 +298,39 @@ def get_glorys_data( """ Generates a bash script to download all of the required ocean forcing data. - Args: + Arguments: longitude_extent (tuple of floats): Westward and Eastward extents of the segment latitude_extent (tuple of floats): Southward and Northward extents of the segment - timerange (tule of datetime strings): Start and end of the segment in format %Y-%m-%d %H:%M:%S - segment_range (str): name of the segment (minus .nc extension, eg east_unprocessed) - download_path (str): Location of where this script is saved + timerange (tuple of datetime strings): Start and end of the segment, each in format %Y-%m-%d %H:%M:%S + segment_range (str): name of the segment (without the ``.nc`` extension, e.g., ``east_unprocessed``) + download_path (str): Location of where the script is saved modify_existing (bool): Whether to add to an existing script or start a new one - buffer (float): number of + Returns: + file path """ - buffer = 0.24 # Pads downloads to ensure that interpolation onto desired domain doesn't fail. Default of 0.24 is twice Glorys cell width (12th degree) + buffer = 0.24 # Pads downloads to ensure that interpolation onto desired domain doesn't fail. + # Default is 0.24, just under three times the Glorys cell width (3 x 1/12 = 0.25). path = Path(download_path) if modify_existing: - file = open(path / "get_glorysdata.sh", "r") + file = open(Path(path / "get_glorys_data.sh"), "r") lines = file.readlines() file.close() else: - lines = ["#!/bin/bash\ncopernicusmarine login"] + lines = ["#!/bin/bash\n"] - file = open(path / "get_glorysdata.sh", "w") + file = open(Path(path / "get_glorys_data.sh"), "w") lines.append( f""" -copernicusmarine subset --dataset-id cmems_mod_glo_phy_my_0.083deg_P1D-m --variable so --variable thetao --variable uo --variable vo --variable zos --start-datetime {str(timerange[0]).replace(" ","T")} --end-datetime {str(timerange[1]).replace(" ","T")} --minimum-longitude {longitude_extent[0] - buffer} --maximum-longitude {longitude_extent[1] + buffer} --minimum-latitude {latitude_extent[0] - buffer} --maximum-latitude {latitude_extent[1] + buffer} --minimum-depth 0 --maximum-depth 6000 -o {str(path)} -f {segment_name}.nc --force-download\n +copernicusmarine subset --dataset-id cmems_mod_glo_phy_my_0.083deg_P1D-m --variable so --variable thetao --variable uo --variable vo --variable zos --start-datetime {str(timerange[0]).replace(" ","T")} --end-datetime {str(timerange[1]).replace(" ","T")} --minimum-longitude {longitude_extent[0] - buffer} --maximum-longitude {longitude_extent[1] + buffer} --minimum-latitude {latitude_extent[0] - buffer} --maximum-latitude {latitude_extent[1] + buffer} --minimum-depth 0 --maximum-depth 6000 -o {str(path)} -f {segment_name}.nc\n """ ) file.writelines(lines) file.close() - return + return Path(path / "get_glorys_data.sh") def hyperbolictan_thickness_profile(nlayers, ratio, total_depth): @@ -216,7 +357,7 @@ def hyperbolictan_thickness_profile(nlayers, ratio, total_depth): bottom-most layer to the top-most layer only departs from the prescribed ``ratio`` by ±20%. - Args: + Arguments: nlayers (int): Number of vertical layers. ratio (float): The desired value of the ratio of bottom-most to the top-most layer thickness. Note that the final value of @@ -308,10 +449,10 @@ def hyperbolictan_thickness_profile(nlayers, ratio, total_depth): return layer_thicknesses -def rectangular_hgrid(λ, φ): +def generate_rectangular_hgrid(lons, lats): """ Construct a horizontal grid with all the metadata required by MOM6, based on - arrays of longitudes (``λ``) and latitudes (``φ``) on the supergrid. + arrays of longitudes (``lons``) and latitudes (``lats``) on the supergrid. Here, 'supergrid' refers to both cell edges and centres, meaning that there are twice as many points along each axis than for any individual field. @@ -321,40 +462,46 @@ def rectangular_hgrid(λ, φ): It is also assumed here that the longitude array values are uniformly spaced. - Ensure both ``λ`` and ``φ`` are monotonically increasing. + Ensure both ``lons`` and ``lats`` are monotonically increasing. - Args: - λ (numpy.array): All longitude points on the supergrid. Must be uniformly spaced. - φ (numpy.array): All latitude points on the supergrid. + Arguments: + lons (numpy.array): All longitude points on the supergrid. Must be uniformly spaced. + lats (numpy.array): All latitude points on the supergrid. Returns: xarray.Dataset: An FMS-compatible horizontal grid (``hgrid``) that includes all required attributes. """ - assert np.all(np.diff(λ) > 0), "longitudes array λ must be monotonically increasing" - assert np.all(np.diff(φ) > 0), "latitudes array φ must be monotonically increasing" + assert np.all( + np.diff(lons) > 0 + ), "longitudes array lons must be monotonically increasing" + assert np.all( + np.diff(lats) > 0 + ), "latitudes array lats must be monotonically increasing" R = 6371e3 # mean radius of the Earth; https://en.wikipedia.org/wiki/Earth_radius # compute longitude spacing and ensure that longitudes are uniformly spaced - dλ = λ[1] - λ[0] + dlons = lons[1] - lons[0] assert np.allclose( - np.diff(λ), dλ * np.ones(np.size(λ) - 1) + np.diff(lons), dlons * np.ones(np.size(lons) - 1) ), "provided array of longitudes must be uniformly spaced" - # dx = R * cos(np.deg2rad(φ)) * np.deg2rad(dλ) / 2 + # dx = R * cos(np.deg2rad(lats)) * np.deg2rad(dlons) / 2 # Note: division by 2 because we're on the supergrid dx = np.broadcast_to( - R * np.cos(np.deg2rad(φ)) * np.deg2rad(dλ) / 2, - (λ.shape[0] - 1, φ.shape[0]), + R * np.cos(np.deg2rad(lats)) * np.deg2rad(dlons) / 2, + (lons.shape[0] - 1, lats.shape[0]), ).T - # dy = R * np.deg2rad(dφ) / 2 + # dy = R * np.deg2rad(dlats) / 2 # Note: division by 2 because we're on the supergrid - dy = np.broadcast_to(R * np.deg2rad(np.diff(φ)) / 2, (λ.shape[0], φ.shape[0] - 1)).T + dy = np.broadcast_to( + R * np.deg2rad(np.diff(lats)) / 2, (lons.shape[0], lats.shape[0] - 1) + ).T - lon, lat = np.meshgrid(λ, φ) + lon, lat = np.meshgrid(lons, lats) area = quadrilateral_areas(lat, lon, R) @@ -404,6 +551,26 @@ def rectangular_hgrid(λ, φ): ) +def find_files_by_pattern(paths: list, patterns: list, error_message=None) -> list: + """ + Function searchs paths for patterns and returns the list of the file paths with that pattern + """ + # Use glob to find all files + all_files = [] + for pattern in patterns: + for path in paths: + all_files.extend(Path(path).glob(pattern)) + + if len(all_files) == 0: + if error_message is None: + return "No files found at the following paths: {} for the following patterns: {}".format( + paths, patterns + ) + else: + return error_message + return all_files + + class experiment: """The main class for setting up a regional experiment. @@ -418,7 +585,7 @@ class experiment: The class can be used to generate the grids for a new experiment, or to read in an existing one (when ``read_existing_grids=True``; see argument description below). - Args: + Arguments: longitude_extent (Tuple[float]): Extent of the region in longitude (in degrees). For example: ``(40.5, 50.0)``. latitude_extent (Tuple[float]): Extent of the region in latitude (in degrees). For @@ -432,9 +599,9 @@ class experiment: depth (float): Depth of the domain. mom_run_dir (str): Path of the MOM6 control directory. mom_input_dir (str): Path of the MOM6 input directory, to receive the forcing files. - toolpath_dir (str): Path of GFDL's FRE tools (https://github.com/NOAA-GFDL/FRE-NCtools) + fre_tools_dir (str): Path of GFDL's FRE tools (https://github.com/NOAA-GFDL/FRE-NCtools) binaries. - grid_type (Optional[str]): Type of horizontal grid to generate. + hgrid_type (Optional[str]): Type of horizontal grid to generate. Currently, only ``'even_spacing'`` is supported. repeat_year_forcing (Optional[bool]): When ``True`` the experiment runs with repeat-year forcing. When ``False`` (default) then inter-annual forcing is used. @@ -442,13 +609,78 @@ class experiment: the grids and the ocean mask are being read from within the ``mom_input_dir`` and ``mom_run_dir`` directories. Useful for modifying or troubleshooting experiments. Default: ``False``. + minimum_depth (Optional[int]): The minimum depth in meters of a grid cell allowed before it is masked out and treated as land. """ + @classmethod + def create_empty( + cls, + longitude_extent=None, + latitude_extent=None, + date_range=None, + resolution=None, + number_vertical_layers=None, + layer_thickness_ratio=None, + depth=None, + mom_run_dir=None, + mom_input_dir=None, + fre_tools_dir=None, + hgrid_type="even_spacing", + repeat_year_forcing=False, + minimum_depth=4, + tidal_constituents=["M2", "S2", "N2", "K2", "K1", "O1", "P1", "Q1", "MM", "MF"], + expt_name=None, + boundaries=["south", "north", "west", "east"], + ): + """ + Alternative to the init method to create an empty expirement object, with the opportunity to override whatever values wanted. This is an unsafe function only to be used by experienced users. + + This function is a way for devs & more experienced users to set specific variables for specific function requirements, + like just regridding the initial condition or subsetting bathymetry, instead of having to set so many other variables that aren't needed. + """ + expt = cls( + longitude_extent=None, + latitude_extent=None, + date_range=None, + resolution=None, + number_vertical_layers=None, + layer_thickness_ratio=None, + depth=None, + minimum_depth=None, + mom_run_dir=None, + mom_input_dir=None, + fre_tools_dir=None, + create_empty=True, + hgrid_type=None, + repeat_year_forcing=None, + tidal_constituents=None, + expt_name=None, + ) + + expt.expt_name = expt_name + expt.tidal_constituents = tidal_constituents + expt.repeat_year_forcing = repeat_year_forcing + expt.hgrid_type = hgrid_type + expt.fre_tools_dir = fre_tools_dir + expt.mom_run_dir = mom_run_dir + expt.mom_input_dir = mom_input_dir + expt.minimum_depth = minimum_depth + expt.depth = depth + expt.layer_thickness_ratio = layer_thickness_ratio + expt.number_vertical_layers = number_vertical_layers + expt.resolution = resolution + expt.date_range = date_range + expt.latitude_extent = latitude_extent + expt.longitude_extent = longitude_extent + expt.ocean_mask = None + expt.layout = None + cls.segments = {} + cls.boundaries = boundaries + return expt + def __init__( self, *, - longitude_extent, - latitude_extent, date_range, resolution, number_vertical_layers, @@ -456,19 +688,36 @@ def __init__( depth, mom_run_dir, mom_input_dir, - toolpath_dir, - grid_type="even_spacing", + fre_tools_dir=None, + longitude_extent=None, + latitude_extent=None, + hgrid_type="even_spacing", + hgrid_path=None, + vgrid_type="hyperbolic_tangent", + vgrid_path=None, repeat_year_forcing=False, - read_existing_grids=False, + minimum_depth=4, + tidal_constituents=["M2", "S2", "N2", "K2", "K1", "O1", "P1", "Q1", "MM", "MF"], + create_empty=False, + expt_name=None, + boundaries=["south", "north", "west", "east"], ): + + # Creates empty experiment object for testing and experienced user manipulation. + # Kinda seems like a logical spinoff of this is to divorce the hgrid/vgrid creation from the experiment object initialization. + # Probably more of a CS workflow. That way read_existing_grids could be a function on its own, which ties in better with + # For now, check out the create_empty method for more explanation + if create_empty: + return + + # ## Set up the experiment with no config file ## in case list was given, convert to tuples - self.longitude_extent = tuple(longitude_extent) - self.latitude_extent = tuple(latitude_extent) + self.expt_name = expt_name self.date_range = tuple(date_range) self.mom_run_dir = Path(mom_run_dir) self.mom_input_dir = Path(mom_input_dir) - self.toolpath_dir = Path(toolpath_dir) + self.fre_tools_dir = Path(fre_tools_dir) if fre_tools_dir is not None else None self.mom_run_dir.mkdir(exist_ok=True) self.mom_input_dir.mkdir(exist_ok=True) @@ -481,23 +730,73 @@ def __init__( self.number_vertical_layers = number_vertical_layers self.layer_thickness_ratio = layer_thickness_ratio self.depth = depth - self.grid_type = grid_type + self.hgrid_type = hgrid_type + self.vgrid_type = vgrid_type self.repeat_year_forcing = repeat_year_forcing self.ocean_mask = None self.layout = None # This should be a tuple. Leaving in a dummy 'None' makes it easy to remind the user to provide a value later on. - if read_existing_grids: + self.minimum_depth = minimum_depth # Minimum depth allowed in bathy file + self.tidal_constituents = tidal_constituents + if hgrid_type == "from_file": + if hgrid_path is None: + hgrid_path = self.mom_input_dir / "hgrid.nc" + else: + hgrid_path = Path(hgrid_path) try: - self.hgrid = xr.open_dataset(self.mom_input_dir / "hgrid.nc") - self.vgrid = xr.open_dataset(self.mom_input_dir / "vcoord.nc") - except: - print( - "Error while reading in existing grids!\n\n" - + f"Make sure `hgrid.nc` and `vcoord.nc` exists in {self.mom_input_dir} directory." + self.hgrid = xr.open_dataset(hgrid_path) + self.longitude_extent = ( + float(self.hgrid.x.min()), + float(self.hgrid.x.max()), ) - raise ValueError + self.latitude_extent = ( + float(self.hgrid.y.min()), + float(self.hgrid.y.max()), + ) + except FileNotFoundError: + if hgrid_path is None: + raise FileNotFoundError( + f"Horizontal grid {self.mom_input_dir}/hgrid.nc not found. Make sure `hgrid.nc`exists in {self.mom_input_dir} directory." + ) + else: + raise FileNotFoundError(f"Horizontal grid {hgrid_path} not found.") + else: + if hgrid_path: + raise ValueError( + "hgrid_path can only be set if hgrid_type is 'from_file'." + ) + self.longitude_extent = tuple(longitude_extent) + self.latitude_extent = tuple(latitude_extent) self.hgrid = self._make_hgrid() + + if vgrid_type == "from_file": + if vgrid_path is None: + vgrid_path = self.mom_input_dir / "vgrid.nc" + else: + vgrid_path = Path(vgrid_path) + + try: + vgrid_from_file = xr.open_dataset(vgrid_path) + + except FileNotFoundError: + if vgrid_path is None: + raise FileNotFoundError( + f"Vertical grid {self.mom_input_dir}/vcoord.nc not found. Make sure `vcoord.nc`exists in {self.mom_input_dir} directory." + ) + else: + raise FileNotFoundError(f"Vertical grid {vgrid_path} not found.") + + self.vgrid = self._make_vgrid(vgrid_from_file.dz.data) + else: + if vgrid_path: + raise ValueError( + "vgrid_path can only be set if vgrid_type is 'from_file'." + ) self.vgrid = self._make_vgrid() + + self.segments = {} + self.boundaries = boundaries + # create additional directories and links (self.mom_input_dir / "weights").mkdir(exist_ok=True) (self.mom_input_dir / "forcing").mkdir(exist_ok=True) @@ -509,15 +808,167 @@ def __init__( if not input_rundir.exists(): input_rundir.symlink_to(self.mom_run_dir.resolve()) + def __str__(self) -> str: + return json.dumps(self.write_config_file(export=False, quiet=True), indent=4) + + @property + def bathymetry(self): + try: + return xr.open_dataset( + self.mom_input_dir / "bathymetry.nc", + decode_cf=False, + decode_times=False, + ) + except Exception as e: + print( + f"Error: {e}. Opening bathymetry threw an error! Make sure you've successfully run the setup_bathmetry method, or copied your own bathymetry.nc file into {self.mom_input_dir}." + ) + return None + + @property + def init_velocities(self): + try: + return xr.open_dataset( + self.mom_input_dir / "init_vel.nc", + decode_cf=False, + decode_times=False, + ) + except Exception as e: + print( + f"Error: {e}. Opening init_vel threw an error! Make sure you've successfully run the setup_initial_condition method, or copied your own init_vel.nc file into {self.mom_input_dir}." + ) + return + + @property + def init_tracers(self): + try: + return xr.open_dataset( + self.mom_input_dir / "init_tracers.nc", + decode_cf=False, + decode_times=False, + ) + except Exception as e: + print( + f"Error: {e}. Opening init_tracers threw an error! Make sure you've successfully run the setup_initial_condition method, or copied your own init_tracers.nc file into {self.mom_input_dir}." + ) + return + + @property + def ocean_state_boundary_paths(self): + """ + Finds the ocean state files from disk, and prints the file paths + """ + ocean_state_path = Path(self.mom_input_dir / "forcing") + patterns = [ + "forcing_*", + "weights/bi*", + ] + return find_files_by_pattern( + [ocean_state_path, self.mom_input_dir], + patterns, + error_message="No ocean state files set up yet (or files misplaced from {}). Call `setup_ocean_state_boundaries` method to set up ocean state.".format( + ocean_state_path + ), + ) + + @property + def tides_boundary_paths(self): + """ + Finds the tides files from disk, and prints the file paths + """ + tides_path = self.mom_input_dir / "forcing" + patterns = ["regrid*", "tu_*", "tz_*"] + return find_files_by_pattern( + [tides_path, self.mom_input_dir], + patterns, + error_message="No tides files set up yet (or files misplaced from {}). Call `setup_tides_boundaries` method to set up tides.".format( + tides_path + ), + ) + + @property + def era5_paths(self): + """ + Finds the ERA5 files from disk, and prints the file paths + """ + era5_path = self.mom_input_dir / "forcing" + # Use glob to find all *_ERA5.nc files + return find_files_by_pattern( + [era5_path], + ["*_ERA5.nc"], + error_message="No era5 files set up yet (or files misplaced from {}). Call `setup_era5` method to set up era5.".format( + era5_path + ), + ) + + @property + def initial_condition_paths(self): + """ + Finds the initial condition files from disk, and prints the file paths + """ + forcing_path = self.mom_input_dir / "forcing" + return find_files_by_pattern( + [forcing_path, self.mom_input_dir], + ["init_*.nc"], + error_message="No initial conditions files set up yet (or files misplaced from {}). Call `setup_initial_condition` method to set up initial conditions.".format( + forcing_path + ), + ) + + @property + def bathymetry_path(self): + """ + Finds the bathymetry file from disk, and prints the file path + """ + if (self.mom_input_dir / "bathymetry.nc").exists(): + return str(self.mom_input_dir / "bathymetry.nc") + else: + return "Not Found" + def __getattr__(self, name): + + ## First, check whether the attribute is an input file + if "segment" in name: + try: + return xr.open_mfdataset( + str(self.mom_input_dir / f"*{name}*.nc"), + decode_times=False, + decode_cf=False, + ) + except Exception as e: + print( + f"Error: {e}. {name} files threw an error! Make sure you've successfully run the setup_ocean_state_boundaries method, or copied your own segment files file into {self.mom_input_dir}." + ) + return None + + ## If we get here, attribute wasn't found + available_methods = [ method for method in dir(self) if not method.startswith("__") ] - error_message = ( - f"{name} method not found. Available methods are: {available_methods}" - ) + error_message = f"{name} not found. Available methods and attributes are: {available_methods}" raise AttributeError(error_message) + def find_MOM6_rectangular_orientation(self, input): + """ + Convert between MOM6 boundary and the specific segment number needed, or the inverse + """ + + direction_dir = {} + counter = 1 + for b in self.boundaries: + direction_dir[b] = counter + counter += 1 + direction_dir_inv = {v: k for k, v in direction_dir.items()} + merged_dict = {**direction_dir, **direction_dir_inv} + try: + val = merged_dict[input] + except KeyError: + raise ValueError( + "Invalid direction or segment number for MOM6 rectangular orientation" + ) + return val + def _make_hgrid(self): """ Set up a horizontal grid based on user's specification of the domain. @@ -525,14 +976,14 @@ def _make_hgrid(self): and in latitude. The latitudinal resolution is scaled with the cosine of the central - latitude of the domain, i.e., ``Δφ = cos(φ_central) * Δλ``, where ``Δλ`` + latitude of the domain, i.e., ``Δlats = cos(lats_central) * Δlons``, where ``Δlons`` is the longitudinal spacing. This way, for a sufficiently small domain, the linear distances between grid points are nearly identical: - ``Δx = R * cos(φ) * Δλ`` and ``Δy = R * Δφ = R * cos(φ_central) * Δλ`` - (here ``R`` is Earth's radius and ``φ``, ``φ_central``, ``Δλ``, and ``Δφ`` + ``Δx = R * cos(lats) * Δlons`` and ``Δy = R * Δlats = R * cos(lats_central) * Δlons`` + (here ``R`` is Earth's radius and ``lats``, ``lats_central``, ``Δlons``, and ``Δlats`` are all expressed in radians). - That is, if the domain is small enough that so that ``cos(φ_North_Side)`` - is not much different from ``cos(φ_South_Side)``, then ``Δx`` and ``Δy`` + That is, if the domain is small enough that so that ``cos(lats_North_Side)`` + is not much different from ``cos(lats_South_Side)``, then ``Δx`` and ``Δy`` are similar. Note: @@ -545,10 +996,10 @@ def _make_hgrid(self): """ assert ( - self.grid_type == "even_spacing" + self.hgrid_type == "even_spacing" ), "only even_spacing grid type is implemented" - if self.grid_type == "even_spacing": + if self.hgrid_type == "even_spacing": # longitudes are evenly spaced based on resolution and bounds nx = int( @@ -558,7 +1009,7 @@ def _make_hgrid(self): if nx % 2 != 1: nx += 1 - λ = np.linspace( + lons = np.linspace( self.longitude_extent[0], self.longitude_extent[1], nx ) # longitudes in degrees @@ -579,26 +1030,35 @@ def _make_hgrid(self): if ny % 2 != 1: ny += 1 - φ = np.linspace( + lats = np.linspace( self.latitude_extent[0], self.latitude_extent[1], ny ) # latitudes in degrees - hgrid = rectangular_hgrid(λ, φ) + hgrid = generate_rectangular_hgrid(lons, lats) hgrid.to_netcdf(self.mom_input_dir / "hgrid.nc") return hgrid - def _make_vgrid(self): + def _make_vgrid(self, thicknesses=None): """ Generates a vertical grid based on the ``number_vertical_layers``, the ratio of largest to smallest layer thickness (``layer_thickness_ratio``) and the total ``depth`` parameters. (All these parameters are specified at the class level.) + + Arguments: + thicknesses (Optional[np.ndarray]): An array of layer thicknesses. If not provided, + the layer thicknesses are generated using the :func:`~hyperbolictan_thickness_profile` + function. """ - thicknesses = hyperbolictan_thickness_profile( - self.number_vertical_layers, self.layer_thickness_ratio, self.depth - ) + if thicknesses is None: + thicknesses = hyperbolictan_thickness_profile( + self.number_vertical_layers, self.layer_thickness_ratio, self.depth + ) + + if not isinstance(thicknesses, np.ndarray): + raise ValueError("thicknesses must be a numpy array") zi = np.cumsum(thicknesses) zi = np.insert(zi, 0, 0.0) # add zi = 0.0 as first interface @@ -607,6 +1067,15 @@ def _make_vgrid(self): vcoord = xr.Dataset({"zi": ("zi", zi), "zl": ("zl", zl)}) + ## Check whether the minimum depth is less than the first three layers + + if len(zi) > 2 and self.minimum_depth < zi[2]: + print( + f"Warning: Minimum depth of {self.minimum_depth}m is less than the depth of the third interface ({zi[2]}m)!\n" + + "This means that some areas may only have one or two layers between the surface and sea floor. \n" + + "For increased stability, consider increasing the minimum depth, or adjusting the vertical coordinate to add more layers near the surface." + ) + vcoord["zi"].attrs = {"units": "meters"} vcoord["zl"].attrs = {"units": "meters"} @@ -614,31 +1083,85 @@ def _make_vgrid(self): return vcoord - def initial_condition( + def write_config_file(self, path=None, export=True, quiet=False): + """ + Write a json configuration file for the experiment. This file contains the experiment + variable information to allow for easy pass off to other users, with a strict computer + independence restriction. It also makes information about the expirement readable, and + is good for just printing out information about the experiment. + + Arguments: + path (str): Path to write the config file to. If not provided, the file is written to the ``mom_run_dir`` directory. + export (bool): If ``True`` (default), the configuration file is written to disk on the given ``path`` + quiet (bool): If ``True``, no print statements are made. + Returns: + Dict: A dictionary containing the configuration information. + """ + if not quiet: + print("Writing Config File.....") + try: + date_range = [ + self.date_range[0].strftime("%Y-%m-%d %H:%M:%S"), + self.date_range[1].strftime("%Y-%m-%d %H:%M:%S"), + ] + except IndexError: + date_range = None + config_dict = { + "expt_name": self.expt_name, + "date_range": date_range, + "latitude_extent": self.latitude_extent, + "longitude_extent": self.longitude_extent, + "resolution": self.resolution, + "number_vertical_layers": self.number_vertical_layers, + "layer_thickness_ratio": self.layer_thickness_ratio, + "depth": self.depth, + "hgrid_type": self.hgrid_type, + "repeat_year_forcing": self.repeat_year_forcing, + "ocean_mask": self.ocean_mask, + "layout": self.layout, + "minimum_depth": self.minimum_depth, + "tidal_constituents": self.tidal_constituents, + "boundaries": self.boundaries, + } + if export: + export_path = path or (self.mom_run_dir / "rmom6_config.json") + with open(export_path, "w") as f: + json.dump( + config_dict, + f, + indent=4, + ) + if not quiet: + print("Done.") + return config_dict + + def setup_initial_condition( self, raw_ic_path, varnames, arakawa_grid="A", vcoord_type="height", + rotational_method=rot.RotationMethod.EXPAND_GRID, ): """ Reads the initial condition from files in ``ic_path``, interpolates to the model grid, fixes up metadata, and saves back to the input directory. - Args: - raw_ic_path (Union[str, Path]): Path to raw initial condition file to read in. + Arguments: + raw_ic_path (Union[str, Path, list[str]]): Path(s) to raw initial condition file(s) to read in. varnames (Dict[str, str]): Mapping from MOM6 variable/coordinate names to the names in the input dataset. For example, ``{'xq': 'lonq', 'yh': 'lath', 'salt': 'so', ...}``. arakawa_grid (Optional[str]): Arakawa grid staggering type of the initial condition. Either ``'A'`` (default), ``'B'``, or ``'C'``. vcoord_type (Optional[str]): The type of vertical coordinate used in the forcing files. Either ``'height'`` or ``'thickness'``. + rotational_method (Optional[RotationMethod]): The method used to rotate the velocities. """ # Remove time dimension if present in the IC. # Assume that the first time dim is the intended on if more than one is present - ic_raw = xr.open_dataset(raw_ic_path) + ic_raw = xr.open_mfdataset(raw_ic_path) if varnames["time"] in ic_raw.dims: ic_raw = ic_raw.isel({varnames["time"]: 0}) if varnames["time"] in ic_raw.coords: @@ -755,34 +1278,6 @@ def initial_condition( + "Terminating!" ) - ## Construct the xq, yh and xh, yq grids - ugrid = ( - self.hgrid[["x", "y"]] - .isel(nxp=slice(None, None, 2), nyp=slice(1, None, 2)) - .rename({"x": "lon", "y": "lat"}) - .set_coords(["lat", "lon"]) - ) - vgrid = ( - self.hgrid[["x", "y"]] - .isel(nxp=slice(1, None, 2), nyp=slice(None, None, 2)) - .rename({"x": "lon", "y": "lat"}) - .set_coords(["lat", "lon"]) - ) - - ## Construct the cell centre grid for tracers (xh, yh). - tgrid = xr.Dataset( - { - "lon": ( - ["lon"], - self.hgrid.x.isel(nxp=slice(1, None, 2), nyp=1).values, - ), - "lat": ( - ["lat"], - self.hgrid.y.isel(nxp=1, nyp=slice(1, None, 2)).values, - ), - } - ) - # NaNs might be here from the land mask of the model that the IC has come from. # If they're not removed then the coastlines from this other grid will be retained! # The land mask comes from the bathymetry file, so we don't need NaNs @@ -822,54 +1317,98 @@ def initial_condition( .bfill("lat") ) + self.hgrid["lon"] = self.hgrid["x"] + self.hgrid["lat"] = self.hgrid["y"] + tgrid = ( + rgd.get_hgrid_arakawa_c_points(self.hgrid, "t") + .rename({"tlon": "lon", "tlat": "lat", "nxp": "nx", "nyp": "ny"}) + .set_coords(["lat", "lon"]) + ) + ## Make our three horizontal regridders - regridder_u = xe.Regridder( - ic_raw_u, - ugrid, - "bilinear", + + regridder_u = rgd.create_regridder( + ic_raw_u, self.hgrid, locstream_out=False, method="bilinear" ) - regridder_v = xe.Regridder( - ic_raw_v, - vgrid, - "bilinear", + regridder_v = rgd.create_regridder( + ic_raw_v, self.hgrid, locstream_out=False, method="bilinear" ) + regridder_t = rgd.create_regridder( + ic_raw_tracers, tgrid, locstream_out=False, method="bilinear" + ) # Doesn't need to be rotated, so we can regrid to just tracers - regridder_t = xe.Regridder( - ic_raw_tracers, - tgrid, - "bilinear", - ) + # ugrid= rgd.get_hgrid_arakawa_c_points(self.hgrid, "u").rename({"ulon": "lon", "ulat": "lat"}).set_coords(["lat", "lon"]) + # vgrid = rgd.get_hgrid_arakawa_c_points(self.hgrid, "v").rename({"vlon": "lon", "vlat": "lat"}).set_coords(["lat", "lon"]) - print("INITIAL CONDITIONS") + ## Construct the cell centre grid for tracers (xh, yh). + print("Setting up Initial Conditions") ## Regrid all fields horizontally. print("Regridding Velocities... ", end="") + regridded_u = regridder_u(ic_raw_u) + regridded_v = regridder_v(ic_raw_v) + rotated_u, rotated_v = rotate( + regridded_u, + regridded_v, + radian_angle=np.radians( + rot.get_rotation_angle(rotational_method, self.hgrid).values + ), + ) + # Slice the velocites to the u and v grid. + u_points = rgd.get_hgrid_arakawa_c_points(self.hgrid, "u") + v_points = rgd.get_hgrid_arakawa_c_points(self.hgrid, "v") + rotated_v = rotated_v[:, v_points.v_points_y.values, v_points.v_points_x.values] + rotated_u = rotated_u[:, u_points.u_points_y.values, u_points.u_points_x.values] + rotated_u["lon"] = u_points.ulon + rotated_u["lat"] = u_points.ulat + rotated_v["lon"] = v_points.vlon + rotated_v["lat"] = v_points.vlat + + # Merge Vels vel_out = xr.merge( [ - regridder_u(ic_raw_u) - .rename({"lon": "xq", "lat": "yh", "nyp": "ny", varnames["zl"]: "zl"}) - .rename("u"), - regridder_v(ic_raw_v) - .rename({"lon": "xh", "lat": "yq", "nxp": "nx", varnames["zl"]: "zl"}) - .rename("v"), + rotated_u.rename( + {"lon": "xq", "lat": "yh", "nyp": "ny", varnames["zl"]: "zl"} + ).rename("u"), + rotated_v.rename( + {"lon": "xh", "lat": "yq", "nxp": "nx", varnames["zl"]: "zl"} + ).rename("v"), ] ) print("Done.\nRegridding Tracers... ", end="") - tracers_out = xr.merge( - [ - regridder_t(ic_raw_tracers[varnames["tracers"][i]]).rename(i) - for i in varnames["tracers"] - ] - ).rename({"lon": "xh", "lat": "yh", varnames["zl"]: "zl"}) + tracers_out = ( + xr.merge( + [ + regridder_t(ic_raw_tracers[varnames["tracers"][i]]).rename(i) + for i in varnames["tracers"] + ] + ) + .rename({"lon": "xh", "lat": "yh", varnames["zl"]: "zl"}) + .transpose("zl", "ny", "nx") + ) + + # tracers_out = tracers_out.assign_coords( + # {"nx":np.arange(tracers_out.sizes["nx"]).astype(float), + # "ny":np.arange(tracers_out.sizes["ny"]).astype(float)}) + # Add dummy values for the nx and ny dimensions. Otherwise MOM6 complains that it's missing data?? + tracers_out = tracers_out.assign_coords( + { + "nx": np.arange(tracers_out.sizes["nx"]).astype(float), + "ny": np.arange(tracers_out.sizes["ny"]).astype(float), + } + ) print("Done.\nRegridding Free surface... ", end="") eta_out = ( - regridder_t(ic_raw_eta).rename({"lon": "xh", "lat": "yh"}).rename("eta_t") + regridder_t(ic_raw_eta) + .rename({"lon": "xh", "lat": "yh"}) + .rename("eta_t") + .transpose("ny", "nx") ) ## eta_t is the name set in MOM_input by default print("Done.") @@ -894,14 +1433,11 @@ def initial_condition( eta_out.attrs = ic_raw_eta.attrs ## Regrid the fields vertically - if ( vcoord_type == "thickness" ): ## In this case construct the vertical profile by summing thickness tracers_out["zl"] = tracers_out["zl"].diff("zl") - dz = tracers_out[self.z].diff(self.z) - dz.name = "dz" - dz = xr.concat([dz, dz[-1]], dim=self.z) + dz = rgd.generate_dz(tracers_out, self.z) tracers_out = tracers_out.interp({"zl": self.vgrid.zl.values}) vel_out = vel_out.interp({"zl": self.vgrid.zl.values}) @@ -909,7 +1445,7 @@ def initial_condition( print("Saving outputs... ", end="") vel_out.fillna(0).to_netcdf( - self.mom_input_dir / "forcing/init_vel.nc", + self.mom_input_dir / "init_vel.nc", mode="w", encoding={ "u": {"_FillValue": netCDF4.default_fillvals["f4"]}, @@ -918,22 +1454,17 @@ def initial_condition( ) tracers_out.to_netcdf( - self.mom_input_dir / "forcing/init_tracers.nc", + self.mom_input_dir / "init_tracers.nc", mode="w", encoding={ - "xh": {"_FillValue": None}, - "yh": {"_FillValue": None}, - "zl": {"_FillValue": None}, "temp": {"_FillValue": -1e20, "missing_value": -1e20}, "salt": {"_FillValue": -1e20, "missing_value": -1e20}, }, ) eta_out.to_netcdf( - self.mom_input_dir / "forcing/init_eta.nc", + self.mom_input_dir / "init_eta.nc", mode="w", encoding={ - "xh": {"_FillValue": None}, - "yh": {"_FillValue": None}, "eta_t": {"_FillValue": None}, }, ) @@ -946,122 +1477,171 @@ def initial_condition( return - def get_glorys_rectangular( - self, raw_boundaries_path, boundaries=["south", "north", "west", "east"] - ): + def get_glorys(self, raw_boundaries_path): """ - This function is a wrapper for `get_glorys_data`, calling this function once for each of the rectangular boundary segments and the initial condition. For more complex boundary shapes, call `get_glorys_data` directly for each of your boundaries that aren't parallel to lines of constant latitude or longitude. + This is a wrapper that calls :func:`~get_glorys_data` once for each of the rectangular boundary segments + and the initial condition. For more complex boundary shapes, call :func:`~get_glorys_data` directly for + each of your boundaries that aren't parallel to lines of constant latitude or longitude. For example, + for an angled Northern boundary that spans multiple latitudes, we need to download a wider rectangle + containing the entire boundary. - args: + Arguments: raw_boundaries_path (str): Path to the directory containing the raw boundary forcing files. boundaries (List[str]): List of cardinal directions for which to create boundary forcing files. - Default is `["south", "north", "west", "east"]`. + Default is ``["south", "north", "west", "east"]``. """ # Initial Condition get_glorys_data( - self.longitude_extent, - self.latitude_extent, - [ + longitude_extent=[float(self.hgrid.x.min()), float(self.hgrid.x.max())], + latitude_extent=[float(self.hgrid.y.min()), float(self.hgrid.y.max())], + timerange=[ self.date_range[0], self.date_range[0] + datetime.timedelta(days=1), ], - "ic_unprocessed", - raw_boundaries_path, - modify_existing=False, + segment_name="ic_unprocessed", + download_path=raw_boundaries_path, + modify_existing=False, # This is the first line, so start bash script anew ) - if "east" in boundaries: + if "east" in self.boundaries: get_glorys_data( - [self.longitude_extent[1], self.longitude_extent[1]], - [self.latitude_extent[0], self.latitude_extent[1]], - self.date_range, - "east_unprocessed", - raw_boundaries_path, + longitude_extent=[ + float(self.hgrid.x.isel(nxp=-1).min()), + float(self.hgrid.x.isel(nxp=-1).max()), + ], ## Collect from Eastern (x = -1) side + latitude_extent=[ + float(self.hgrid.y.isel(nxp=-1).min()), + float(self.hgrid.y.isel(nxp=-1).max()), + ], + timerange=self.date_range, + segment_name="east_unprocessed", + download_path=raw_boundaries_path, ) - if "west" in boundaries: + if "west" in self.boundaries: get_glorys_data( - [self.longitude_extent[0], self.longitude_extent[0]], - [self.latitude_extent[0], self.latitude_extent[1]], - self.date_range, - "west_unprocessed", - raw_boundaries_path, + longitude_extent=[ + float(self.hgrid.x.isel(nxp=0).min()), + float(self.hgrid.x.isel(nxp=0).max()), + ], ## Collect from Western (x = 0) side + latitude_extent=[ + float(self.hgrid.y.isel(nxp=0).min()), + float(self.hgrid.y.isel(nxp=0).max()), + ], + timerange=self.date_range, + segment_name="west_unprocessed", + download_path=raw_boundaries_path, ) - if "north" in boundaries: + if "south" in self.boundaries: get_glorys_data( - [self.longitude_extent[0], self.longitude_extent[1]], - [self.latitude_extent[1], self.latitude_extent[1]], - self.date_range, - "north_unprocessed", - raw_boundaries_path, + longitude_extent=[ + float(self.hgrid.x.isel(nyp=0).min()), + float(self.hgrid.x.isel(nyp=0).max()), + ], ## Collect from Southern (y = 0) side + latitude_extent=[ + float(self.hgrid.y.isel(nyp=0).min()), + float(self.hgrid.y.isel(nyp=0).max()), + ], + timerange=self.date_range, + segment_name="south_unprocessed", + download_path=raw_boundaries_path, ) - if "south" in boundaries: + if "north" in self.boundaries: get_glorys_data( - [self.longitude_extent[0], self.longitude_extent[1]], - [self.latitude_extent[0], self.latitude_extent[0]], - self.date_range, - "south_unprocessed", - raw_boundaries_path, + longitude_extent=[ + float(self.hgrid.x.isel(nyp=-1).min()), + float(self.hgrid.x.isel(nyp=-1).max()), + ], ## Collect from Southern (y = -1) side + latitude_extent=[ + float(self.hgrid.y.isel(nyp=-1).min()), + float(self.hgrid.y.isel(nyp=-1).max()), + ], + timerange=self.date_range, + segment_name="north_unprocessed", + download_path=raw_boundaries_path, ) print( - f"script `get_glorys_data.sh` has been greated at {raw_boundaries_path}.\n Run this script via bash to download the data from a terminal with internet access. \nYou will need to enter your Copernicus Marine username and password.\nIf you don't have an account, make one here:\nhttps://data.marine.copernicus.eu/register" + f"The script `get_glorys_data.sh` has been generated at:\n {raw_boundaries_path}.\n" + f"To download the data, run this script using `bash` in a terminal with internet access.\n\n" + f"Important instructions:\n" + f"1. You will need your Copernicus Marine username and password.\n" + f" If you do not have an account, you can create one here: \n" + f" https://data.marine.copernicus.eu/register\n" + f"2. You will be prompted to enter your Copernicus Marine credentials multiple times: once for each dataset.\n" + f"3. Depending on the dataset size, the download process may take significant time and resources.\n" + f"4. Thus, on certain systems, you may need to run this script as a batch job.\n" ) return - def rectangular_boundaries( + def setup_ocean_state_boundaries( self, raw_boundaries_path, varnames, - boundaries=["south", "north", "west", "east"], arakawa_grid="A", + bathymetry_path=None, + rotational_method=rot.RotationMethod.EXPAND_GRID, ): """ - This function is a wrapper for `simple_boundary`. Given a list of up to four cardinal directions, - it creates a boundary forcing file for each one. Ensure that the raw boundaries are all saved in the same directory, - and that they are named using the format `east_unprocessed.nc` + This is a wrapper for :func:`~simple_boundary`. Given a list of up to four cardinal directions, + it creates a boundary forcing file for each one. Ensure that the raw boundaries are all saved + in the same directory, and that they are named using the format ``east_unprocessed.nc``. - Args: + Arguments: raw_boundaries_path (str): Path to the directory containing the raw boundary forcing files. varnames (Dict[str, str]): Mapping from MOM6 variable/coordinate names to the name in the input dataset. boundaries (List[str]): List of cardinal directions for which to create boundary forcing files. - Default is `["south", "north", "west", "east"]`. + Default is ``["south", "north", "west", "east"]``. arakawa_grid (Optional[str]): Arakawa grid staggering type of the boundary forcing. Either ``'A'`` (default), ``'B'``, or ``'C'``. + bathymetry_path (Optional[str]): Path to the bathymetry file. Default is ``None``, in which case the + boundary condition is not masked. + rotational_method (Optional[str]): Method to use for rotating the boundary velocities. Default is ``EXPAND_GRID``. """ - for i in boundaries: + for i in self.boundaries: if i not in ["south", "north", "west", "east"]: raise ValueError( f"Invalid boundary direction: {i}. Must be one of ['south', 'north', 'west', 'east']" ) - if len(boundaries) < 4: + if len(self.boundaries) < 4: print( - "NOTE: the 'setup_run_directories' method assumes that you have four boundaries. You'll need to modify the MOM_input file manually to reflect the number of boundaries you have, and their orientations. You should be able to find the relevant section in the MOM_input file by searching for 'segment_'. Ensure that the segment names match those in your inputdir/forcing folder" + "NOTE: the 'setup_run_directories' method does understand the less than four boundaries but be careful. Please check the MOM_input/override file carefully to reflect the number of boundaries you have, and their orientations. You should be able to find the relevant section in the MOM_input/override file by searching for 'segment_'. Ensure that the segment names match those in your inputdir/forcing folder" ) - if len(boundaries) > 4: + if len(self.boundaries) > 4: raise ValueError( "This method only supports up to four boundaries. To set up more complex boundary shapes you can manually call the 'simple_boundary' method for each boundary." ) + # Now iterate through our four boundaries - for i, orientation in enumerate(boundaries, start=1): - self.simple_boundary( - Path(raw_boundaries_path) / (orientation + "_unprocessed.nc"), + for orientation in self.boundaries: + self.setup_single_boundary( + Path(raw_boundaries_path / (orientation + "_unprocessed.nc")), varnames, orientation, # The cardinal direction of the boundary - i, # A number to identify the boundary; indexes from 1 + self.find_MOM6_rectangular_orientation( + orientation + ), # A number to identify the boundary; indexes from 1 arakawa_grid=arakawa_grid, + bathymetry_path=bathymetry_path, + rotational_method=rotational_method, ) - def simple_boundary( - self, path_to_bc, varnames, orientation, segment_number, arakawa_grid="A" + def setup_single_boundary( + self, + path_to_bc, + varnames, + orientation, + segment_number, + arakawa_grid="A", + bathymetry_path=None, + rotational_method=rot.RotationMethod.EXPAND_GRID, ): """ - Here 'simple' refers to boundaries that are parallel to lines of constant longitude or latitude. - Set up a boundary forcing file for a given orientation. + Set up a boundary forcing file for a given ``orientation``. - Args: + Arguments: path_to_bc (str): Path to boundary forcing file. Ideally this should be a pre cut-out netCDF file containing only the boundary region and 3 extra boundary points on either side. Users can also provide a large dataset containing their entire domain but this @@ -1074,15 +1654,22 @@ def simple_boundary( the ``MOM_input``. arakawa_grid (Optional[str]): Arakawa grid staggering type of the boundary forcing. Either ``'A'`` (default), ``'B'``, or ``'C'``. + bathymetry_path (str): Path to the bathymetry file. Default is ``None``, in which case + the boundary condition is not masked. + rotational_method (Optional[str]): Method to use for rotating the boundary velocities. + Default is 'EXPAND_GRID'. """ - print("Processing {} boundary...".format(orientation), end="") + print( + "Processing {} boundary velocity & tracers...".format(orientation), end="" + ) if not path_to_bc.exists(): raise FileNotFoundError( f"Boundary file not found at {path_to_bc}. Please ensure that the files are named in the format `east_unprocessed.nc`." ) - seg = segment( + self.segments[orientation] = segment( hgrid=self.hgrid, + bathymetry_path=bathymetry_path, infile=path_to_bc, # location of raw boundary outfolder=self.mom_input_dir, varnames=varnames, @@ -1093,32 +1680,134 @@ def simple_boundary( repeat_year_forcing=self.repeat_year_forcing, ) - seg.rectangular_brushcut() + self.segments[orientation].regrid_velocity_tracers( + rotational_method=rotational_method + ) + print("Done.") return + def setup_boundary_tides( + self, + tpxo_elevation_filepath, + tpxo_velocity_filepath, + tidal_constituents=None, + bathymetry_path=None, + rotational_method=rot.RotationMethod.EXPAND_GRID, + ): + """Subset the tidal data and generate more boundary files. + + Arguments: + path_to_td (str): Path to boundary tidal file. + tpxo_elevation_filepath: Filepath to the TPXO elevation product. Generally of the form ``h_tidalversion.nc`` + tpxo_velocity_filepath: Filepath to the TPXO velocity product. Generally of the form ``u_tidalversion.nc`` + tidal_constituents: List of tidal constituents to include in the regridding. Default is set in the constructor + bathymetry_path (str): Path to the bathymetry file. Default is ``None``, in which case the boundary condition is not masked + rotational_method (str): Method to use for rotating the tidal velocities. Default is 'EXPAND_GRID'. + + Returns: + netCDF files: Regridded tidal velocity and elevation files in 'inputdir/forcing' + + The tidal data functions are sourced from the GFDL NWA25 and modified so that: + - Converted code for regional-mom6 segment class + - Implemented horizontal subsetting. + - Combined all functions of NWA25 into a four function process (in the style of regional-mom6), i.e., ``expt.setup_tides_rectangular_boundaries``, ``coords``, ``segment.regrid_tides``, and ``segment.encode_tidal_files_and_output``. + + Code sourced from: + Author(s): GFDL, James Simkins, Rob Cermak, and contributors + Year: 2022 + Title: "NWA25: Northwest Atlantic 1/25th Degree MOM6 Simulation" + Version: N/A + Type: Python Functions, Source Code + Web Address: https://github.com/jsimkins2/nwa25 + """ + if tidal_constituents is not None: + self.tidal_constituents = tidal_constituents + tpxo_h = ( + xr.open_dataset(Path(tpxo_elevation_filepath)) + .rename({"lon_z": "lon", "lat_z": "lat", "nc": "constituent"}) + .isel( + constituent=convert_to_tpxo_tidal_constituents(self.tidal_constituents) + ) + ) + + h = tpxo_h["ha"] * np.exp(-1j * np.radians(tpxo_h["hp"])) + tpxo_h["hRe"] = np.real(h) + tpxo_h["hIm"] = np.imag(h) + tpxo_u = ( + xr.open_dataset(Path(tpxo_velocity_filepath)) + .rename({"lon_u": "lon", "lat_u": "lat", "nc": "constituent"}) + .isel( + constituent=convert_to_tpxo_tidal_constituents(self.tidal_constituents) + ) + ) + tpxo_u["ua"] *= 0.01 # convert to m/s + u = tpxo_u["ua"] * np.exp(-1j * np.radians(tpxo_u["up"])) + tpxo_u["uRe"] = np.real(u) + tpxo_u["uIm"] = np.imag(u) + tpxo_v = ( + xr.open_dataset(Path(tpxo_velocity_filepath)) + .rename({"lon_v": "lon", "lat_v": "lat", "nc": "constituent"}) + .isel( + constituent=convert_to_tpxo_tidal_constituents(self.tidal_constituents) + ) + ) + tpxo_v["va"] *= 0.01 # convert to m/s + v = tpxo_v["va"] * np.exp(-1j * np.radians(tpxo_v["vp"])) + tpxo_v["vRe"] = np.real(v) + tpxo_v["vIm"] = np.imag(v) + times = xr.DataArray( + pd.date_range( + self.date_range[0], periods=1 + ), # Import pandas for this shouldn't be a big deal b/c it's already required in regional-mom6 dependencies + dims=["time"], + ) + # Initialize or find boundary segment + for b in self.boundaries: + print("Processing {} boundary...".format(b), end="") + + # If the GLORYS ocean_state has already created segments, we don't create them again. + seg = segment( + hgrid=self.hgrid, + bathymetry_path=bathymetry_path, + infile=None, # location of raw boundary + outfolder=self.mom_input_dir, + varnames=None, + segment_name="segment_{:03d}".format( + self.find_MOM6_rectangular_orientation(b) + ), + orientation=b, + startdate=self.date_range[0], + repeat_year_forcing=self.repeat_year_forcing, + ) + + # Output and regrid tides + seg.regrid_tides( + tpxo_v, tpxo_u, tpxo_h, times, rotational_method=rotational_method + ) + print("Done") + def setup_bathymetry( self, *, bathymetry_path, longitude_coordinate_name="lon", latitude_coordinate_name="lat", - vertical_coordinate_name="elevation", + vertical_coordinate_name="elevation", # This is to match GEBCO fill_channels=False, - minimum_layers=3, positive_down=False, - chunks="auto", + write_to_file=True, ): """ Cut out and interpolate the chosen bathymetry and then fill inland lakes. - It's also possible to optionally fill narrow channels (see ``fill_channels`` - below), although narrow channels are less of an issue for models that are - discretized on an Arakawa C grid, like MOM6. + Users can optionally fill narrow channels (see ``fill_channels`` keyword argument + below). Note, however, that narrow channels are less of an issue for models that + are discretized on an Arakawa C grid, like MOM6. Output is saved in the input directory of the experiment. - Args: + Arguments: bathymetry_path (str): Path to the netCDF file with the bathymetry. longitude_coordinate_name (Optional[str]): The name of the longitude coordinate in the bathymetry dataset at ``bathymetry_path``. For example, for GEBCO bathymetry: ``'lon'`` (default). @@ -1129,15 +1818,9 @@ def setup_bathymetry( fill_channels (Optional[bool]): Whether or not to fill in diagonal channels. This removes more narrow inlets, but can also connect extra islands to land. Default: ``False``. - minimum_layers (Optional[int]): The minimum depth allowed as an integer - number of layers. Anything shallower than the ``minimum_layers`` - (as specified by the vertical coordinate file ``vcoord.nc``) is deemed land. - Default: 3. positive_down (Optional[bool]): If ``True``, it assumes that bathymetry vertical coordinate is positive down. Default: ``False``. - chunks (Optional Dict[str, str]): Horizontal chunking scheme for the bathymetry, e.g., - ``{"longitude": 100, "latitude": 100}``. Use ``'longitude'`` and ``'latitude'`` rather - than the actual coordinate names in the input file. + write_to_file (Optional[bool]): Whether to write the bathymetry to a file. Default: ``True``. """ ## Convert the provided coordinate names into a dictionary mapping to the @@ -1145,16 +1828,11 @@ def setup_bathymetry( coordinate_names = { "xh": longitude_coordinate_name, "yh": latitude_coordinate_name, - "elevation": vertical_coordinate_name, + "depth": vertical_coordinate_name, } - if chunks != "auto": - chunks = { - coordinate_names["xh"]: chunks["longitude"], - coordinate_names["yh"]: chunks["latitude"], - } - bathymetry = xr.open_dataset(bathymetry_path, chunks=chunks)[ - coordinate_names["elevation"] + bathymetry = xr.open_dataset(bathymetry_path, chunks="auto")[ + coordinate_names["depth"] ] bathymetry = bathymetry.sel( @@ -1201,7 +1879,7 @@ def setup_bathymetry( ) bathymetry.attrs["missing_value"] = -1e20 # missing value expected by FRE tools - bathymetry_output = xr.Dataset({"elevation": bathymetry}) + bathymetry_output = xr.Dataset({"depth": bathymetry}) bathymetry.close() bathymetry_output = bathymetry_output.rename( @@ -1209,35 +1887,24 @@ def setup_bathymetry( ) bathymetry_output.lon.attrs["units"] = "degrees_east" bathymetry_output.lat.attrs["units"] = "degrees_north" - bathymetry_output.elevation.attrs["_FillValue"] = -1e20 - bathymetry_output.elevation.attrs["units"] = "meters" - bathymetry_output.elevation.attrs["standard_name"] = ( + bathymetry_output.depth.attrs["_FillValue"] = -1e20 + bathymetry_output.depth.attrs["units"] = "meters" + bathymetry_output.depth.attrs["standard_name"] = ( "height_above_reference_ellipsoid" ) - bathymetry_output.elevation.attrs["long_name"] = ( - "Elevation relative to sea level" - ) - bathymetry_output.elevation.attrs["coordinates"] = "lon lat" - bathymetry_output.to_netcdf( - self.mom_input_dir / "bathymetry_original.nc", mode="w", engine="netcdf4" - ) + bathymetry_output.depth.attrs["long_name"] = "Elevation relative to sea level" + bathymetry_output.depth.attrs["coordinates"] = "lon lat" + if write_to_file: + bathymetry_output.to_netcdf( + self.mom_input_dir / "bathymetry_original.nc", + mode="w", + engine="netcdf4", + ) - tgrid = xr.Dataset( - { - "lon": ( - ["lon"], - self.hgrid.x.isel(nxp=slice(1, None, 2), nyp=1).values, - ), - "lat": ( - ["lat"], - self.hgrid.y.isel(nxp=1, nyp=slice(1, None, 2)).values, - ), - } - ) tgrid = xr.Dataset( data_vars={ - "elevation": ( - ["lat", "lon"], + "depth": ( + ["ny", "nx"], np.zeros( self.hgrid.x.isel( nxp=slice(1, None, 2), nyp=slice(1, None, 2) @@ -1247,69 +1914,77 @@ def setup_bathymetry( }, coords={ "lon": ( - ["lon"], - self.hgrid.x.isel(nxp=slice(1, None, 2), nyp=1).values, + ["ny", "nx"], + self.hgrid.x.isel( + nxp=slice(1, None, 2), nyp=slice(1, None, 2) + ).values, ), "lat": ( - ["lat"], - self.hgrid.y.isel(nxp=1, nyp=slice(1, None, 2)).values, + ["ny", "nx"], + self.hgrid.y.isel( + nxp=slice(1, None, 2), nyp=slice(1, None, 2) + ).values, ), }, ) # rewrite chunks to use lat/lon now for use with xesmf - if chunks != "auto": - chunks = { - "lon": chunks[coordinate_names["xh"]], - "lat": chunks[coordinate_names["yh"]], - } - - tgrid = tgrid.chunk(chunks) tgrid.lon.attrs["units"] = "degrees_east" tgrid.lon.attrs["_FillValue"] = 1e20 tgrid.lat.attrs["units"] = "degrees_north" tgrid.lat.attrs["_FillValue"] = 1e20 - tgrid.elevation.attrs["units"] = "meters" - tgrid.elevation.attrs["coordinates"] = "lon lat" - tgrid.to_netcdf( - self.mom_input_dir / "bathymetry_unfinished.nc", mode="w", engine="netcdf4" - ) - tgrid.close() + tgrid.depth.attrs["units"] = "meters" + tgrid.depth.attrs["coordinates"] = "lon lat" + if write_to_file: + tgrid.to_netcdf( + self.mom_input_dir / "bathymetry_unfinished.nc", + mode="w", + engine="netcdf4", + ) + tgrid.close() + + bathymetry_output = bathymetry_output.load() - ## Replace subprocess run with regular regridder print( "Begin regridding bathymetry...\n\n" - + "If this process hangs it means that the chosen domain might be too big to handle this way. " - + "After ensuring access to appropriate computational resources, try calling ESMF " - + "directly from a terminal in the input directory via\n\n" - + "mpirun ESMF_Regrid -s bathymetry_original.nc -d bathymetry_unfinished.nc -m bilinear --src_var elevation --dst_var elevation --netcdf4 --src_regional --dst_regional\n\n" + + f"Original bathymetry size: {bathymetry_output.nbytes/1e6:.2f} Mb\n" + + f"Regridded size: {tgrid.nbytes/1e6:.2f} Mb\n" + + "Automatic regridding may fail if your domain is too big! If this process hangs or crashes," + + "open a terminal with appropriate computational and resources try calling ESMF " + + f"directly in the input directory {self.mom_input_dir} via\n\n" + + "`mpirun -np NUMBER_OF_CPUS ESMF_Regrid -s bathymetry_original.nc -d bathymetry_unfinished.nc -m bilinear --src_var depth --dst_var depth --netcdf4 --src_regional --dst_regional`\n\n" + "For details see https://xesmf.readthedocs.io/en/latest/large_problems_on_HPC.html\n\n" - + "Afterwards, we run 'tidy_bathymetry' method to skip the expensive interpolation step, and finishing metadata, encoding and cleanup." - ) - - # If we have a domain large enough for chunks, we'll run regridder with parallel=True - parallel = True - if len(tgrid.chunks) != 2: - parallel = False - print(f"Regridding in parallel: {parallel}") - bathymetry_output = bathymetry_output.chunk(chunks) - # return - regridder = xe.Regridder( - bathymetry_output, tgrid, "bilinear", parallel=parallel + + "Afterwards, we run the 'expt.tidy_bathymetry' method to skip the expensive interpolation step, and finishing metadata, encoding and cleanup.\n\n\n" ) - + regridder = xe.Regridder(bathymetry_output, tgrid, "bilinear", parallel=False) bathymetry = regridder(bathymetry_output) - bathymetry.to_netcdf( - self.mom_input_dir / "bathymetry_unfinished.nc", mode="w", engine="netcdf4" - ) + if write_to_file: + bathymetry.to_netcdf( + self.mom_input_dir / "bathymetry_unfinished.nc", + mode="w", + engine="netcdf4", + ) print( - "Regridding finished. Now calling `tidy_bathymetry` method for some finishing touches..." + "Regridding successful! Now calling `tidy_bathymetry` method for some finishing touches..." ) - self.tidy_bathymetry(fill_channels, minimum_layers, positive_down) + print("setup bathymetry has finished successfully.") + return self.tidy_bathymetry( + fill_channels, + positive_down, + bathymetry=bathymetry, + write_to_file=write_to_file, + ) def tidy_bathymetry( - self, fill_channels=False, minimum_layers=3, positive_down=True + self, + fill_channels=False, + positive_down=False, + vertical_coordinate_name="depth", + bathymetry=None, + write_to_file=True, + longitude_coordinate_name="lon", + latitude_coordinate_name="lat", ): """ An auxiliary function for bathymetry used to fix up the metadata and remove inland @@ -1321,27 +1996,34 @@ def tidy_bathymetry( or fill in some channels, then call this function directly to read in the existing ``bathymetry_unfinished.nc`` file that should be in the input directory. - Args: + Arguments: fill_channels (Optional[bool]): Whether to fill in diagonal channels. This removes more narrow inlets, but can also connect extra islands to land. Default: ``False``. - minimum_layers (Optional[int]): The minimum depth allowed - as an integer number of layers. The default value of ``3`` - layers means that anything shallower than the 3rd - layer (as specified by the ``vcoord``) is deemed land. - positive_down (Optional[bool]): If ``True`` (default), assume that - bathymetry vertical coordinate is positive down. + positive_down (Optional[bool]): If ``False`` (default), assume that + bathymetry vertical coordinate is positive down, as is the case in GEBCO for example. + bathymetry (Optional[xr.Dataset]): The bathymetry dataset to tidy up. If not provided, + it will read the bathymetry from the file ``bathymetry_unfinished.nc`` in the input directory + that was created by :func:`~setup_bathymetry`. """ ## reopen bathymetry to modify - print("Reading in regridded bathymetry to fix up metadata...", end="") - bathymetry = xr.open_dataset( - self.mom_input_dir / "bathymetry_unfinished.nc", engine="netcdf4" + print( + "Tidy bathymetry: Reading in regridded bathymetry to fix up metadata...", + end="", ) + if read_bathy_from_file := bathymetry is None: + bathymetry = xr.open_dataset( + self.mom_input_dir / "bathymetry_unfinished.nc", engine="netcdf4" + ) ## Ensure correct encoding bathymetry = xr.Dataset( - {"depth": (["ny", "nx"], bathymetry["elevation"].values)} + {"depth": (["ny", "nx"], bathymetry[vertical_coordinate_name].values)}, + coords={ + "lon": (["ny", "nx"], bathymetry[longitude_coordinate_name].values), + "lat": (["ny", "nx"], bathymetry[latitude_coordinate_name].values), + }, ) bathymetry.attrs["depth"] = "meters" bathymetry.attrs["standard_name"] = "bathymetric depth at T-cell centers" @@ -1353,15 +2035,13 @@ def tidy_bathymetry( ## Ensure that coordinate is positive down! bathymetry["depth"] *= -1 - ## REMOVE INLAND LAKES - - min_depth = self.vgrid.zi[minimum_layers] - - ocean_mask = bathymetry.copy(deep=True).depth.where( - bathymetry.depth <= min_depth, 1 - ) + ## Make a land mask based on the bathymetry + ocean_mask = xr.where(bathymetry.depth <= 0, 0, 1) land_mask = np.abs(ocean_mask - 1) + ## REMOVE INLAND LAKES + print("done. Filling in inland lakes and channels... ", end="") + changed = True ## keeps track of whether solution has converged or not forward = True ## only useful for iterating through diagonal channel removal. Means iteration goes SW -> NE @@ -1494,20 +2174,22 @@ def tidy_bathymetry( bathymetry["depth"] *= self.ocean_mask + ## Now, any points in the bathymetry that are shallower than minimum depth are set to minimum depth. + ## This preserves the true land/ocean mask. + bathymetry["depth"] = bathymetry["depth"].where(bathymetry["depth"] > 0, np.nan) bathymetry["depth"] = bathymetry["depth"].where( - bathymetry["depth"] != 0, np.nan - ) - - bathymetry.expand_dims({"ntiles": 1}).to_netcdf( - self.mom_input_dir / "bathymetry.nc", - mode="w", - encoding={"depth": {"_FillValue": None}}, + ~(bathymetry.depth <= self.minimum_depth), self.minimum_depth + 0.1 ) - print("done.") - self.bathymetry = bathymetry + if write_to_file: + bathymetry.expand_dims({"ntiles": 1}).to_netcdf( + self.mom_input_dir / "bathymetry.nc", + mode="w", + encoding={"depth": {"_FillValue": None}}, + ) + return bathymetry - def FRE_tools(self, layout=None): + def run_FRE_tools(self, layout=None): """A wrapper for FRE Tools ``check_mask``, ``make_solo_mosaic``, and ``make_quick_mosaic``. User provides processor ``layout`` tuple of processing units. """ @@ -1525,7 +2207,7 @@ def FRE_tools(self, layout=None): print( "OUTPUT FROM MAKE SOLO MOSAIC:", subprocess.run( - str(self.toolpath_dir / "make_solo_mosaic/make_solo_mosaic") + str(self.fre_tools_dir / "make_solo_mosaic/make_solo_mosaic") + " --num_tiles 1 --dir . --mosaic_name ocean_mosaic --tile_file hgrid.nc", shell=True, cwd=self.mom_input_dir, @@ -1536,7 +2218,7 @@ def FRE_tools(self, layout=None): print( "OUTPUT FROM QUICK MOSAIC:", subprocess.run( - str(self.toolpath_dir / "make_quick_mosaic/make_quick_mosaic") + str(self.fre_tools_dir / "make_quick_mosaic/make_quick_mosaic") + " --input_mosaic ocean_mosaic.nc --mosaic_name grid_spec --ocean_topog bathymetry.nc", shell=True, cwd=self.mom_input_dir, @@ -1545,9 +2227,9 @@ def FRE_tools(self, layout=None): ) if layout != None: - self.cpu_layout(layout) + self.configure_cpu_layout(layout) - def cpu_layout(self, layout): + def configure_cpu_layout(self, layout): """ Wrapper for the ``check_mask`` function of GFDL's FRE Tools. User provides processor ``layout`` tuple of processing units. @@ -1556,7 +2238,7 @@ def cpu_layout(self, layout): print( "OUTPUT FROM CHECK MASK:\n\n", subprocess.run( - str(self.toolpath_dir / "check_mask/check_mask") + str(self.fre_tools_dir / "check_mask/check_mask") + f" --grid_file ocean_mosaic.nc --ocean_topog bathymetry.nc --layout {layout[0]},{layout[1]} --halo 4", shell=True, cwd=self.mom_input_dir, @@ -1570,12 +2252,13 @@ def setup_run_directory( surface_forcing=None, using_payu=False, overwrite=False, + with_tides=False, ): """ Set up the run directory for MOM6. Either copy a pre-made set of files, or modify existing files in the 'rundir' directory for the experiment. - Args: + Arguments: surface_forcing (Optional[str]): Specify the choice of surface forcing, one of: ``'jra'`` or ``'era5'``. If not prescribed then constant fluxes are used. using_payu (Optional[bool]): Whether or not to use payu (https://github.com/payu-org/payu) @@ -1588,33 +2271,41 @@ def setup_run_directory( ## Get the path to the regional_mom package on this computer premade_rundir_path = Path( - importlib.resources.files("regional_mom6") / "demos/premade_run_directories" + importlib.resources.files("regional_mom6") + / "demos" + / "premade_run_directories" ) + if not premade_rundir_path.exists(): print("Could not find premade run directories at ", premade_rundir_path) print( - "Perhaps the package was imported directly rather than installed with conda. Checking if this is the case... " + "Perhaps the package was imported directly rather than installed with conda. Checking if this is the case... ", + end="", ) premade_rundir_path = Path( importlib.resources.files("regional_mom6").parent - / "demos/premade_run_directories" + / "demos" + / "premade_run_directories" ) if not premade_rundir_path.exists(): raise ValueError( f"Cannot find the premade run directory files at {premade_rundir_path} either.\n\n" + "There may be an issue with package installation. Check that the `premade_run_directory` folder is present in one of these two locations" ) + else: + print("Found run files. Continuing...") # Define the locations of the directories we'll copy files across from. Base contains most of the files, and overwrite replaces files in the base directory. - base_run_dir = premade_rundir_path / "common_files" + base_run_dir = Path(premade_rundir_path / "common_files") if not premade_rundir_path.exists(): raise ValueError( f"Cannot find the premade run directory files at {premade_rundir_path}.\n\n" + "These files missing might be indicating an error during the package installation!" ) if surface_forcing: - overwrite_run_dir = premade_rundir_path / f"{surface_forcing}_surface" + overwrite_run_dir = Path(premade_rundir_path / f"{surface_forcing}_surface") + if not overwrite_run_dir.exists(): available = [x for x in premade_rundir_path.iterdir() if x.is_dir()] raise ValueError( @@ -1624,6 +2315,18 @@ def setup_run_directory( ## In case there is additional forcing (e.g., tides) then we need to modify the run dir to include the additional forcing. overwrite_run_dir = False + # Check if we can implement tides + if with_tides: + tidal_files_exist = any(Path(self.mom_input_dir).rglob("tu*")) + + if not tidal_files_exist: + raise ValueError( + "No files with 'tu' in their names found in the forcing or input directory. If you meant to use tides, please run the setup_tides_rectangle_boundaries method first. That does output some tidal files." + ) + + # Set local var + ncpus = None + # 3 different cases to handle: # 1. User is creating a new run directory from scratch. Here we copy across all files and modify. # 2. User has already created a run directory, and wants to modify it. Here we only modify the MOM_layout file. @@ -1632,8 +2335,8 @@ def setup_run_directory( if not overwrite: for file in base_run_dir.glob( "*" - ): ## copy each file individually if it doesn't already exist OR overwrite = True - if not os.path.exists(self.mom_run_dir / file.name): + ): ## copy each file individually if it doesn't already exist + if not (self.mom_run_dir / file.name).exists(): ## Check whether this file exists in an override directory or not if ( overwrite_run_dir != False @@ -1645,7 +2348,7 @@ def setup_run_directory( else: shutil.copytree(base_run_dir, self.mom_run_dir, dirs_exist_ok=True) if overwrite_run_dir != False: - shutil.copy(base_run_dir / file, self.mom_run_dir) + shutil.copytree(base_run_dir, self.mom_run_dir, dirs_exist_ok=True) ## Make symlinks between run and input directories inputdir_in_rundir = self.mom_run_dir / "inputdir" @@ -1678,52 +2381,172 @@ def setup_run_directory( print( f"Mask table {p.name} read. Using this to infer the cpu layout {layout}, total masked out cells {masked}, and total number of CPUs {ncpus}." ) - + # Case where there's no mask table. Either because user hasn't run FRE tools, or because the domain is mostly water. if mask_table == None: - if self.layout == None: - raise AttributeError( - "No mask table found, and the cpu layout has not been set. At least one of these is requiret to set up the experiment." - ) - print( - f"No mask table found, but the cpu layout has been set to {self.layout} This suggests the domain is mostly water, so there are " - + "no `non compute` cells that are entirely land. If this doesn't seem right, " - + "ensure you've already run the `FRE_tools` method which sets up the cpu mask table. Keep an eye on any errors that might print while" - + "the FRE tools (which run C++ in the background) are running." - ) # Here we define a local copy of the layout just for use within this function. # This prevents the layout from being overwritten in the main class in case # in case the user accidentally loads in the wrong mask table. layout = self.layout - ncpus = layout[0] * layout[1] + if layout == None: + print( + "WARNING: No mask table found, and the cpu layout has not been set. \nAt least one of these is requiret to set up the experiment if you're running MOM6 standalone with the FMS coupler. \nIf you're running within CESM, ignore this message." + ) + else: + print( + f"No mask table found, but the cpu layout has been set to {self.layout} This suggests the domain is mostly water, so there are " + + "no `non compute` cells that are entirely land. If this doesn't seem right, " + + "ensure you've already run the `FRE_tools` method which sets up the cpu mask table. Keep an eye on any errors that might print while" + + "the FRE tools (which run C++ in the background) are running." + ) - print("Number of CPUs required: ", ncpus) + ncpus = layout[0] * layout[1] + print("Number of CPUs required: ", ncpus) - ## Modify the input namelists to give the correct layouts + ## Modify the MOM_layout file to have correct horizontal dimensions and CPU layout # TODO Re-implement with package that works for this file type? or at least tidy up code - with open(self.mom_run_dir / "MOM_layout", "r") as file: - lines = file.readlines() - for jj in range(len(lines)): - if "MASKTABLE" in lines[jj]: - if mask_table != None: - lines[jj] = f'MASKTABLE = "{mask_table}"\n' - else: - lines[jj] = "# MASKTABLE = no mask table" - if "LAYOUT =" in lines[jj] and "IO" not in lines[jj]: - lines[jj] = f"LAYOUT = {layout[1]},{layout[0]}\n" + MOM_layout_dict = self.read_MOM_file_as_dict("MOM_layout") + if "MASKTABLE" in MOM_layout_dict: + MOM_layout_dict["MASKTABLE"]["value"] = ( + mask_table or " # MASKTABLE = no mask table" + ) + if ( + "LAYOUT" in MOM_layout_dict + and "IO_Layout" not in MOM_layout_dict + and layout != None + ): + MOM_layout_dict["LAYOUT"]["value"] = str(layout[1]) + "," + str(layout[0]) + if "NIGLOBAL" in MOM_layout_dict: + MOM_layout_dict["NIGLOBAL"]["value"] = self.hgrid.nx.shape[0] // 2 + if "NJGLOBAL" in MOM_layout_dict: + MOM_layout_dict["NJGLOBAL"]["value"] = self.hgrid.ny.shape[0] // 2 - if "NIGLOBAL" in lines[jj]: - lines[jj] = f"NIGLOBAL = {self.hgrid.nx.shape[0]//2}\n" + MOM_input_dict = self.read_MOM_file_as_dict("MOM_input") + MOM_override_dict = self.read_MOM_file_as_dict("MOM_override") + # The number of boundaries is reflected in the number of segments setup in setup_ocean_state_boundary under expt.segments. + # The setup_tides_boundaries function currently only works with rectangular grids amd sets up 4 segments, but DOESN"T save them to expt.segments. + # Therefore, we can use expt.segments to determine how many segments we need for MOM_input. We can fill the empty segments with a empty string to make sure it is overriden correctly. - if "NJGLOBAL" in lines[jj]: - lines[jj] = f"NJGLOBAL = {self.hgrid.ny.shape[0]//2}\n" + # Others + MOM_override_dict["MINIMUM_DEPTH"]["value"] = float(self.minimum_depth) + MOM_override_dict["NK"]["value"] = len(self.vgrid.zl.values) - with open(self.mom_run_dir / "MOM_layout", "w") as f: - f.writelines(lines) + # OBC Adjustments + + # Delete MOM_input OBC stuff that is indexed because we want them only in MOM_override. + print( + "Deleting indexed OBC keys from MOM_input_dict in case we have a different number of segments" + ) + keys_to_delete = [key for key in MOM_input_dict if "_SEGMENT_00" in key] + for key in keys_to_delete: + del MOM_input_dict[key] + + # Define number of OBC segments + MOM_override_dict["OBC_NUMBER_OF_SEGMENTS"]["value"] = len( + self.boundaries + ) # This means that each SEGMENT_00{num} has to be configured to point to the right file, which based on our other functions needs to be specified. + + # More OBC Consts + MOM_override_dict["OBC_FREESLIP_VORTICITY"]["value"] = "False" + MOM_override_dict["OBC_FREESLIP_STRAIN"]["value"] = "False" + MOM_override_dict["OBC_COMPUTED_VORTICITY"]["value"] = "True" + MOM_override_dict["OBC_COMPUTED_STRAIN"]["value"] = "True" + MOM_override_dict["OBC_ZERO_BIHARMONIC"]["value"] = "True" + MOM_override_dict["OBC_TRACER_RESERVOIR_LENGTH_SCALE_OUT"]["value"] = "3.0E+04" + MOM_override_dict["OBC_TRACER_RESERVOIR_LENGTH_SCALE_IN"]["value"] = "3000.0" + MOM_override_dict["BRUSHCUTTER_MODE"]["value"] = "True" + + # Define Specific Segments + for seg in self.boundaries: + ind_seg = self.find_MOM6_rectangular_orientation(seg) + key_start = f"OBC_SEGMENT_00{ind_seg}" + ## Position and Config + key_POSITION = key_start + + rect_MOM6_index_dir = { + "south": '"J=0,I=0:N', + "north": '"J=N,I=N:0', + "east": '"I=N,J=0:N', + "west": '"I=0,J=N:0', + } + index_str = rect_MOM6_index_dir[seg] + + MOM_override_dict[key_POSITION]["value"] = ( + index_str + ',FLATHER,ORLANSKI,NUDGED,ORLANSKI_TAN,NUDGED_TAN"' + ) + + # Nudging Key + key_NUDGING = key_start + "_VELOCITY_NUDGING_TIMESCALES" + MOM_override_dict[key_NUDGING]["value"] = "0.3, 360.0" + + # Data Key + key_DATA = key_start + "_DATA" + file_num_obc = str( + self.find_MOM6_rectangular_orientation(seg) + ) # 1,2,3,4 for rectangular boundaries, BUT if we have less than 4 segments we use the index to specific the number, but keep filenames as if we had four boundaries + + obc_string = ( + f'"U=file:forcing_obc_segment_00{file_num_obc}.nc(u),' + f"V=file:forcing_obc_segment_00{file_num_obc}.nc(v)," + f"SSH=file:forcing_obc_segment_00{file_num_obc}.nc(eta)," + f"TEMP=file:forcing_obc_segment_00{file_num_obc}.nc(temp)," + f"SALT=file:forcing_obc_segment_00{file_num_obc}.nc(salt)" + ) + MOM_override_dict[key_DATA]["value"] = obc_string + if with_tides: + tides_addition = ( + f",Uamp=file:tu_segment_00{file_num_obc}.nc(uamp)," + f"Uphase=file:tu_segment_00{file_num_obc}.nc(uphase)," + f"Vamp=file:tu_segment_00{file_num_obc}.nc(vamp)," + f"Vphase=file:tu_segment_00{file_num_obc}.nc(vphase)," + f"SSHamp=file:tz_segment_00{file_num_obc}.nc(zamp)," + f'SSHphase=file:tz_segment_00{file_num_obc}.nc(zphase)"' + ) + MOM_override_dict[key_DATA]["value"] = ( + MOM_override_dict[key_DATA]["value"] + tides_addition + ) + else: + MOM_override_dict[key_DATA]["value"] = ( + MOM_override_dict[key_DATA]["value"] + '"' + ) + if type(self.date_range[0]) == str: + self.date_range[0] = dt.datetime.strptime( + self.date_range[0], "%Y-%m-%d %H:%M:%S" + ) + self.date_range[1] = dt.datetime.strptime( + self.date_range[1], "%Y-%m-%d %H:%M:%S" + ) + # Tides OBC adjustments + if with_tides: + + # Include internal tide forcing + MOM_override_dict["TIDES"]["value"] = "True" + + # OBC tides + MOM_override_dict["OBC_TIDE_ADD_EQ_PHASE"]["value"] = "True" + MOM_override_dict["OBC_TIDE_N_CONSTITUENTS"]["value"] = len( + self.tidal_constituents + ) + MOM_override_dict["OBC_TIDE_CONSTITUENTS"]["value"] = ( + '"' + ", ".join(self.tidal_constituents) + '"' + ) + MOM_override_dict["OBC_TIDE_REF_DATE"]["value"] = self.date_range[ + 0 + ].strftime("%Y, %m, %d") + + for key, val in MOM_override_dict.items(): + if isinstance(val, dict) and key != "original": + MOM_override_dict[key]["override"] = True + self.write_MOM_file(MOM_input_dict) + self.write_MOM_file(MOM_override_dict) + self.write_MOM_file(MOM_layout_dict) ## If using payu to run the model, create a payu configuration file if not using_payu and os.path.exists(f"{self.mom_run_dir}/config.yaml"): os.remove(f"{self.mom_run_dir}/config.yaml") - + elif ncpus == None: + print( + "WARNING: Layout has not been set! Cannot create payu configuration file. Run the FRE_tools first." + ) else: with open(f"{self.mom_run_dir}/config.yaml", "r") as file: lines = file.readlines() @@ -1755,6 +2578,211 @@ def setup_run_directory( ] nml.write(self.mom_run_dir / "input.nml", force=True) + # Edit Diag Table Date + # Read the file + with open(self.mom_run_dir / "diag_table", "r") as file: + lines = file.readlines() + + # The date is the second line + lines[1] = self.date_range[0].strftime("%Y %-m %-d %-H %-M %-S\n") + + # Write the file + with open(self.mom_run_dir / "diag_table", "w") as file: + file.writelines(lines) + + return + + def change_MOM_parameter( + self, param_name, param_value=None, comment=None, override=True, delete=False + ): + """ + *Requires already copied MOM parameter files in the run directory* + Change a parameter in the MOM_input or MOM_override file. Returns original value if there was one. + If delete is specified, ONLY MOM_override version will be deleted. Deleting from MOM_input is not safe. + If the parameter does not exist, it will be added to the file. if delete is set to True, the parameter will be removed. + Arguments: + param_name (str): + Parameter name we are working with + param_value (Optional[str]): + New Assigned Value + comment (Optional[str]): + Any comment to add + delete (Optional[bool]): + Whether to delete the specified param_name + + """ + if not delete and param_value is None: + raise ValueError( + "If not deleting a parameter, you must specify a new value for it." + ) + + MOM_override_dict = self.read_MOM_file_as_dict("MOM_override") + original_val = "No original val" + if not delete: + + if param_name in MOM_override_dict.keys(): + original_val = MOM_override_dict[param_name]["value"] + print( + "This parameter {} is being replaced from {} to {} in MOM_override".format( + param_name, original_val, param_value + ) + ) + + MOM_override_dict[param_name]["value"] = param_value + MOM_override_dict[param_name]["comment"] = comment + MOM_override_dict[param_name]["override"] = override + else: + if param_name in MOM_override_dict.keys(): + original_val = MOM_override_dict[param_name]["value"] + print("Deleting parameter {} from MOM_override".format(param_name)) + del MOM_override_dict[param_name] + else: + print( + "Key to be deleted {} was not in MOM_override to begin with.".format( + param_name + ) + ) + self.write_MOM_file(MOM_override_dict) + return original_val + + def read_MOM_file_as_dict(self, filename): + """ + Read the MOM_input file and return a dictionary of the variables and their values. + """ + + # Default information for each parameter + default_layout = {"value": None, "override": False, "comment": None} + + if not os.path.exists(Path(self.mom_run_dir / filename)): + raise ValueError( + f"File {filename} does not exist in the run directory {self.mom_run_dir}" + ) + with open(Path(self.mom_run_dir / filename), "r") as file: + lines = file.readlines() + + # Set the default initialization for a new key + MOM_file_dict = defaultdict(lambda: copy.deepcopy(default_layout)) + MOM_file_dict["filename"] = filename + dlc = copy.deepcopy(default_layout) + for jj in range(len(lines)): + if "=" in lines[jj] and not "===" in lines[jj]: + split = lines[jj].split("=", 1) + var = split[0] + value = split[1] + if "#override" in var: + var = var.split("#override")[1].strip() + dlc["override"] = True + else: + dlc["override"] = False + if "!" in value: + dlc["comment"] = value.split("!")[1] + value = value.split("!")[0].strip() # Remove Comments + dlc["value"] = str(value) + else: + dlc["value"] = str(value.strip()) + dlc["comment"] = None + + MOM_file_dict[var.strip()] = copy.deepcopy(dlc) + + # Save a copy of the original dictionary + MOM_file_dict["original"] = copy.deepcopy(MOM_file_dict) + return MOM_file_dict + + def write_MOM_file(self, MOM_file_dict): + """ + Write the MOM_input file from a dictionary of variables and their values. Does not support removing fields. + """ + # Replace specific variable values + original_MOM_file_dict = MOM_file_dict.pop("original") + with open(Path(self.mom_run_dir / MOM_file_dict["filename"]), "r") as file: + lines = file.readlines() + for jj in range(len(lines)): + if "=" in lines[jj] and not "===" in lines[jj]: + var = lines[jj].split("=", 1)[0].strip() + if "#override" in var: + var = var.replace("#override", "") + var = var.strip() + else: + # As in there wasn't an override before but we want one + if MOM_file_dict[var]["override"]: + lines[jj] = "#override " + lines[jj] + print("Added override to variable " + var + "!") + if var in MOM_file_dict.keys() and ( + str(MOM_file_dict[var]["value"]) + ) != str(original_MOM_file_dict[var]["value"]): + lines[jj] = lines[jj].replace( + str(original_MOM_file_dict[var]["value"]), + str(MOM_file_dict[var]["value"]), + ) + if original_MOM_file_dict[var]["comment"] != None: + lines[jj] = lines[jj].replace( + original_MOM_file_dict[var]["comment"], + str(MOM_file_dict[var]["comment"]), + ) + else: + lines[jj] = ( + lines[jj].replace("\n", "") + + " !" + + str(MOM_file_dict[var]["comment"]) + + "\n" + ) + + print( + "Changed " + + str(var) + + " from " + + str(original_MOM_file_dict[var]["value"]) + + " to " + + str(MOM_file_dict[var]["value"]) + + "in {}!".format(str(MOM_file_dict["filename"])) + ) + + # Add new fields + lines.append("! === Added with regional-mom6 ===\n") + for key in MOM_file_dict.keys(): + if key not in original_MOM_file_dict.keys(): + if MOM_file_dict[key]["override"]: + lines.append( + f"#override {key} = {MOM_file_dict[key]['value']} !{MOM_file_dict[key]['comment']}\n" + ) + else: + lines.append( + f"{key} = {MOM_file_dict[key]['value']} !{MOM_file_dict[key]['comment']}\n" + ) + print( + "Added", + key, + "to", + MOM_file_dict["filename"], + "with value", + MOM_file_dict[key], + ) + + # Check any fields removed + for key in original_MOM_file_dict.keys(): + if key not in MOM_file_dict.keys(): + search_words = [ + key, + original_MOM_file_dict[key]["value"], + original_MOM_file_dict[key]["comment"], + ] + lines = [ + line + for line in lines + if not all(word in line for word in search_words) + ] + print( + "Removed", + key, + "in", + MOM_file_dict["filename"], + "with value", + original_MOM_file_dict[key], + ) + + with open(Path(self.mom_run_dir / MOM_file_dict["filename"]), "w") as f: + f.writelines(lines) + def setup_era5(self, era5_path): """ Setup the ERA5 forcing files for the experiment. This assumes that @@ -1762,7 +2790,7 @@ def setup_era5(self, era5_path): We need the following fields: "2t", "10u", "10v", "sp", "2d", "msdwswrf", "msdwlwrf", "lsrr", and "crr". - Args: + Arguments: era5_path (str): Path to the ERA5 forcing files. Specifically, the single-level reanalysis product. For example, ``'SOMEPATH/era5/single-levels/reanalysis'`` """ @@ -1778,6 +2806,7 @@ def setup_era5(self, era5_path): i for i in range(self.date_range[0].year, self.date_range[1].year + 1) ] # construct a list of all paths for all years to use for open_mfdataset + # paths_per_year = [Path(era5_path / fname / year) for year in years] paths_per_year = [Path(f"{era5_path}/{fname}/{year}/") for year in years] all_files = [] for path in paths_per_year: @@ -1828,7 +2857,7 @@ def setup_era5(self, era5_path): q.q.attrs = {"long_name": "Specific Humidity", "units": "kg/kg"} q.to_netcdf( - f"{self.mom_input_dir}/forcing/q_ERA5.nc", + f"{self.mom_input_dir}/q_ERA5.nc", unlimited_dims="time", encoding={"q": {"dtype": "double"}}, ) @@ -1843,7 +2872,7 @@ def setup_era5(self, era5_path): "units": "kg m**-2 s**-1", } trr.to_netcdf( - f"{self.mom_input_dir}/forcing/trr_ERA5.nc", + f"{self.mom_input_dir}/trr_ERA5.nc", unlimited_dims="time", encoding={"trr": {"dtype": "double"}}, ) @@ -1853,7 +2882,7 @@ def setup_era5(self, era5_path): pass else: rawdata[fname].to_netcdf( - f"{self.mom_input_dir}/forcing/{fname}_ERA5.nc", + f"{self.mom_input_dir}/{fname}_ERA5.nc", unlimited_dims="time", encoding={vname: {"dtype": "double"}}, ) @@ -1861,8 +2890,8 @@ def setup_era5(self, era5_path): class segment: """ - Class to turn raw boundary segment data into MOM6 boundary - segments. + Class to turn raw boundary and tidal segment data into MOM6 boundary + and tidal segments. Boundary segments should only contain the necessary data for that segment. No horizontal chunking is done here, so big fat segments @@ -1875,7 +2904,7 @@ class segment: Note: Only supports z-star (z*) vertical coordinate. - Args: + Arguments: hgrid (xarray.Dataset): The horizontal grid used for domain. infile (Union[str, Path]): Path to the raw, unprocessed boundary segment. outfolder (Union[str, Path]): Path to folder where the model inputs will @@ -1892,11 +2921,6 @@ class segment: Either ``'A'`` (default), ``'B'``, or ``'C'``. time_units (str): The units used by the raw forcing files, e.g., ``hours``, ``days`` (default). - tidal_constituents (Optional[int]): An integer determining the number of tidal - constituents to be included from the list: *M*:sub:`2`, *S*:sub:`2`, *N*:sub:`2`, - *K*:sub:`2`, *K*:sub:`1`, *O*:sub:`2`, *P*:sub:`1`, *Q*:sub:`1`, *Mm*, - *Mf*, and *M*:sub:`4`. For example, specifying ``1`` only includes *M*:sub:`2`; - specifying ``2`` includes *M*:sub:`2` and *S*:sub:`2`, etc. Default: ``None``. repeat_year_forcing (Optional[bool]): When ``True`` the experiment runs with repeat-year forcing. When ``False`` (default) then inter-annual forcing is used. """ @@ -1911,15 +2935,20 @@ def __init__( segment_name, orientation, startdate, + bathymetry_path=None, arakawa_grid="A", time_units="days", - tidal_constituents=None, repeat_year_forcing=False, ): ## Store coordinate names - if arakawa_grid == "A": - self.x = varnames["x"] - self.y = varnames["y"] + if arakawa_grid == "A" and infile is not None: + try: + self.x = varnames["x"] + self.y = varnames["y"] + ## In case user continues using T point names for A grid + except: + self.x = varnames["xh"] + self.y = varnames["yh"] elif arakawa_grid in ("B", "C"): self.xq = varnames["xq"] @@ -1928,15 +2957,17 @@ def __init__( self.yh = varnames["yh"] ## Store velocity names - self.u = varnames["u"] - self.v = varnames["v"] - self.z = varnames["zl"] - self.eta = varnames["eta"] - self.time = varnames["time"] + if infile is not None: + self.u = varnames["u"] + self.v = varnames["v"] + self.z = varnames["zl"] + self.eta = varnames["eta"] + self.time = varnames["time"] self.startdate = startdate ## Store tracer names - self.tracers = varnames["tracers"] + if infile is not None: + self.tracers = varnames["tracers"] self.time_units = time_units ## Store other data @@ -1954,110 +2985,95 @@ def __init__( self.infile = infile self.outfolder = outfolder self.hgrid = hgrid + try: + self.bathymetry = xr.open_dataset(bathymetry_path) + except: + self.bathymetry = None self.segment_name = segment_name - self.tidal_constituents = tidal_constituents self.repeat_year_forcing = repeat_year_forcing - def rectangular_brushcut(self): - """ - Cut out and interpolate tracers. ``rectangular_brushcut`` assumes that the boundary - is a simple Northern, Southern, Eastern, or Western boundary. + def regrid_velocity_tracers(self, rotational_method=rot.RotationMethod.EXPAND_GRID): """ - if self.orientation == "north": - self.hgrid_seg = self.hgrid.isel(nyp=[-1]) - self.perpendicular = "ny" - self.parallel = "nx" - - if self.orientation == "south": - self.hgrid_seg = self.hgrid.isel(nyp=[0]) - self.perpendicular = "ny" - self.parallel = "nx" - - if self.orientation == "east": - self.hgrid_seg = self.hgrid.isel(nxp=[-1]) - self.perpendicular = "nx" - self.parallel = "ny" - - if self.orientation == "west": - self.hgrid_seg = self.hgrid.isel(nxp=[0]) - self.perpendicular = "nx" - self.parallel = "ny" - - ## Need to keep track of which axis the 'main' coordinate corresponds to for later on when re-adding the 'secondary' axis - if self.perpendicular == "ny": - self.axis_to_expand = 2 - else: - self.axis_to_expand = 3 + Cut out and interpolate the velocities and tracers. - ## Grid for interpolating our fields - self.interp_grid = xr.Dataset( - { - "lat": ( - [f"{self.parallel}_{self.segment_name}"], - self.hgrid_seg.y.squeeze().data, - ), - "lon": ( - [f"{self.parallel}_{self.segment_name}"], - self.hgrid_seg.x.squeeze().data, - ), - } - ).set_coords(["lat", "lon"]) + Arguments: + rotational_method (rot.RotationMethod): The method to use for rotation of the velocities. Currently, the default method, ``EXPAND_GRID``, works even with non-rotated grids. + """ rawseg = xr.open_dataset(self.infile, decode_times=False, engine="netcdf4") + coords = rgd.coords(self.hgrid, self.orientation, self.segment_name) + if self.arakawa_grid == "A": + rawseg = rawseg.rename({self.x: "lon", self.y: "lat"}) - ## In this case velocities and tracers all on same points - regridder = xe.Regridder( + # In this case velocities and tracers all on same points + regridder = rgd.create_regridder( rawseg[self.u], - self.interp_grid, - "bilinear", - locstream_out=True, - reuse_weights=False, - filename=self.outfolder + coords, + self.outfolder / f"weights/bilinear_velocity_weights_{self.orientation}.nc", + method="bilinear", ) - segment_out = xr.merge( - [ - regridder( - rawseg[ - [self.u, self.v, self.eta] - + [self.tracers[i] for i in self.tracers] - ] - ) + regridded = regridder( + rawseg[ + [self.u, self.v, self.eta] + [self.tracers[i] for i in self.tracers] ] ) + ## Angle Calculation & Rotation + rotated_u, rotated_v = rotate( + regridded[self.u], + regridded[self.v], + radian_angle=np.radians( + rot.get_rotation_angle( + rotational_method, self.hgrid, orientation=self.orientation + ).values + ), + ) + + rotated_ds = xr.Dataset( + { + self.u: rotated_u, + self.v: rotated_v, + } + ) + segment_out = xr.merge([rotated_ds, regridded.drop_vars([self.u, self.v])]) + if self.arakawa_grid == "B": ## All tracers on one grid, all velocities on another - regridder_velocity = xe.Regridder( + regridder_velocity = rgd.create_regridder( rawseg[self.u].rename({self.xq: "lon", self.yq: "lat"}), - self.interp_grid, - "bilinear", - locstream_out=True, - reuse_weights=False, - filename=self.outfolder + coords, + self.outfolder / f"weights/bilinear_velocity_weights_{self.orientation}.nc", ) - - regridder_tracer = xe.Regridder( + regridder_tracer = rgd.create_regridder( rawseg[self.tracers["salt"]].rename({self.xh: "lon", self.yh: "lat"}), - self.interp_grid, - "bilinear", - locstream_out=True, - reuse_weights=False, - filename=self.outfolder + coords, + self.outfolder / f"weights/bilinear_tracer_weights_{self.orientation}.nc", ) + velocities_out = regridder_velocity( + rawseg[[self.u, self.v]].rename({self.xq: "lon", self.yq: "lat"}) + ) + + # See explanation of the rotational methods in the A grid section + velocities_out["u"], velocities_out["v"] = rotate( + velocities_out["u"], + velocities_out["v"], + radian_angle=np.radians( + rot.get_rotation_angle( + rotational_method, self.hgrid, orientation=self.orientation + ).values + ), + ) + segment_out = xr.merge( [ - regridder_velocity( - rawseg[[self.u, self.v]].rename( - {self.xq: "lon", self.yq: "lat"} - ) - ), + velocities_out, regridder_tracer( rawseg[ [self.eta] + [self.tracers[i] for i in self.tracers] @@ -2068,40 +3084,50 @@ def rectangular_brushcut(self): if self.arakawa_grid == "C": ## All tracers on one grid, all velocities on another - regridder_uvelocity = xe.Regridder( + regridder_uvelocity = rgd.create_regridder( rawseg[self.u].rename({self.xq: "lon", self.yh: "lat"}), - self.interp_grid, - "bilinear", - locstream_out=True, - reuse_weights=False, - filename=self.outfolder + coords, + self.outfolder / f"weights/bilinear_uvelocity_weights_{self.orientation}.nc", ) - regridder_vvelocity = xe.Regridder( + regridder_vvelocity = rgd.create_regridder( rawseg[self.v].rename({self.xh: "lon", self.yq: "lat"}), - self.interp_grid, - "bilinear", - locstream_out=True, - reuse_weights=False, - filename=self.outfolder + coords, + self.outfolder / f"weights/bilinear_vvelocity_weights_{self.orientation}.nc", ) - regridder_tracer = xe.Regridder( + regridder_tracer = rgd.create_regridder( rawseg[self.tracers["salt"]].rename({self.xh: "lon", self.yh: "lat"}), - self.interp_grid, - "bilinear", - locstream_out=True, - reuse_weights=False, - filename=self.outfolder + coords, + self.outfolder / f"weights/bilinear_tracer_weights_{self.orientation}.nc", ) + regridded_u = regridder_uvelocity(rawseg[[self.u]]) + regridded_v = regridder_vvelocity(rawseg[[self.v]]) + + # See explanation of the rotational methods in the A grid section + rotated_u, rotated_v = rotate( + regridded_u, + regridded_v, + radian_angle=np.radians( + rot.get_rotation_angle( + rotational_method, self.hgrid, orientation=self.orientation + ).values + ), + ) + + rotated_ds = xr.Dataset( + { + self.u: rotated_u, + self.v: rotated_v, + } + ) segment_out = xr.merge( [ - regridder_vvelocity(rawseg[[self.v]]), - regridder_uvelocity(rawseg[[self.u]]), + rotated_ds, regridder_tracer( rawseg[[self.eta] + [self.tracers[i] for i in self.tracers]] ), @@ -2110,9 +3136,10 @@ def rectangular_brushcut(self): ## segment out now contains our interpolated boundary. ## Now, we need to fix up all the metadata and save + segment_out = segment_out.rename( + {"lon": f"lon_{self.segment_name}", "lat": f"lat_{self.segment_name}"} + ) - del segment_out["lon"] - del segment_out["lat"] ## Convert temperatures to celsius # use pint if ( np.nanmin(segment_out[self.tracers["temp"]].isel({self.time: 0, self.z: 0})) @@ -2122,44 +3149,29 @@ def rectangular_brushcut(self): segment_out[self.tracers["temp"]].attrs["units"] = "degrees Celsius" # fill in NaNs - segment_out = ( - segment_out.ffill(self.z) - .interpolate_na(f"{self.parallel}_{self.segment_name}") - .ffill(f"{self.parallel}_{self.segment_name}") - .bfill(f"{self.parallel}_{self.segment_name}") + # segment_out = rgd.fill_missing_data(segment_out, self.z) + segment_out = rgd.fill_missing_data( + segment_out, + xdim=f"{coords.attrs['parallel']}_{self.segment_name}", + zdim=self.z, ) - time = np.arange( - 0, #! Indexing everything from start of experiment = simple but maybe counterintutive? - segment_out[self.time].shape[ - 0 - ], ## Time is indexed from start date of window - dtype=float, + times = xr.DataArray( + np.arange( + 0, #! Indexing everything from start of experiment = simple but maybe counterintutive? + segment_out[self.time].shape[ + 0 + ], ## Time is indexed from start date of window + dtype=float, + ), # Import pandas for this shouldn't be a big deal b/c it's already kinda required somewhere deep in some tree. + dims=["time"], ) - - segment_out = segment_out.assign_coords({"time": time}) + # This to change the time coordinate. + segment_out = rgd.add_or_update_time_dim(segment_out, times) segment_out.time.attrs = { "calendar": "julian", "units": f"{self.time_units} since {self.startdate}", } - # Dictionary we built for encoding the netcdf at end - encoding_dict = { - "time": { - "dtype": "double", - }, - f"nx_{self.segment_name}": { - "dtype": "int32", - }, - f"ny_{self.segment_name}": { - "dtype": "int32", - }, - } - - ### Generate the dz variable; needs to be in layer thicknesses - dz = segment_out[self.z].diff(self.z) - dz.name = "dz" - dz = xr.concat([dz, dz[-1]], dim=self.z) - # Here, keep in mind that 'var' keeps track of the mom6 variable names we want, and self.tracers[var] # will return the name of the variable from the original data @@ -2178,99 +3190,302 @@ def rectangular_brushcut(self): ## Rename each variable in dataset segment_out = segment_out.rename({allfields[var]: v}) - ## Rename vertical coordinate for this variable - segment_out[f"{var}_{self.segment_name}"] = segment_out[ - f"{var}_{self.segment_name}" - ].rename({self.z: f"nz_{self.segment_name}_{var}"}) - - ## Replace the old depth coordinates with incremental integers - segment_out[f"nz_{self.segment_name}_{var}"] = np.arange( - segment_out[f"nz_{self.segment_name}_{var}"].size + segment_out = rgd.vertical_coordinate_encoding( + segment_out, v, self.segment_name, self.z ) - ## Re-add the secondary dimension (even though it represents one value..) - segment_out[v] = segment_out[v].expand_dims( - f"{self.perpendicular}_{self.segment_name}", axis=self.axis_to_expand + segment_out = rgd.add_secondary_dimension( + segment_out, v, coords, self.segment_name ) - ## Add the layer thicknesses - segment_out[f"dz_{v}"] = ( - [ - "time", - f"nz_{v}", - f"ny_{self.segment_name}", - f"nx_{self.segment_name}", - ], - da.broadcast_to( - dz.data[None, :, None, None], - segment_out[v].shape, - chunks=( - 1, - None, - None, - None, - ), ## Chunk in each time, and every 5 vertical layers - ), + segment_out = rgd.generate_layer_thickness( + segment_out, v, self.segment_name, self.z ) - encoding_dict[v] = { - "_FillValue": netCDF4.default_fillvals["f8"], - "zlib": True, - # "chunksizes": tuple(s), - } - encoding_dict[f"dz_{v}"] = { - "_FillValue": netCDF4.default_fillvals["f8"], - "zlib": True, - # "chunksizes": tuple(s), - } - - ## appears to be another variable just with integers?? - encoding_dict[f"nz_{self.segment_name}_{var}"] = {"dtype": "int32"} - ## Treat eta separately since it has no vertical coordinate. Do the same things as for the surface variables above segment_out = segment_out.rename({self.eta: f"eta_{self.segment_name}"}) - encoding_dict[f"eta_{self.segment_name}"] = { - "_FillValue": netCDF4.default_fillvals["f8"], - } - segment_out[f"eta_{self.segment_name}"] = segment_out[ - f"eta_{self.segment_name}" - ].expand_dims( - f"{self.perpendicular}_{self.segment_name}", axis=self.axis_to_expand - 1 + + segment_out = rgd.add_secondary_dimension( + segment_out, f"eta_{self.segment_name}", coords, self.segment_name ) # Overwrite the actual lat/lon values in the dimensions, replace with incrementing integers - segment_out[f"{self.parallel}_{self.segment_name}"] = np.arange( - segment_out[f"{self.parallel}_{self.segment_name}"].size + segment_out[f"{coords.attrs['parallel']}_{self.segment_name}"] = np.arange( + segment_out[f"{coords.attrs['parallel']}_{self.segment_name}"].size + ) + segment_out[f"{coords.attrs['parallel']}_{self.segment_name}"] = np.arange( + segment_out[f"{coords.attrs['parallel']}_{self.segment_name}"].size + ) + segment_out[f"{coords.attrs['perpendicular']}_{self.segment_name}"] = [0] + encoding_dict = { + "time": {"dtype": "double"}, + f"nx_{self.segment_name}": { + "dtype": "int32", + }, + f"ny_{self.segment_name}": { + "dtype": "int32", + }, + } + segment_out = rgd.mask_dataset( + segment_out, + self.hgrid, + self.bathymetry, + self.orientation, + self.segment_name, + ) + encoding_dict = rgd.generate_encoding( + segment_out, + encoding_dict, + default_fill_value=1.0e20, ) - segment_out[f"{self.perpendicular}_{self.segment_name}"] = [0] - # Store actual lat/lon values here as variables rather than coordinates - segment_out[f"lon_{self.segment_name}"] = ( - [f"ny_{self.segment_name}", f"nx_{self.segment_name}"], - self.hgrid_seg.x.data, + segment_out.load().to_netcdf( + self.outfolder / f"forcing_obc_{self.segment_name}.nc", + encoding=encoding_dict, + unlimited_dims="time", ) - segment_out[f"lat_{self.segment_name}"] = ( - [f"ny_{self.segment_name}", f"nx_{self.segment_name}"], - self.hgrid_seg.y.data, + + return segment_out, encoding_dict + + def regrid_tides( + self, + tpxo_v, + tpxo_u, + tpxo_h, + times, + rotational_method=rot.RotationMethod.EXPAND_GRID, + ): + """ + Regrids and interpolates the tidal data for MOM6. Steps include: + + - Read raw tidal data (all constituents) + - Perform minor transformations/conversions + - Regrid the tidal elevation, and tidal velocity + - Encode the output + + Method was inspired by: + Author(s): GFDL, James Simkins, Rob Cermak, and contributors + Year: 2022 + Title: "NWA25: Northwest Atlantic 1/25th Degree MOM6 Simulation" + Type: Python Functions, Source Code + Web Address: https://github.com/jsimkins2/nwa25 + + General Description: + The tidal data functions sourced from the GFDL's code above were changed in the following ways: + + - Converted code for regional-mom6 segment class + - Implemented horizontal subsetting + - Combined all functions of NWA25 into a four function process (in the style of regional-mom6), that is: ``expt.setup_tides_rectangular_boundaries``, ``segment.coords``, ``segment.regrid_tides``, ``segment.encode_tidal_files_and_output``. + + Arguments: + infile_td (str): Raw Tidal File/Dir + tpxo_v, tpxo_u, tpxo_h (xarray.Dataset): Specific adjusted for MOM6 tpxo datasets (Adjusted with :func:`~setup_tides`) + times (pd.DateRange): The start date of our model period + rotational_method (rot.RotationMethod): The method to use for rotation of the velocities. Currently, the default method, EXPAND_GRID, works even with non-rotated grids. + + Returns: + netCDF files: Regridded tidal velocity and elevation files in 'inputdir/forcing' + """ + + # Establish Coords + coords = rgd.coords(self.hgrid, self.orientation, self.segment_name) + + ########## Tidal Elevation: Horizontally interpolate elevation components ############ + regrid = rgd.create_regridder( + tpxo_h[["lon", "lat", "hRe"]], + coords, + Path( + self.outfolder / "forcing" / f"regrid_{self.segment_name}_tidal_elev.nc" + ), ) - # Add units to the lat / lon to keep the `categorize_axis_from_units` checker happy - segment_out[f"lat_{self.segment_name}"].attrs = { - "units": "degrees_north", - } - segment_out[f"lon_{self.segment_name}"].attrs = { - "units": "degrees_east", - } + redest = regrid(tpxo_h[["lon", "lat", "hRe"]]) + imdest = regrid(tpxo_h[["lon", "lat", "hIm"]]) - # If repeat-year forcing, add modulo coordinate - if self.repeat_year_forcing: - segment_out["time"] = segment_out["time"].assign_attrs({"modulo": " "}) + # Fill missing data. + # Need to do this first because complex would get converted to real + redest = rgd.fill_missing_data( + redest, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + redest = redest["hRe"] + imdest = rgd.fill_missing_data( + imdest, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + imdest = imdest["hIm"] + + # Convert complex + cplex = redest + 1j * imdest + + # Convert to real amplitude and phase. + ds_ap = xr.Dataset({f"zamp_{self.segment_name}": np.abs(cplex)}) + + # np.angle doesn't return dataarray + ds_ap[f"zphase_{self.segment_name}"] = ( + ("constituent", f"{coords.attrs['parallel']}_{self.segment_name}"), + -1 * np.angle(cplex), + ) # radians + + # Add time coordinate and transpose so that time is first, + # so that it can be the unlimited dimension + times = xr.DataArray( + pd.date_range( + self.startdate, periods=1 + ), # Import pandas for this shouldn't be a big deal b/c it's already kinda required somewhere deep in some tree. + dims=["time"], + ) - with ProgressBar(): - segment_out.load().to_netcdf( - self.outfolder / f"forcing/forcing_obc_{self.segment_name}.nc", - encoding=encoding_dict, - unlimited_dims="time", - ) + ds_ap = rgd.add_or_update_time_dim(ds_ap, times) + ds_ap = ds_ap.transpose( + "time", "constituent", f"{coords.attrs['parallel']}_{self.segment_name}" + ) - return segment_out, encoding_dict + self.encode_tidal_files_and_output(ds_ap, "tz") + + ########### Regrid Tidal Velocity ###################### + + regrid_u = rgd.create_regridder(tpxo_u[["lon", "lat", "uRe"]], coords) + regrid_v = rgd.create_regridder(tpxo_v[["lon", "lat", "vRe"]], coords) + + # Interpolate each real and imaginary parts to self. + uredest = regrid_u(tpxo_u[["lon", "lat", "uRe"]])["uRe"] + uimdest = regrid_u(tpxo_u[["lon", "lat", "uIm"]])["uIm"] + vredest = regrid_v(tpxo_v[["lon", "lat", "vRe"]])["vRe"] + vimdest = regrid_v(tpxo_v[["lon", "lat", "vIm"]])["vIm"] + + # Fill missing data. + # Need to do this first because complex would get converted to real + uredest = rgd.fill_missing_data( + uredest, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + uimdest = rgd.fill_missing_data( + uimdest, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + vredest = rgd.fill_missing_data( + vredest, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + vimdest = rgd.fill_missing_data( + vimdest, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + + # Convert to complex, remaining separate for u and v. + ucplex = uredest + 1j * uimdest + vcplex = vredest + 1j * vimdest + + # Convert complex u and v to ellipse, + # rotate ellipse from earth-relative to model-relative, + # and convert ellipse back to amplitude and phase. + SEMA, ECC, INC, PHA = ap2ep(ucplex, vcplex) + + # Rotate + INC -= np.radians( + rot.get_rotation_angle( + rotational_method, self.hgrid, orientation=self.orientation + ).data[np.newaxis, :] + ) + + ua, va, up, vp = ep2ap(SEMA, ECC, INC, PHA) + # Convert to real amplitude and phase. + + ds_ap = xr.Dataset( + {f"uamp_{self.segment_name}": ua, f"vamp_{self.segment_name}": va} + ) + # up, vp aren't dataarraysf + ds_ap[f"uphase_{self.segment_name}"] = ( + ("constituent", f"{coords.attrs['parallel']}_{self.segment_name}"), + up, + ) # radians + ds_ap[f"vphase_{self.segment_name}"] = ( + ("constituent", f"{coords.attrs['parallel']}_{self.segment_name}"), + vp, + ) # radians + + times = xr.DataArray( + pd.date_range( + self.startdate, periods=1 + ), # Import pandas for this shouldn't be a big deal b/c it's already kinda required somewhere deep in some tree. + dims=["time"], + ) + ds_ap = rgd.add_or_update_time_dim(ds_ap, times) + ds_ap = ds_ap.transpose( + "time", "constituent", f"{coords.attrs['parallel']}_{self.segment_name}" + ) + + # Some things may have become missing during the transformation + ds_ap = rgd.fill_missing_data( + ds_ap, xdim=f"{coords.attrs['parallel']}_{self.segment_name}", zdim=None + ) + + self.encode_tidal_files_and_output(ds_ap, "tu") + + return + + def encode_tidal_files_and_output(self, ds, filename): + """ + This function: + + - Expands the dimensions (with the segment name) + - Renames some dimensions to be more specific to the segment + - Provides an output file encoding + - Exports the files. + + Arguments: + self.outfolder (str/path): The output folder to save the tidal files into + dataset (xarray.Dataset): The processed tidal dataset + filename (str): The output file name + + Returns: + netCDF files: Regridded [FILENAME] files in 'self.outfolder/[filename]_[segmentname].nc' + + General Description: + This tidal data functions are sourced from the GFDL NWA25 and changed in the following ways: + + - Converted code for regional-mom6 segment class + - Implemented horizontal Subsetting + - Combined all functions of NWA25 into a four function process (in the style of regional-mom6), that is: ``expt.setup_tides_rectangular_boundaries``, ``segment.coords``, ``segment.regrid_tides``, ``segment.encode_tidal_files_and_output``. + + Code sourced from: + Author(s): GFDL, James Simkins, Rob Cermak, and contributors + Year: 2022 + Title: "NWA25: Northwest Atlantic 1/25th Degree MOM6 Simulation" + Version: N/A + Type: Python Functions, Source Code + Web Address: https://github.com/jsimkins2/nwa25 + """ + + coords = rgd.coords(self.hgrid, self.orientation, self.segment_name) + + ## Expand Tidal Dimensions ## + + for var in ds: + + ds = rgd.add_secondary_dimension(ds, str(var), coords, self.segment_name) + + ## Rename Tidal Dimensions ## + ds = ds.rename( + {"lon": f"lon_{self.segment_name}", "lat": f"lat_{self.segment_name}"} + ) + + ds = rgd.mask_dataset( + ds, self.hgrid, self.bathymetry, self.orientation, self.segment_name + ) + ## Perform Encoding ## + + fname = f"{filename}_{self.segment_name}.nc" + # Set format and attributes for coordinates, including time if it does not already have calendar attribute + # (may change this to detect whether time is a time type or a float). + # Need to include the fillvalue or it will be back to nan + encoding = { + "time": dict(dtype="float64", calendar="gregorian", _FillValue=1.0e20), + f"lon_{self.segment_name}": dict(dtype="float64", _FillValue=1.0e20), + f"lat_{self.segment_name}": dict(dtype="float64", _FillValue=1.0e20), + } + encoding = rgd.generate_encoding(ds, encoding, default_fill_value=1.0e20) + + ## Export Files ## + ds.to_netcdf( + Path(self.outfolder / fname), + engine="netcdf4", + encoding=encoding, + unlimited_dims="time", + ) + return ds diff --git a/regional_mom6/regridding.py b/regional_mom6/regridding.py new file mode 100644 index 00000000..00ea14ab --- /dev/null +++ b/regional_mom6/regridding.py @@ -0,0 +1,713 @@ +""" +Custom-built helper functions to regrid the boundary conditions and encoding for MOM6. + +Steps: +1. Initial Regridding -> Find the boundary of the ``hgrid``, and regrid the forcing variables to that boundary. Call (``initial_regridding``) and then use the xesmf.Regridder with whatever datasets you need. +2. Work on some data issues + + 1. For temperature - Make sure it's in Celsius + 2. FILL IN NANS -> this is important for MOM6 (fill_missing_data) -> This diverges between + +3. For tides, we split the tides into an amplitude and a phase +4. In some cases, here is a great place to rotate the velocities to match a curved grid (tidal_velocity), velocity is also a good place to do this. +5. We then add the time coordinate +6. For vars that are not just surface variables, we need to add several depth related variables + 1. Add a dz variable in layer thickness + 2. Some metadata issues later on +7. Now we do up the metadata +8. Rename variables to var_segment_num +9. (IF VERTICAL EXISTS) Rename the vertical coordinate of the variable to nz_segment_num_var +10. (IF VERTICAL EXISTS) Declare this new vertical coordiante as a increasing series of integers +11. Re-add the "perpendicular" dimension +12. ....Add layer thickness of dz to the vertical forcings +13. Add to encoding_dict a fill value(_FillValue) and zlib, dtype, for time, lat long, ....and each variable (no type needed though) +""" + +import xesmf as xe +import xarray as xr +from pathlib import Path +import dask.array as da +import numpy as np +import netCDF4 +from regional_mom6.utils import setup_logger + + +regridding_logger = setup_logger(__name__, set_handler=False) + + +def coords( + hgrid: xr.Dataset, + orientation: str, + segment_name: str, + coords_at_t_points=False, + angle_variable_name="angle_dx", +) -> xr.Dataset: + """ + Allows us to call the coords for use in the ``xesmf.Regridder`` in the :func:`~regrid_tides` function. + ``self.coords`` gives us the subset of the ``hgrid`` based on the orientation. + + Arguments: + hgrid (xr.Dataset): The horizontal grid dataset + orientation (str): The orientation of the boundary + segment_name (str): The name of the segment + coords_at_t_points (bool, optional): Whether to return the boundary t-points instead of + the q/u/v of a general boundary for rotation. Default: ``False`` + + Returns: + xr.Dataset: The correct coordinate space for the orientation + + Code adapted from:: + Author(s): GFDL, James Simkins, Rob Cermak, etc.. + Year: 2022 + Title: "NWA25: Northwest Atlantic 1/25th Degree MOM6 Simulation" + Version: N/A + Type: Python Functions, Source Code + Web Address: https://github.com/jsimkins2/nwa25 + """ + + dataset_to_get_coords = None + + if coords_at_t_points: + regridding_logger.info("Creating coordinates of the boundary t-points") + + # Calc T Point Info + ds = get_hgrid_arakawa_c_points(hgrid, "t") + + tangle_dx = hgrid[angle_variable_name][(ds.t_points_y, ds.t_points_x)] + # Assign to dataset + dataset_to_get_coords = xr.Dataset( + { + "x": ds.tlon, + "y": ds.tlat, + angle_variable_name: (("nyp", "nxp"), tangle_dx.values), + }, + coords={"nyp": ds.nyp, "nxp": ds.nxp}, + ) + else: + regridding_logger.info("Creating coordinates of the boundary q/u/v points") + # Don't have to do anything because this is the actual boundary. t-points are one-index deep and require managing. + dataset_to_get_coords = hgrid + + # Rename nxp and nyp to locations + if orientation == "south": + rcoord = xr.Dataset( + { + "lon": dataset_to_get_coords["x"].isel(nyp=0), + "lat": dataset_to_get_coords["y"].isel(nyp=0), + "angle": dataset_to_get_coords[angle_variable_name].isel(nyp=0), + } + ) + rcoord = rcoord.rename_dims({"nxp": f"nx_{segment_name}"}) + rcoord.attrs["perpendicular"] = "ny" + rcoord.attrs["parallel"] = "nx" + rcoord.attrs["axis_to_expand"] = ( + 2 ## Need to keep track of which axis the 'main' coordinate corresponds to when re-adding the 'secondary' axis + ) + elif orientation == "north": + rcoord = xr.Dataset( + { + "lon": dataset_to_get_coords["x"].isel(nyp=-1), + "lat": dataset_to_get_coords["y"].isel(nyp=-1), + "angle": dataset_to_get_coords[angle_variable_name].isel(nyp=-1), + } + ) + rcoord = rcoord.rename_dims({"nxp": f"nx_{segment_name}"}) + rcoord.attrs["perpendicular"] = "ny" + rcoord.attrs["parallel"] = "nx" + rcoord.attrs["axis_to_expand"] = 2 + elif orientation == "west": + rcoord = xr.Dataset( + { + "lon": dataset_to_get_coords["x"].isel(nxp=0), + "lat": dataset_to_get_coords["y"].isel(nxp=0), + "angle": dataset_to_get_coords[angle_variable_name].isel(nxp=0), + } + ) + rcoord = rcoord.rename_dims({"nyp": f"ny_{segment_name}"}) + rcoord.attrs["perpendicular"] = "nx" + rcoord.attrs["parallel"] = "ny" + rcoord.attrs["axis_to_expand"] = 3 + elif orientation == "east": + rcoord = xr.Dataset( + { + "lon": dataset_to_get_coords["x"].isel(nxp=-1), + "lat": dataset_to_get_coords["y"].isel(nxp=-1), + "angle": dataset_to_get_coords[angle_variable_name].isel(nxp=-1), + } + ) + rcoord = rcoord.rename_dims({"nyp": f"ny_{segment_name}"}) + rcoord.attrs["perpendicular"] = "nx" + rcoord.attrs["parallel"] = "ny" + rcoord.attrs["axis_to_expand"] = 3 + + # Make lat and lon coordinates + rcoord = rcoord.assign_coords(lat=rcoord["lat"], lon=rcoord["lon"]) + + return rcoord + + +def get_hgrid_arakawa_c_points(hgrid: xr.Dataset, point_type="t") -> xr.Dataset: + """ + Get the Arakawa C points from the Hgrid, originally written by Fred (Castruccio) and moved to regional-mom6 + Parameters + ---------- + hgrid: xr.Dataset + The hgrid dataset + Returns + ------- + xr.Dataset + The specific points x, y, & point indexes + """ + if point_type not in "uvqth": + raise ValueError("point_type must be one of 'uvqht'") + + regridding_logger.info("Getting {} points..".format(point_type)) + + # Figure out the maths for the offset + k = 2 + kp2 = k // 2 + offset_one_by_two_y = np.arange(kp2, len(hgrid.x.nyp), k) + offset_one_by_two_x = np.arange(kp2, len(hgrid.x.nxp), k) + by_two_x = np.arange(0, len(hgrid.x.nxp), k) + by_two_y = np.arange(0, len(hgrid.x.nyp), k) + + # T point locations + if point_type == "t" or point_type == "h": + points = (offset_one_by_two_y, offset_one_by_two_x) + # U point locations + elif point_type == "u": + points = (offset_one_by_two_y, by_two_x) + # V point locations + elif point_type == "v": + points = (by_two_y, offset_one_by_two_x) + # Corner point locations + elif point_type == "q": + points = (by_two_y, by_two_x) + else: + raise ValueError("Invalid Point Type (u, v, q, or t/h only)") + + point_dataset = xr.Dataset( + { + "{}lon".format(point_type): hgrid.x[points], + "{}lat".format(point_type): hgrid.y[points], + "{}_points_y".format(point_type): points[0], + "{}_points_x".format(point_type): points[1], + } + ) + point_dataset.attrs["description"] = ( + "Arakawa C {}-points of supplied h-grid".format(point_type) + ) + return point_dataset + + +def create_regridder( + forcing_variables: xr.Dataset, + output_grid: xr.Dataset, + outfile: Path = None, + method: str = "bilinear", + locstream_out: bool = True, + periodic: bool = False, +) -> xe.Regridder: + """ + Basic Regridder for any forcing variables, this just wraps the xesmf regridder for a few defaults + Parameters + ---------- + forcing_variables : xr.Dataset + The dataset of the forcing variables + output_grid : xr.Dataset + The dataset of the output grid -> this is the boundary of the hgrid + outfile : Path, optional + The path to the output file for weights I believe, by default Path(".temp") + method : str, optional + The regridding method, by default "bilinear" + locstream_out : bool, optional + Whether to output the locstream, by default True + periodic : bool, optional + Whether the grid is periodic, by default False + Returns + ------- + xe.Regridder + The regridding object + """ + regridding_logger.info("Creating Regridder") + regridder = xe.Regridder( + forcing_variables, + output_grid, + method=method, + locstream_out=locstream_out, + periodic=periodic, + filename=outfile, + reuse_weights=False, + ) + return regridder + + +def fill_missing_data( + ds: xr.Dataset, xdim: str = "locations", zdim: str = "z", fill: str = "b" +) -> xr.Dataset: + """ + Fill in missing values, taken from GFDL NWA 25 Repo + Parameters + ---------- + ds : xr.Dataset + The dataset to fill in + z_dim_name : str + The name of the z dimension + Returns + ------- + xr.Dataset + The filled in dataset + """ + regridding_logger.info("Filling in missing data horizontally, then vertically") + if fill == "f": + filled = ds.ffill(dim=xdim, limit=None) + elif fill == "b": + filled = ds.bfill(dim=xdim, limit=None) + if zdim is not None: + filled = filled.ffill(dim=zdim, limit=None).fillna(0) + return filled + + +def add_or_update_time_dim(ds: xr.Dataset, times) -> xr.Dataset: + """ + Add the time dimension to the dataset, in tides case can be one time step. + Parameters + ---------- + ds : xr.Dataset + The dataset to add the time dimension to + times : list, np.Array, xr.DataArray + The list of times + Returns + ------- + xr.Dataset + The dataset with the time dimension added + """ + regridding_logger.info("Adding time dimension") + + regridding_logger.debug(f"Times: {times}") + regridding_logger.debug(f"Make sure times is a DataArray") + # Make sure times is an xr.DataArray + times = xr.DataArray(times) + + if "time" in ds.dims: + regridding_logger.debug("Time already in dataset, overwriting with new values") + ds["time"] = times + else: + regridding_logger.debug("Time not in dataset, xr.Broadcasting time dimension") + ds, _ = xr.broadcast(ds, times) + + # Make sure time is first.... + regridding_logger.debug("Transposing time to first dimension") + new_dims = ["time"] + [dim for dim in ds.dims if dim != "time"] + ds = ds.transpose(*new_dims) + + return ds + + +def generate_dz(ds: xr.Dataset, z_dim_name: str) -> xr.Dataset: + """ + For vertical coordinates, you need to have the layer thickness or something. Generate the dz variable for the dataset + Parameters + ---------- + ds : xr.Dataset + The dataset to get the z variable from + z_dim_name : str + The name of the z dimension + Returns + ------- + xr.Dataset + the dz variable + """ + dz = ds[z_dim_name].diff(z_dim_name) + dz.name = "dz" + dz = xr.concat([dz, dz[-1]], dim=z_dim_name) + return dz + + +def add_secondary_dimension( + ds: xr.Dataset, var: str, coords, segment_name: str, to_beginning=False +) -> xr.Dataset: + """Add the perpendiciular dimension to the dataset, even if it's like one val. It's required. + Parameters + ----------- + ds : xr.Dataset + The dataset to add the perpendicular dimension to + var : str + The variable to add the perpendicular dimension to + coords : xr.Dataset + The coordinates from the function coords... + segment_name : str + The segment name + to_beginning : bool, optional + Whether to add the perpendicular dimension to the beginning or to the selected position, by default False + Returns + ------- + xr.Dataset + The dataset with the perpendicular dimension added + + + """ + + # Check if we need to insert the dim earlier or later + regridding_logger.info("Adding perpendicular dimension to {}".format(var)) + + regridding_logger.debug( + "Checking if nz or constituent is in dimensions, then we have to bump the perpendicular dimension up by one" + ) + insert_behind_by = 0 + if not to_beginning: + + if any( + coord.startswith("nz") or coord == "constituent" for coord in ds[var].dims + ): + regridding_logger.debug("Bump it by one") + insert_behind_by = 0 + else: + # Missing vertical dim or tidal coord means we don't need to offset the perpendicular + insert_behind_by = 1 + else: + insert_behind_by = coords.attrs[ + "axis_to_expand" + ] # Just magic to add dim to the beginning + + regridding_logger.debug(f"Expand dimensions") + ds[var] = ds[var].expand_dims( + f"{coords.attrs['perpendicular']}_{segment_name}", + axis=coords.attrs["axis_to_expand"] - insert_behind_by, + ) + return ds + + +def vertical_coordinate_encoding( + ds: xr.Dataset, var: str, segment_name: str, old_vert_coord_name: str +) -> xr.Dataset: + """ + Rename vertical coordinate to nz[additional-text] then change it to regular increments + + Parameters + ---------- + ds : xr.Dataset + The dataset to rename the vertical coordinate in + var : str + The variable to rename the vertical coordinate in + segment_name : str + The segment name + old_vert_coord_name : str + The old vertical coordinate name + """ + + regridding_logger.info("Renaming vertical coordinate to nz_... in {}".format(var)) + section = "_seg" + base_var = var[: var.find(section)] if section in var else var + ds[var] = ds[var].rename({old_vert_coord_name: f"nz_{segment_name}_{base_var}"}) + + ## Replace the old depth coordinates with incremental integers + regridding_logger.info("Replacing old depth coordinates with incremental integers") + ds[f"nz_{segment_name}_{base_var}"] = np.arange( + ds[f"nz_{segment_name}_{base_var}"].size + ) + + return ds + + +def generate_layer_thickness( + ds: xr.Dataset, var: str, segment_name: str, old_vert_coord_name: str +) -> xr.Dataset: + """ + Generate Layer Thickness Variable, needed for vars with vertical dimensions + Parameters + ---------- + ds : xr.Dataset + The dataset to generate the layer thickness for + var : str + The variable to generate the layer thickness for + segment_name : str + The segment name + old_vert_coord_name : str + The old vertical coordinate name + Returns + ------- + xr.Dataset + The dataset with the layer thickness variable added + """ + regridding_logger.debug("Generating layer thickness variable for {}".format(var)) + dz = generate_dz(ds, old_vert_coord_name) + ds[f"dz_{var}"] = ( + [ + "time", + f"nz_{var}", + f"ny_{segment_name}", + f"nx_{segment_name}", + ], + da.broadcast_to( + dz.data[None, :, None, None], + ds[var].shape, + chunks=( + 1, + None, + None, + None, + ), ## Chunk in each time, and every 5 vertical layers + ), + ) + + return ds + + +def get_boundary_mask( + hgrid: xr.Dataset, + bathy: xr.Dataset, + side: str, + segment_name: str, + minimum_depth=0, + x_dim_name="lonh", + y_dim_name="lath", + add_land_exceptions=True, +) -> np.ndarray: + """ + Mask out the boundary conditions based on the bathymetry. We don't want to have boundary conditions on land. + Parameters + ---------- + hgrid : xr.Dataset + The hgrid dataset + bathy : xr.Dataset + The bathymetry dataset + side : str + The side of the boundary, "north", "south", "east", or "west" + segment_name : str + The segment name + minimum_depth : float, optional + The minimum depth to consider land, by default 0 + add_land_exceptions : bool + Add the corners and 3 coast point exceptions + Returns + ------- + np.ndarray + The boundary mask + """ + + # Hide the bathy as an hgrid so we can take advantage of the coords function to get the boundary points. + + # First rename bathy dims to nyp and nxp + try: + bathy = bathy.rename({y_dim_name: "nyp", x_dim_name: "nxp"}) + except: + try: + bathy = bathy.rename({"ny": "nyp", "nx": "nxp"}) + except: + regridding_logger.error("Could not rename bathy to nyp and nxp") + raise ValueError("Please provide the bathymetry x and y dimension names") + + # Copy Hgrid + bathy_as_hgrid = hgrid.copy(deep=True) + + # Create new depth field + bathy_as_hgrid["depth"] = bathy_as_hgrid["angle_dx"] + bathy_as_hgrid["depth"][:, :] = np.nan + + # Fill at t_points (what bathy is determined at) + ds_t = get_hgrid_arakawa_c_points(hgrid, "t") + + # Identify any extra dimension like ntiles + extra_dim = None + for dim in bathy.dims: + if dim not in ["nyp", "nxp"]: + extra_dim = dim + break + # Select the first index along the extra dimension if it exists + if extra_dim: + bathy = bathy.isel({extra_dim: 0}) + + bathy_as_hgrid["depth"][ + ds_t.t_points_y.values, ds_t.t_points_x.values + ] = bathy.depth + + bathy_as_hgrid_coords = coords( + bathy_as_hgrid, + side, + segment_name, + angle_variable_name="depth", + coords_at_t_points=True, + ) + + # Get the Boundary Depth -> we're done with the hgrid now + bathy_as_hgrid_coords["boundary_depth"] = bathy_as_hgrid_coords["angle"] + + # Mask Fill Values + land = 0.5 + ocean = 1.0 + zero_out = 0.0 + + # Create Mask + boundary_mask = np.full(np.shape(coords(hgrid, side, segment_name).angle), ocean) + + # Fill with MOM6 version of mask + for i in range(len(bathy_as_hgrid_coords["boundary_depth"])): + if bathy_as_hgrid_coords["boundary_depth"][i] <= minimum_depth: + # The points to the left and right of this t-point are land points + boundary_mask[(i * 2) + 2] = land + boundary_mask[(i * 2) + 1] = ( + land # u/v point on the second level just like mask2DCu + ) + boundary_mask[(i * 2)] = land + + if add_land_exceptions: + # Land points that can't be NaNs: Corners & 3 points at the coast + + # Looks like in the boundary between land and ocean - in NWA for example - we basically need to remove 3 points closest to ocean as a buffer. + # Search for intersections + coasts_lower_index = [] + coasts_higher_index = [] + for index in range(1, len(boundary_mask) - 1): + if boundary_mask[index - 1] == land and boundary_mask[index] == ocean: + coasts_lower_index.append(index) + elif boundary_mask[index + 1] == land and boundary_mask[index] == ocean: + coasts_higher_index.append(index) + + # Remove 3 land points from the coast, and make them zeroed out real values + for i in range(3): + for coast in coasts_lower_index: + if coast - 1 - i >= 0: + boundary_mask[coast - 1 - i] = zero_out + for coast in coasts_higher_index: + if coast + 1 + i < len(boundary_mask): + boundary_mask[coast + 1 + i] = zero_out + + # Corner Q-points defined as land should be zeroed out + if boundary_mask[0] == land: + boundary_mask[0] = zero_out + if boundary_mask[-1] == land: + boundary_mask[-1] = zero_out + + # Convert land points to nans + boundary_mask[np.where(boundary_mask == land)] = np.nan + + return boundary_mask + + +def mask_dataset( + ds: xr.Dataset, + hgrid: xr.Dataset, + bathymetry: xr.Dataset, + orientation, + segment_name: str, + y_dim_name="lath", + x_dim_name="lonh", + add_land_exceptions=True, +) -> xr.Dataset: + """ + This function masks the dataset to the provided bathymetry. If bathymetry is not provided, it fills all NaNs with 0. + Parameters + ---------- + ds : xr.Dataset + The dataset to mask + hgrid : xr.Dataset + The hgrid dataset + bathymetry : xr.Dataset + The bathymetry dataset + orientation : str + The orientation of the boundary + segment_name : str + The segment name + add_land_exceptions : bool + To add the corner and 3 point coast exception + """ + ## Add Boundary Mask ## + if bathymetry is not None: + regridding_logger.info( + "Masking to bathymetry. If you don't want this, set bathymetry_path to None in the segment class." + ) + mask = get_boundary_mask( + hgrid, + bathymetry, + orientation, + segment_name, + minimum_depth=0, + x_dim_name=x_dim_name, + y_dim_name=y_dim_name, + add_land_exceptions=add_land_exceptions, + ) + if orientation in ["east", "west"]: + mask = mask[:, np.newaxis] + else: + mask = mask[np.newaxis, :] + + for var in ds.data_vars.keys(): + + ## Compare the dataset to the mask by reducing dims## + dataset_reduce_dim = ds[var] + for index in range(ds[var].ndim - 2): + dataset_reduce_dim = dataset_reduce_dim[0] + if orientation in ["east", "west"]: + dataset_reduce_dim = dataset_reduce_dim[:, 0] + mask_reduce = mask[:, 0] + else: + dataset_reduce_dim = dataset_reduce_dim[0, :] + mask_reduce = mask[0, :] + loc_nans_data = np.where(np.isnan(dataset_reduce_dim)) + loc_nans_mask = np.where(np.isnan(mask_reduce)) + + ## Check if all nans in the data are in the mask without corners ## + if not np.isin(loc_nans_data[1:-1], loc_nans_mask[1:-1]).all(): + regridding_logger.warning( + f"NaNs in {var} not in mask. This values are filled with zeroes b/c they could cause issues with boundary conditions." + ) + + ## Remove Nans if needed ## + ds[var] = ds[var].fillna(0) + elif np.isnan(dataset_reduce_dim[0]): # The corner is nan in the data + ds[var] = ds[var].copy() + ds[var][..., 0, 0] = 0 + elif np.isnan(dataset_reduce_dim[-1]): # The corner is nan in the data + ds[var] = ds[var].copy() + if orientation in ["east", "west"]: + ds[var][..., -1, 0] = 0 + else: + ds[var][..., 0, -1] = 0 + + ## Remove Nans if needed ## + ds[var] = ds[var].fillna(0) + + ## Apply the mask ## # Multiplication allows us to use 1, 0, and nan in the mask + ds[var] = ds[var] * mask + else: + regridding_logger.warning( + "All NaNs filled b/c bathymetry wasn't provided to the function. Add bathymetry_path to the segment class to avoid this" + ) + ds = ds.fillna( + 0 + ) # Without bathymetry, we can't assume the nans will be allowed in Boundary Conditions + return ds + + +def generate_encoding( + ds: xr.Dataset, encoding_dict, default_fill_value=netCDF4.default_fillvals["f8"] +) -> dict: + """ + Generate the encoding dictionary for the dataset + Parameters + ---------- + ds : xr.Dataset + The dataset to generate the encoding for + encoding_dict : dict + The starting encoding dict with some specifications needed for time and other vars, this will be updated with encodings in this function + default_fill_value : float, optional + The default fill value, by default 1.0e20 + Returns + ------- + dict + The encoding dictionary + """ + regridding_logger.info("Generating encoding dictionary") + for var in ds: + if "_segment_" in var and not "nz" in var: + encoding_dict[var] = { + "_FillValue": default_fill_value, + } + for var in ds.coords: + if "nz_" in var: + encoding_dict[var] = { + "dtype": "int32", + } + + return encoding_dict diff --git a/regional_mom6/rotation.py b/regional_mom6/rotation.py new file mode 100644 index 00000000..32c263d1 --- /dev/null +++ b/regional_mom6/rotation.py @@ -0,0 +1,339 @@ +from regional_mom6 import utils +from regional_mom6.regridding import get_hgrid_arakawa_c_points, coords + +rotation_logger = utils.setup_logger(__name__, set_handler=False) +# An Enum is like a dropdown selection for a menu, it essentially limits the type of input parameters. It comes with additional complexity, which of course is always a challenge. +from enum import Enum +import xarray as xr +import numpy as np + + +class RotationMethod(Enum): + """Prescribes the rotational method to be used in boundary conditions when the grid + does not have coordinates along lines of constant longitude-latitude. regional-mom6 main + class passes this ``Enum`` to :func:`~regrid_tides` and to :func:`~regrid_velocity_tracers`. + + Attributes: + EXPAND_GRID (int): This method is used with the basis that we can find the angles at the q-u-v points by pretending we have another row/column of the ``hgrid`` with the same distances as the t-point to u/v points in the actual grid then use the four points to calculate the angle. This method replicates exactly what MOM6 does. + GIVEN_ANGLE (int): Expects a pre-given angle called ``angle_dx``. + NO_ROTATION (int): Grid is along lines of constant latitude-longitude and therefore no rotation is required. + """ + + EXPAND_GRID = 1 + GIVEN_ANGLE = 2 + NO_ROTATION = 3 + + +def initialize_grid_rotation_angles_using_expanded_hgrid( + hgrid: xr.Dataset, +) -> xr.Dataset: + """ + Calculate the ``angle_dx`` in degrees from the true x direction (parallel to latitude) counter-clockwise and return as a dataarray. + + Parameters + ---------- + hgrid: xr.Dataset + The hgrid dataset + + Returns + ------- + xr.DataArray + The t-point angles + """ + # Get expanded (pseudo) grid + expanded_hgrid = create_expanded_hgrid(hgrid) + + return mom6_angle_calculation_method( + expanded_hgrid.x.max() - expanded_hgrid.x.min(), + expanded_hgrid.isel(nyp=slice(2, None), nxp=slice(0, -2)), + expanded_hgrid.isel(nyp=slice(2, None), nxp=slice(2, None)), + expanded_hgrid.isel(nyp=slice(0, -2), nxp=slice(0, -2)), + expanded_hgrid.isel(nyp=slice(0, -2), nxp=slice(2, None)), + hgrid, + ) + + +def initialize_grid_rotation_angle(hgrid: xr.Dataset) -> xr.DataArray: + """ + Calculate the ``angle_dx`` in degrees from the true ``x`` direction (parallel to latitude) counter-clockwise + and return as a dataarray. (Mimics MOM6 angle calculation function :func:`~mom6_angle_calculation_method`) + + Parameters + ---------- + hgrid: xr.Dataset + The hgrid dataset + + Returns + ------- + xr.DataArray + The t-point angles + """ + ds_t = get_hgrid_arakawa_c_points(hgrid, "t") + ds_q = get_hgrid_arakawa_c_points(hgrid, "q") + + # Reformat into x, y comps + t_points = xr.Dataset( + { + "x": (("nyp", "nxp"), ds_t.tlon.data), + "y": (("nyp", "nxp"), ds_t.tlat.data), + } + ) + q_points = xr.Dataset( + { + "x": (("nyp", "nxp"), ds_q.qlon.data), + "y": (("nyp", "nxp"), ds_q.qlat.data), + } + ) + + return mom6_angle_calculation_method( + hgrid.x.max() - hgrid.x.min(), + q_points.isel(nyp=slice(1, None), nxp=slice(0, -1)), + q_points.isel(nyp=slice(1, None), nxp=slice(1, None)), + q_points.isel(nyp=slice(0, -1), nxp=slice(0, -1)), + q_points.isel(nyp=slice(0, -1), nxp=slice(1, None)), + t_points, + ) + + +def modulo_around_point(x, x0, L): + """ + Return the modulo-:math:`L` value of :math:`x` within the interval :math:`[x_0 - L/2, x_0 + L/2]`. + If :math:`L ≤ 0`, then we get back :math:`x`. + + (Adapted from MOM6 code; https://github.com/mom-ocean/MOM6/blob/776be843e904d85c7035ffa00233b962a03bfbb4/src/initialization/MOM_shared_initialization.F90#L592-L606) + + Parameters + ---------- + x: float + Value to which to apply modulo arithmetic + x0: float + Center of modulo range + L: float + Modulo range width + + Returns + ------- + float + ``x`` shifted by an integer multiple of ``L`` to be closer to ``x0``, i.e., within the interval ``[x0 - L/2, x0 + L/2]`` + """ + if L <= 0: + return x + else: + return ((x - (x0 - L / 2)) % L) + (x0 - L / 2) + + +def mom6_angle_calculation_method( + len_lon, + top_left: xr.DataArray, + top_right: xr.DataArray, + bottom_left: xr.DataArray, + bottom_right: xr.DataArray, + point: xr.DataArray, +) -> xr.DataArray: + """ + Calculate the angle of the point using the MOM6 method adapted from the + MOM6 code: https://github.com/mom-ocean/MOM6/blob/05d8cc395c1c3c04dd04885bf8dd6df50a86b862/src/initialization/MOM_shared_initialization.F90#L572-L587 + + This method can handle vectorized computations. + + Parameters + ---------- + len_lon: float + The extent of the longitude of the regional domain (in degrees). + top_left, top_right, bottom_left, bottom_right: xr.DataArray + The four points around the point to calculate the angle from the hgrid; + requires both an `x` and `y` component, both of which are in degrees. + point: xr.DataArray + The point to calculate the angle from the ``hgrid`` + + Returns + ------- + xr.DataArray + The angle of the point + """ + rotation_logger.info("Calculating grid rotation angle") + + # Compute lonB for all points + lonB = np.zeros((2, 2, len(point.nyp), len(point.nxp))) + + # Vectorized computation of lonB + lonB[0][0] = modulo_around_point(bottom_left.x, point.x, len_lon) # Bottom Left + lonB[1][0] = modulo_around_point(top_left.x, point.x, len_lon) # Top Left + lonB[1][1] = modulo_around_point(top_right.x, point.x, len_lon) # Top Right + lonB[0][1] = modulo_around_point(bottom_right.x, point.x, len_lon) # Bottom Right + + cos_meanlat = np.cos( + np.deg2rad((bottom_left.y + bottom_right.y + top_right.y + top_left.y) / 4) + ) + + # Compute angle + angle = np.arctan2( + cos_meanlat * ((lonB[1, 0] - lonB[0, 1]) + (lonB[1, 1] - lonB[0, 0])), + (top_right.y - bottom_left.y) + (top_left.y - bottom_right.y), + ) + # Assign angle to angles_arr + angles_arr = -np.rad2deg(angle) + + # Assign angles_arr to hgrid + t_angles = xr.DataArray( + angles_arr, + dims=["nyp", "nxp"], + coords={ + "nyp": point.nyp.values, + "nxp": point.nxp.values, + }, + ) + return t_angles + + +def create_expanded_hgrid(hgrid: xr.Dataset, expansion_width=1) -> xr.Dataset: + """ + Adds an additional boundary to the hgrid to allow for the calculation of the ``angle_dx`` for the boundary points using the method in MOM6. + """ + if expansion_width != 1: + raise NotImplementedError("Only expansion_width = 1 is supported") + + pseudo_hgrid_x = np.full((len(hgrid.nyp) + 2, len(hgrid.nxp) + 2), np.nan) + pseudo_hgrid_y = np.full((len(hgrid.nyp) + 2, len(hgrid.nxp) + 2), np.nan) + + ## Fill Boundaries + pseudo_hgrid_x[1:-1, 1:-1] = hgrid.x.values + pseudo_hgrid_x[0, 1:-1] = hgrid.x.values[0, :] - ( + hgrid.x.values[1, :] - hgrid.x.values[0, :] + ) # Bottom Fill + pseudo_hgrid_x[-1, 1:-1] = hgrid.x.values[-1, :] + ( + hgrid.x.values[-1, :] - hgrid.x.values[-2, :] + ) # Top Fill + pseudo_hgrid_x[1:-1, 0] = hgrid.x.values[:, 0] - ( + hgrid.x.values[:, 1] - hgrid.x.values[:, 0] + ) # Left Fill + pseudo_hgrid_x[1:-1, -1] = hgrid.x.values[:, -1] + ( + hgrid.x.values[:, -1] - hgrid.x.values[:, -2] + ) # Right Fill + + pseudo_hgrid_y[1:-1, 1:-1] = hgrid.y.values + pseudo_hgrid_y[0, 1:-1] = hgrid.y.values[0, :] - ( + hgrid.y.values[1, :] - hgrid.y.values[0, :] + ) # Bottom Fill + pseudo_hgrid_y[-1, 1:-1] = hgrid.y.values[-1, :] + ( + hgrid.y.values[-1, :] - hgrid.y.values[-2, :] + ) # Top Fill + pseudo_hgrid_y[1:-1, 0] = hgrid.y.values[:, 0] - ( + hgrid.y.values[:, 1] - hgrid.y.values[:, 0] + ) # Left Fill + pseudo_hgrid_y[1:-1, -1] = hgrid.y.values[:, -1] + ( + hgrid.y.values[:, -1] - hgrid.y.values[:, -2] + ) # Right Fill + + ## Fill Corners + pseudo_hgrid_x[0, 0] = hgrid.x.values[0, 0] - ( + hgrid.x.values[1, 1] - hgrid.x.values[0, 0] + ) # Bottom Left + pseudo_hgrid_x[-1, 0] = hgrid.x.values[-1, 0] - ( + hgrid.x.values[-2, 1] - hgrid.x.values[-1, 0] + ) # Top Left + pseudo_hgrid_x[0, -1] = hgrid.x.values[0, -1] - ( + hgrid.x.values[1, -2] - hgrid.x.values[0, -1] + ) # Bottom Right + pseudo_hgrid_x[-1, -1] = hgrid.x.values[-1, -1] - ( + hgrid.x.values[-2, -2] - hgrid.x.values[-1, -1] + ) # Top Right + + pseudo_hgrid_y[0, 0] = hgrid.y.values[0, 0] - ( + hgrid.y.values[1, 1] - hgrid.y.values[0, 0] + ) # Bottom Left + pseudo_hgrid_y[-1, 0] = hgrid.y.values[-1, 0] - ( + hgrid.y.values[-2, 1] - hgrid.y.values[-1, 0] + ) # Top Left + pseudo_hgrid_y[0, -1] = hgrid.y.values[0, -1] - ( + hgrid.y.values[1, -2] - hgrid.y.values[0, -1] + ) # Bottom Right + pseudo_hgrid_y[-1, -1] = hgrid.y.values[-1, -1] - ( + hgrid.y.values[-2, -2] - hgrid.y.values[-1, -1] + ) # Top Right + + pseudo_hgrid = xr.Dataset( + { + "x": (["nyp", "nxp"], pseudo_hgrid_x), + "y": (["nyp", "nxp"], pseudo_hgrid_y), + } + ) + return pseudo_hgrid + + +def get_rotation_angle( + rotational_method: RotationMethod, hgrid: xr.Dataset, orientation=None +): + """ + Returns the rotation angle - with the assumption of degrees - based on the rotational method and provided hgrid, if orientation & coords are provided, it will assume the boundary is requested. + + Parameters + ---------- + rotational_method: RotationMethod + The rotational method to use + hgrid: xr.Dataset + The hgrid dataset + orientation: xr.Dataset + The orientation, which also lets us now that we are on a boundary + + Returns + ------- + xr.DataArray + angle in degrees + """ + rotation_logger.info("Getting rotation angle") + boundary = False + if orientation != None: + rotation_logger.debug( + "The rotational angle is requested for the boundary: {}".format(orientation) + ) + boundary = True + + if rotational_method == RotationMethod.NO_ROTATION: + rotation_logger.debug("Using NO_ROTATION method") + if not utils.is_rectilinear_hgrid(hgrid): + raise ValueError("NO_ROTATION method only works with rectilinear grids") + angles = xr.zeros_like(hgrid.x) + + if boundary: + # Subset to just boundary + # Add zeroes to hgrid + hgrid["zero_angle"] = angles + + # Cut to boundary + zero_angle = coords( + hgrid, + orientation, + "doesnt_matter", + angle_variable_name="zero_angle", + )["angle"] + + return zero_angle + else: + return angles + elif rotational_method == RotationMethod.GIVEN_ANGLE: + rotation_logger.debug("Using GIVEN_ANGLE method") + if boundary: + return coords( + hgrid, orientation, "doesnt_matter", angle_variable_name="angle_dx" + )["angle"] + else: + return hgrid["angle_dx"] + elif rotational_method == RotationMethod.EXPAND_GRID: + rotation_logger.debug("Using EXPAND_GRID method") + hgrid["angle_dx_rm6"] = initialize_grid_rotation_angles_using_expanded_hgrid( + hgrid + ) + + if boundary: + degree_angle = coords( + hgrid, + orientation, + "doesnt_matter", + angle_variable_name="angle_dx_rm6", + )["angle"] + return degree_angle + else: + return hgrid["angle_dx_rm6"] + else: + raise ValueError("Invalid rotational method") diff --git a/regional_mom6/utils.py b/regional_mom6/utils.py index fb0ce865..3c002b8b 100644 --- a/regional_mom6/utils.py +++ b/regional_mom6/utils.py @@ -1,4 +1,8 @@ import numpy as np +import logging +import sys +import xarray as xr +from regional_mom6 import regridding as rgd def vecdot(v1, v2): @@ -91,7 +95,7 @@ def latlon_to_cartesian(lat, lon, R=1): """Convert latitude and longitude (in degrees) to Cartesian coordinates on a sphere of radius ``R``. By default ``R = 1``. - Args: + Arguments: lat (float): Latitude (in degrees). lon (float): Longitude (in degrees). R (float): The radius of the sphere; default: 1. @@ -128,7 +132,7 @@ def quadrilateral_areas(lat, lon, R=1): By default, ``R = 1``. The quadrilaterals are formed by constant latitude and longitude lines on the ``lat``-``lon`` grid provided. - Args: + Arguments: lat (numpy.array): Array of latitude points (in degrees). lon (numpy.array): Array of longitude points (in degrees). R (float): The radius of the sphere; default: 1. @@ -177,3 +181,203 @@ def quadrilateral_areas(lat, lon, R=1): return quadrilateral_area( coords[:-1, :-1, :], coords[:-1, 1:, :], coords[1:, 1:, :], coords[1:, :-1, :] ) + + +def ap2ep(uc, vc): + """Convert complex tidal u and v to tidal ellipse. + + Adapted from ap2ep.m for Matlab. Copyright notice:: + + Authorship: + + The author retains the copyright of this program, while you are welcome + to use and distribute it as long as you credit the author properly and respect + the program name itself. Particularly, you are expected to retain the original + author's name in this original version or any of its modified version that + you might make. You are also expected not to essentially change the name of + the programs except for adding possible extension for your own version you + might create, e.g. ap2ep_xx is acceptable. Any suggestions are welcome and + enjoy my program(s)! + + Author Info: + + Zhigang Xu, Ph.D. + (pronounced as Tsi Gahng Hsu) + Research Scientist + Coastal Circulation + Bedford Institute of Oceanography + 1 Challenge Dr. + P.O. Box 1006 Phone (902) 426-2307 (o) + Dartmouth, Nova Scotia Fax (902) 426-7827 + CANADA B2Y 4A2 email xuz@dfo-mpo.gc.ca + + Release Date: Nov. 2000, Revised on May. 2002 to adopt Foreman's northern semi + major axis convention. + + Arguments: + uc: complex tidal u velocity + vc: complex tidal v velocity + + Returns: + (semi-major axis, eccentricity, inclination [radians], phase [radians]) + """ + wp = (uc + 1j * vc) / 2.0 + wm = np.conj(uc - 1j * vc) / 2.0 + + Wp = np.abs(wp) + Wm = np.abs(wm) + THETAp = np.angle(wp) + THETAm = np.angle(wm) + + SEMA = Wp + Wm + SEMI = Wp - Wm + ECC = SEMI / SEMA + PHA = (THETAm - THETAp) / 2.0 + INC = (THETAm + THETAp) / 2.0 + + return SEMA, ECC, INC, PHA + + +def ep2ap(SEMA, ECC, INC, PHA): + """Convert tidal ellipse to real u and v amplitude and phase. + + Adapted from ep2ap.m for Matlab. Copyright notice:: + + Authorship: + + The author of this program retains the copyright of this program, while + you are welcome to use and distribute this program as long as you credit + the author properly and respect the program name itself. Particularly, + you are expected to retain the original author's name in this original + version of the program or any of its modified version that you might make. + You are also expected not to essentially change the name of the programs + except for adding possible extension for your own version you might create, + e.g. app2ep_xx is acceptable. Any suggestions are welcome and enjoy my + program(s)! + + Author Info: + + Zhigang Xu, Ph.D. + (pronounced as Tsi Gahng Hsu) + Research Scientist + Coastal Circulation + Bedford Institute of Oceanography + 1 Challenge Dr. + P.O. Box 1006 Phone (902) 426-2307 (o) + Dartmouth, Nova Scotia Fax (902) 426-7827 + CANADA B2Y 4A2 email xuz@dfo-mpo.gc.ca + + Release Date: Nov. 2000 + + Arguments: + SEMA: semi-major axis + ECC: eccentricity + INC: inclination [radians] + PHA: phase [radians] + + Returns: + (u amplitude, u phase [radians], v amplitude, v phase [radians]) + """ + Wp = (1 + ECC) / 2.0 * SEMA + Wm = (1 - ECC) / 2.0 * SEMA + THETAp = INC - PHA + THETAm = INC + PHA + + wp = Wp * np.exp(1j * THETAp) + wm = Wm * np.exp(1j * THETAm) + + cu = wp + np.conj(wm) + cv = -1j * (wp - np.conj(wm)) + + ua = np.abs(cu) + va = np.abs(cv) + up = -np.angle(cu) + vp = -np.angle(cv) + + return ua, va, up, vp + + +def setup_logger( + name: str, set_handler=False, log_level=logging.INFO +) -> logging.Logger: + """ + Setup general config for a logger. + """ + logger = logging.getLogger(name) + logger.setLevel(log_level) + if set_handler and not logger.hasHandlers(): + # Create a handler to print to stdout (Jupyter captures stdout) + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(log_level) + + # Create a formatter (optional) + formatter = logging.Formatter("%(name)s.%(funcName)s:%(levelname)s:%(message)s") + handler.setFormatter(formatter) + + # Add the handler to the logger + logger.addHandler(handler) + return logger + + +def rotate_complex(u, v, radian_angle): + """ + Rotate velocities to grid orientation using complex number math (Same as :func:`rotate`.) + + Arguments: + u (xarray.DataArray): The u-component of the velocity. + v (xarray.DataArray): The v-component of the velocity. + radian_angle (xarray.DataArray): The angle of the grid in radians. + + Returns: + Tuple[xarray.DataArray, xarray.DataArray]: The rotated u and v components of the velocity. + """ + + # express velocity in the complex plan + vel = u + v * 1j + # rotate velocity using grid angle theta + vel = vel * np.exp(1j * radian_angle) + + # From here you can easily get the rotated u, v, or the magnitude/direction of the currents: + u = np.real(vel) + v = np.imag(vel) + + return u, v + + +def rotate(u, v, radian_angle): + """ + Rotate the velocities to the grid orientation. + + Arguments: + u (xarray.DataArray): The u-component of the velocity. + v (xarray.DataArray): The v-component of the velocity. + radian_angle (xarray.DataArray): The angle of the grid in radians. + + Returns: + Tuple[xarray.DataArray, xarray.DataArray]: The rotated u and v components of the velocity. + """ + + u_rot = u * np.cos(radian_angle) - v * np.sin(radian_angle) + v_rot = u * np.sin(radian_angle) + v * np.cos(radian_angle) + return u_rot, v_rot + + +def is_rectilinear_hgrid(hgrid: xr.Dataset, rtol: float = 1e-3) -> bool: + """ + Check if the ``hgrid`` is a rectilinear grid by comparing the first and last rows and columns of the tlon and tlat arrays. + + From ``mom6_bathy.grid.is_rectangular`` by Alper (Altuntas). + + Arguments: + hgrid (xarray.Dataset): The horizontal grid dataset. + rtol (float): Relative tolerance. Default is 1e-3. + """ + ds_t = rgd.get_hgrid_arakawa_c_points(hgrid) + if ( + np.allclose(ds_t.tlon[:, 0], ds_t.tlon[0, 0], rtol=rtol) + and np.allclose(ds_t.tlon[:, -1], ds_t.tlon[0, -1], rtol=rtol) + and np.allclose(ds_t.tlat[0, :], ds_t.tlat[0, 0], rtol=rtol) + and np.allclose(ds_t.tlat[-1, :], ds_t.tlat[-1, 0], rtol=rtol) + ): + return True + return False diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..a16792cd --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,281 @@ +import pytest +import os +import xarray as xr +import numpy as np +import regional_mom6 as rmom6 + +# Define the path where the curvilinear hgrid file is expected in the Docker container +DOCKER_FILE_PATH = "/data/small_curvilinear_hgrid.nc" + + +# Define the local directory where the user might have added the curvilinear hgrid file +LOCAL_FILE_PATH = str(os.getenv("local_curvilinear_hgrid")) + + +@pytest.fixture +def get_curvilinear_hgrid(): + # Check if the file exists in the Docker-specific location + if os.path.exists(DOCKER_FILE_PATH): + return xr.open_dataset(DOCKER_FILE_PATH) + + # Check if the user has provided the file in a specific local directory + elif os.path.exists(LOCAL_FILE_PATH): + return xr.open_dataset(LOCAL_FILE_PATH) + + # If neither location contains the file, skip test + else: + pytest.skip( + f"Required file 'hgrid.nc' not found in {DOCKER_FILE_PATH} or {LOCAL_FILE_PATH}" + ) + + +@pytest.fixture +def get_rectilinear_hgrid(): + lat = np.linspace(0, 10, 7) + lon = np.linspace(0, 10, 13) + rect_hgrid = rmom6.generate_rectangular_hgrid(lat, lon) + return rect_hgrid + + +@pytest.fixture() +def generate_silly_vt_dataset(): + latitude_extent = [30, 40] + longitude_extent = [-80, -70] + eastern_boundary = xr.Dataset( + { + "temp": xr.DataArray( + np.random.random((100, 5, 10, 10)), + dims=["silly_lat", "silly_lon", "silly_depth", "time"], + coords={ + "silly_lat": np.linspace( + latitude_extent[0] - 5, latitude_extent[1] + 5, 100 + ), + "silly_lon": np.linspace( + longitude_extent[1] - 0.5, longitude_extent[1] + 0.5, 5 + ), + "silly_depth": np.linspace(0, 1000, 10), + "time": np.linspace(0, 1000, 10), + }, + ), + "eta": xr.DataArray( + np.random.random((100, 5, 10)), + dims=["silly_lat", "silly_lon", "time"], + coords={ + "silly_lat": np.linspace( + latitude_extent[0] - 5, latitude_extent[1] + 5, 100 + ), + "silly_lon": np.linspace( + longitude_extent[1] - 0.5, longitude_extent[1] + 0.5, 5 + ), + "time": np.linspace(0, 1000, 10), + }, + ), + "salt": xr.DataArray( + np.random.random((100, 5, 10, 10)), + dims=["silly_lat", "silly_lon", "silly_depth", "time"], + coords={ + "silly_lat": np.linspace( + latitude_extent[0] - 5, latitude_extent[1] + 5, 100 + ), + "silly_lon": np.linspace( + longitude_extent[1] - 0.5, longitude_extent[1] + 0.5, 5 + ), + "silly_depth": np.linspace(0, 1000, 10), + "time": np.linspace(0, 1000, 10), + }, + ), + "u": xr.DataArray( + np.random.random((100, 5, 10, 10)), + dims=["silly_lat", "silly_lon", "silly_depth", "time"], + coords={ + "silly_lat": np.linspace( + latitude_extent[0] - 5, latitude_extent[1] + 5, 100 + ), + "silly_lon": np.linspace( + longitude_extent[1] - 0.5, longitude_extent[1] + 0.5, 5 + ), + "silly_depth": np.linspace(0, 1000, 10), + "time": np.linspace(0, 1000, 10), + }, + ), + "v": xr.DataArray( + np.random.random((100, 5, 10, 10)), + dims=["silly_lat", "silly_lon", "silly_depth", "time"], + coords={ + "silly_lat": np.linspace( + latitude_extent[0] - 5, latitude_extent[1] + 5, 100 + ), + "silly_lon": np.linspace( + longitude_extent[1] - 0.5, longitude_extent[1] + 0.5, 5 + ), + "silly_depth": np.linspace(0, 1000, 10), + "time": np.linspace(0, 1000, 10), + }, + ), + } + ) + return eastern_boundary + + +@pytest.fixture() +def generate_silly_ic_dataset(): + def _generate_silly_ic_dataset( + longitude_extent, + latitude_extent, + resolution, + number_vertical_layers, + depth, + temp_dataarray_initial_condition, + ): + nx, ny = number_of_gridpoints(longitude_extent, latitude_extent, resolution) + silly_lat, silly_lon, silly_depth = generate_silly_coords( + longitude_extent, latitude_extent, resolution, depth, number_vertical_layers + ) + + dims = ["silly_lat", "silly_lon", "silly_depth"] + + coords = { + "silly_lat": silly_lat, + "silly_lon": silly_lon, + "silly_depth": silly_depth, + } + # initial condition includes, temp, salt, eta, u, v + initial_cond = xr.Dataset( + { + "eta": xr.DataArray( + np.random.random((ny, nx)), + dims=["silly_lat", "silly_lon"], + coords={ + "silly_lat": silly_lat, + "silly_lon": silly_lon, + }, + ), + "temp": temp_dataarray_initial_condition, + "salt": xr.DataArray( + np.random.random((ny, nx, number_vertical_layers)), + dims=dims, + coords=coords, + ), + "u": xr.DataArray( + np.random.random((ny, nx, number_vertical_layers)), + dims=dims, + coords=coords, + ), + "v": xr.DataArray( + np.random.random((ny, nx, number_vertical_layers)), + dims=dims, + coords=coords, + ), + } + ) + return initial_cond + + return _generate_silly_ic_dataset + + +@pytest.fixture() +def dummy_bathymetry_data(): + latitude_extent = [16.0, 27] + longitude_extent = [192, 209] + + bathymetry = np.random.random((100, 100)) * (-100) + bathymetry = xr.DataArray( + bathymetry, + dims=["silly_lat", "silly_lon"], + coords={ + "silly_lat": np.linspace( + latitude_extent[0] - 5, latitude_extent[1] + 5, 100 + ), + "silly_lon": np.linspace( + longitude_extent[0] - 5, longitude_extent[1] + 5, 100 + ), + }, + ) + bathymetry.name = "silly_depth" + return bathymetry + + +def get_temperature_dataarrays( + longitude_extent, latitude_extent, resolution, number_vertical_layers, depth +): + + silly_lat, silly_lon, silly_depth = generate_silly_coords( + longitude_extent, latitude_extent, resolution, depth, number_vertical_layers + ) + + dims = ["silly_lat", "silly_lon", "silly_depth"] + + coords = { + "silly_lat": silly_lat, + "silly_lon": silly_lon, + "silly_depth": silly_depth, + } + + fre_tools_dir = "toolpath" + hgrid_type = "even_spacing" + + nx, ny = number_of_gridpoints(longitude_extent, latitude_extent, resolution) + + temp_in_C, temp_in_C_masked, temp_in_K, temp_in_K_masked = ( + generate_temperature_arrays(nx, ny, number_vertical_layers) + ) + + temp_C = xr.DataArray(temp_in_C, dims=dims, coords=coords) + temp_K = xr.DataArray(temp_in_K, dims=dims, coords=coords) + temp_C_masked = xr.DataArray(temp_in_C_masked, dims=dims, coords=coords) + temp_K_masked = xr.DataArray(temp_in_K_masked, dims=dims, coords=coords) + + maximum_temperature_in_C = np.max(temp_in_C) + return [temp_C, temp_C_masked, temp_K, temp_K_masked] + + +def number_of_gridpoints(longitude_extent, latitude_extent, resolution): + nx = int((longitude_extent[-1] - longitude_extent[0]) / resolution) + ny = int((latitude_extent[-1] - latitude_extent[0]) / resolution) + + return nx, ny + + +def generate_silly_coords( + longitude_extent, latitude_extent, resolution, depth, number_vertical_layers +): + nx, ny = number_of_gridpoints(longitude_extent, latitude_extent, resolution) + + horizontal_buffer = 5 + + silly_lat = np.linspace( + latitude_extent[0] - horizontal_buffer, + latitude_extent[1] + horizontal_buffer, + ny, + ) + silly_lon = np.linspace( + longitude_extent[0] - horizontal_buffer, + longitude_extent[1] + horizontal_buffer, + nx, + ) + silly_depth = np.linspace(0, depth, number_vertical_layers) + + return silly_lat, silly_lon, silly_depth + + +def generate_temperature_arrays(nx, ny, number_vertical_layers): + + # temperatures close to 0 ᵒC + temp_in_C = np.random.randn(ny, nx, number_vertical_layers) + + temp_in_C_masked = np.copy(temp_in_C) + if int(ny / 4 + 4) < ny - 1 and int(nx / 3 + 4) < nx + 1: + temp_in_C_masked[ + int(ny / 3) : int(ny / 3 + 5), int(nx) : int(nx / 4 + 4), : + ] = float("nan") + else: + raise ValueError("use bigger domain") + + temp_in_K = np.copy(temp_in_C) + 273.15 + temp_in_K_masked = np.copy(temp_in_C_masked) + 273.15 + + # ensure we didn't mask the minimum temperature + if np.nanmin(temp_in_C_masked) == np.min(temp_in_C): + return temp_in_C, temp_in_C_masked, temp_in_K, temp_in_K_masked + else: + return generate_temperature_arrays(nx, ny, number_vertical_layers) diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 00000000..be0dd946 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,145 @@ +import pytest +import regional_mom6 as rmom6 +from pathlib import Path +import os +import json +import shutil + + +def test_write_config(tmp_path): + expt_name = "testing" + + latitude_extent = [16.0, 27] + longitude_extent = [192, 209] + + date_range = ["2005-01-01 00:00:00", "2005-02-01 00:00:00"] + + ## Place where all your input files go + input_dir = Path( + os.path.join( + tmp_path, + expt_name, + "inputs", + ) + ) + + ## Directory where you'll run the experiment from + run_dir = Path( + os.path.join( + tmp_path, + expt_name, + "run_files", + ) + ) + data_path = Path(tmp_path / "data") + for path in (run_dir, input_dir, data_path): + os.makedirs(str(path), exist_ok=True) + + ## User-1st, test if we can even read the angled nc files. + expt = rmom6.experiment( + longitude_extent=longitude_extent, + latitude_extent=latitude_extent, + date_range=date_range, + resolution=0.05, + number_vertical_layers=75, + layer_thickness_ratio=10, + depth=4500, + minimum_depth=25, + mom_run_dir=run_dir, + mom_input_dir=input_dir, + fre_tools_dir="", + expt_name="test", + boundaries=["south", "north"], + ) + config_dict = expt.write_config_file(tmp_path / "testing_config.json") + assert config_dict["longitude_extent"] == tuple(longitude_extent) + assert config_dict["latitude_extent"] == tuple(latitude_extent) + assert config_dict["date_range"] == date_range + assert config_dict["resolution"] == 0.05 + assert config_dict["number_vertical_layers"] == 75 + assert config_dict["layer_thickness_ratio"] == 10 + assert config_dict["depth"] == 4500 + assert config_dict["minimum_depth"] == 25 + assert config_dict["expt_name"] == "test" + assert config_dict["hgrid_type"] == "even_spacing" + assert config_dict["repeat_year_forcing"] == False + assert config_dict["tidal_constituents"] == [ + "M2", + "S2", + "N2", + "K2", + "K1", + "O1", + "P1", + "Q1", + "MM", + "MF", + ] + assert config_dict["expt_name"] == "test" + assert config_dict["boundaries"] == ["south", "north"] + shutil.rmtree(run_dir) + shutil.rmtree(input_dir) + shutil.rmtree(data_path) + + +def test_load_config(tmp_path): + + expt_name = "testing" + + latitude_extent = [16.0, 27] + longitude_extent = [192, 209] + + date_range = ["2005-01-01 00:00:00", "2005-02-01 00:00:00"] + + ## Place where all your input files go + input_dir = Path( + os.path.join( + tmp_path, + expt_name, + "inputs", + ) + ) + + ## Directory where you'll run the experiment from + run_dir = Path( + tmp_path, + os.path.join( + tmp_path, + expt_name, + "run_files", + ), + ) + data_path = Path(tmp_path / "data") + for path in (run_dir, input_dir, data_path): + os.makedirs(str(path), exist_ok=True) + + ## User-1st, test if we can even read the angled nc files. + expt = rmom6.experiment( + longitude_extent=longitude_extent, + latitude_extent=latitude_extent, + date_range=date_range, + resolution=0.05, + number_vertical_layers=75, + layer_thickness_ratio=10, + depth=4500, + minimum_depth=25, + mom_run_dir=run_dir, + mom_input_dir=input_dir, + fre_tools_dir="", + ) + path = tmp_path / "testing_config.json" + config_expt = expt.write_config_file(path) + new_expt = rmom6.create_experiment_from_config( + os.path.join(path), mom_input_folder=tmp_path, mom_run_folder=tmp_path + ) + assert str(new_expt) == str(expt) + print(new_expt.vgrid) + print(expt.vgrid) + assert new_expt.hgrid == expt.hgrid + assert (new_expt.vgrid.zi == expt.vgrid.zi).all() & ( + new_expt.vgrid.zl == expt.vgrid.zl + ).all() + assert os.path.exists(new_expt.mom_run_dir) & os.path.exists(new_expt.mom_input_dir) + assert os.path.exists(new_expt.mom_input_dir / "hgrid.nc") & os.path.exists( + new_expt.mom_input_dir / "vcoord.nc" + ) diff --git a/tests/test_expt_class.py b/tests/test_expt_class.py index d0713c2f..830b9764 100644 --- a/tests/test_expt_class.py +++ b/tests/test_expt_class.py @@ -2,6 +2,14 @@ import pytest from regional_mom6 import experiment import xarray as xr +import xesmf as xe +import dask +from .conftest import ( + generate_temperature_arrays, + generate_silly_coords, + number_of_gridpoints, + get_temperature_dataarrays, +) ## Note: ## When creating test dataarrays we use 'silly' names for coordinates to @@ -17,10 +25,8 @@ "number_vertical_layers", "layer_thickness_ratio", "depth", - "mom_run_dir", - "mom_input_dir", - "toolpath_dir", - "grid_type", + "fre_tools_dir", + "hgrid_type", ), [ ( @@ -31,8 +37,6 @@ 5, 1, 1000, - "rundir/", - "inputdir/", "toolpath", "even_spacing", ), @@ -46,12 +50,12 @@ def test_setup_bathymetry( number_vertical_layers, layer_thickness_ratio, depth, - mom_run_dir, - mom_input_dir, - toolpath_dir, - grid_type, + fre_tools_dir, + hgrid_type, tmp_path, ): + mom_run_dir = tmp_path / "rundir" + mom_input_dir = tmp_path / "inputdir" expt = experiment( longitude_extent=longitude_extent, latitude_extent=latitude_extent, @@ -60,10 +64,10 @@ def test_setup_bathymetry( number_vertical_layers=number_vertical_layers, layer_thickness_ratio=layer_thickness_ratio, depth=depth, - mom_run_dir=mom_run_dir, - mom_input_dir=mom_input_dir, - toolpath_dir=toolpath_dir, - grid_type=grid_type, + mom_run_dir=tmp_path / mom_run_dir, + mom_input_dir=tmp_path / mom_input_dir, + fre_tools_dir=fre_tools_dir, + hgrid_type=hgrid_type, ) ## Generate a bathymetry to use in tests @@ -93,65 +97,11 @@ def test_setup_bathymetry( longitude_coordinate_name="silly_lon", latitude_coordinate_name="silly_lat", vertical_coordinate_name="silly_depth", - minimum_layers=1, - chunks={"longitude": 10, "latitude": 10}, ) bathymetry_file.unlink() -def number_of_gridpoints(longitude_extent, latitude_extent, resolution): - nx = int((longitude_extent[-1] - longitude_extent[0]) / resolution) - ny = int((latitude_extent[-1] - latitude_extent[0]) / resolution) - - return nx, ny - - -def generate_temperature_arrays(nx, ny, number_vertical_layers): - - # temperatures close to 0 ᵒC - temp_in_C = np.random.randn(ny, nx, number_vertical_layers) - - temp_in_C_masked = np.copy(temp_in_C) - if int(ny / 4 + 4) < ny - 1 and int(nx / 3 + 4) < nx + 1: - temp_in_C_masked[ - int(ny / 3) : int(ny / 3 + 5), int(nx) : int(nx / 4 + 4), : - ] = float("nan") - else: - raise ValueError("use bigger domain") - - temp_in_K = np.copy(temp_in_C) + 273.15 - temp_in_K_masked = np.copy(temp_in_C_masked) + 273.15 - - # ensure we didn't mask the minimum temperature - if np.nanmin(temp_in_C_masked) == np.min(temp_in_C): - return temp_in_C, temp_in_C_masked, temp_in_K, temp_in_K_masked - else: - return generate_temperature_arrays(nx, ny, number_vertical_layers) - - -def generate_silly_coords( - longitude_extent, latitude_extent, resolution, depth, number_vertical_layers -): - nx, ny = number_of_gridpoints(longitude_extent, latitude_extent, resolution) - - horizontal_buffer = 5 - - silly_lat = np.linspace( - latitude_extent[0] - horizontal_buffer, - latitude_extent[1] + horizontal_buffer, - ny, - ) - silly_lon = np.linspace( - longitude_extent[0] - horizontal_buffer, - longitude_extent[1] + horizontal_buffer, - nx, - ) - silly_depth = np.linspace(0, depth, number_vertical_layers) - - return silly_lat, silly_lon, silly_depth - - longitude_extent = [-5, 3] latitude_extent = (0, 10) date_range = ["2003-01-01 00:00:00", "2003-01-01 00:00:00"] @@ -160,36 +110,12 @@ def generate_silly_coords( layer_thickness_ratio = 1 depth = 1000 -silly_lat, silly_lon, silly_depth = generate_silly_coords( - longitude_extent, latitude_extent, resolution, depth, number_vertical_layers -) - -dims = ["silly_lat", "silly_lon", "silly_depth"] - -coords = {"silly_lat": silly_lat, "silly_lon": silly_lon, "silly_depth": silly_depth} - -mom_run_dir = "rundir/" -mom_input_dir = "inputdir/" -toolpath_dir = "toolpath" -grid_type = "even_spacing" - -nx, ny = number_of_gridpoints(longitude_extent, latitude_extent, resolution) - -temp_in_C, temp_in_C_masked, temp_in_K, temp_in_K_masked = generate_temperature_arrays( - nx, ny, number_vertical_layers -) - -temp_C = xr.DataArray(temp_in_C, dims=dims, coords=coords) -temp_K = xr.DataArray(temp_in_K, dims=dims, coords=coords) -temp_C_masked = xr.DataArray(temp_in_C_masked, dims=dims, coords=coords) -temp_K_masked = xr.DataArray(temp_in_K_masked, dims=dims, coords=coords) - -maximum_temperature_in_C = np.max(temp_in_C) - @pytest.mark.parametrize( "temp_dataarray_initial_condition", - [temp_C, temp_C_masked, temp_K, temp_K_masked], + get_temperature_dataarrays( + longitude_extent, latitude_extent, resolution, number_vertical_layers, depth + ), ) @pytest.mark.parametrize( ( @@ -200,10 +126,8 @@ def generate_silly_coords( "number_vertical_layers", "layer_thickness_ratio", "depth", - "mom_run_dir", - "mom_input_dir", - "toolpath_dir", - "grid_type", + "fre_tools_dir", + "hgrid_type", ), [ ( @@ -214,8 +138,6 @@ def generate_silly_coords( number_vertical_layers, layer_thickness_ratio, depth, - "rundir/", - "inputdir/", "toolpath", "even_spacing", ), @@ -229,26 +151,15 @@ def test_ocean_forcing( number_vertical_layers, layer_thickness_ratio, depth, - mom_run_dir, - mom_input_dir, - toolpath_dir, - grid_type, + fre_tools_dir, + hgrid_type, temp_dataarray_initial_condition, tmp_path, + generate_silly_ic_dataset, ): - - silly_lat, silly_lon, silly_depth = generate_silly_coords( - longitude_extent, latitude_extent, resolution, depth, number_vertical_layers - ) - - dims = ["silly_lat", "silly_lon", "silly_depth"] - - coords = { - "silly_lat": silly_lat, - "silly_lon": silly_lon, - "silly_depth": silly_depth, - } - + dask.config.set(scheduler="single-threaded") + mom_run_dir = tmp_path / "rundir" + mom_input_dir = tmp_path / "inputdir" expt = experiment( longitude_extent=longitude_extent, latitude_extent=latitude_extent, @@ -257,48 +168,22 @@ def test_ocean_forcing( number_vertical_layers=number_vertical_layers, layer_thickness_ratio=layer_thickness_ratio, depth=depth, - mom_run_dir=mom_run_dir, - mom_input_dir=mom_input_dir, - toolpath_dir=toolpath_dir, - grid_type=grid_type, + mom_run_dir=tmp_path / mom_run_dir, + mom_input_dir=tmp_path / mom_input_dir, + fre_tools_dir=fre_tools_dir, + hgrid_type=hgrid_type, ) - ## Generate some initial condition to test on - - nx, ny = number_of_gridpoints(longitude_extent, latitude_extent, resolution) - # initial condition includes, temp, salt, eta, u, v - initial_cond = xr.Dataset( - { - "eta": xr.DataArray( - np.random.random((ny, nx)), - dims=["silly_lat", "silly_lon"], - coords={ - "silly_lat": silly_lat, - "silly_lon": silly_lon, - }, - ), - "temp": temp_dataarray_initial_condition, - "salt": xr.DataArray( - np.random.random((ny, nx, number_vertical_layers)), - dims=dims, - coords=coords, - ), - "u": xr.DataArray( - np.random.random((ny, nx, number_vertical_layers)), - dims=dims, - coords=coords, - ), - "v": xr.DataArray( - np.random.random((ny, nx, number_vertical_layers)), - dims=dims, - coords=coords, - ), - } + initial_cond = generate_silly_ic_dataset( + longitude_extent, + latitude_extent, + resolution, + number_vertical_layers, + depth, + temp_dataarray_initial_condition, ) - # Generate boundary forcing - initial_cond.to_netcdf(tmp_path / "ic_unprocessed") initial_cond.close() varnames = { @@ -312,7 +197,7 @@ def test_ocean_forcing( "tracers": {"temp": "temp", "salt": "salt"}, } - expt.initial_condition( + expt.setup_initial_condition( tmp_path / "ic_unprocessed", varnames, arakawa_grid="A", @@ -320,9 +205,10 @@ def test_ocean_forcing( # ensure that temperature is in degrees C assert np.nanmin(expt.ic_tracers["temp"]) < 100.0 - + maximum_temperature_in_C = np.max(temp_dataarray_initial_condition) # max(temp) can be less maximum_temperature_in_C due to re-gridding assert np.nanmax(expt.ic_tracers["temp"]) <= maximum_temperature_in_C + dask.config.set(scheduler=None) @pytest.mark.parametrize( @@ -334,10 +220,8 @@ def test_ocean_forcing( "number_vertical_layers", "layer_thickness_ratio", "depth", - "mom_run_dir", - "mom_input_dir", - "toolpath_dir", - "grid_type", + "fre_tools_dir", + "hgrid_type", ), [ ( @@ -348,8 +232,6 @@ def test_ocean_forcing( 5, 1, 1000, - "rundir/", - "inputdir/", "toolpath", "even_spacing", ), @@ -363,10 +245,8 @@ def test_rectangular_boundaries( number_vertical_layers, layer_thickness_ratio, depth, - mom_run_dir, - mom_input_dir, - toolpath_dir, - grid_type, + fre_tools_dir, + hgrid_type, tmp_path, ): @@ -445,7 +325,8 @@ def test_rectangular_boundaries( ) eastern_boundary.to_netcdf(tmp_path / "east_unprocessed.nc") eastern_boundary.close() - + mom_run_dir = tmp_path / "rundir" + mom_input_dir = tmp_path / "inputdir" expt = experiment( longitude_extent=longitude_extent, latitude_extent=latitude_extent, @@ -454,10 +335,11 @@ def test_rectangular_boundaries( number_vertical_layers=number_vertical_layers, layer_thickness_ratio=layer_thickness_ratio, depth=depth, - mom_run_dir=mom_run_dir, - mom_input_dir=mom_input_dir, - toolpath_dir=toolpath_dir, - grid_type=grid_type, + mom_run_dir=tmp_path / mom_run_dir, + mom_input_dir=tmp_path / mom_input_dir, + fre_tools_dir=fre_tools_dir, + hgrid_type=hgrid_type, + boundaries=["east"], ) varnames = { @@ -470,5 +352,4 @@ def test_rectangular_boundaries( "v": "v", "tracers": {"temp": "temp", "salt": "salt"}, } - - expt.rectangular_boundaries(tmp_path, varnames, ["east"]) + expt.setup_ocean_state_boundaries(tmp_path, varnames) diff --git a/tests/test_grid_generation.py b/tests/test_grid_generation.py index d5158420..11bc7587 100644 --- a/tests/test_grid_generation.py +++ b/tests/test_grid_generation.py @@ -2,7 +2,7 @@ import pytest from regional_mom6 import hyperbolictan_thickness_profile -from regional_mom6 import rectangular_hgrid +from regional_mom6 import generate_rectangular_hgrid from regional_mom6 import longitude_slicer from regional_mom6.utils import angle_between @@ -129,7 +129,7 @@ def test_quadrilateral_areas(lat, lon, true_area): ], ) def test_rectangular_hgrid(lat, lon): - assert isinstance(rectangular_hgrid(lat, lon), xr.Dataset) + assert isinstance(generate_rectangular_hgrid(lon, lat), xr.Dataset) def test_longitude_slicer(): diff --git a/tests/test_regridding.py b/tests/test_regridding.py new file mode 100644 index 00000000..40143fab --- /dev/null +++ b/tests/test_regridding.py @@ -0,0 +1,279 @@ +import regional_mom6 as rmom6 +import regional_mom6.rotation as rot +import regional_mom6.regridding as rgd +import pytest +import xarray as xr +import numpy as np + + +# Not testing get_arakawa_c_points, coords, & create_regridder +def test_smoke_untested_funcs(get_curvilinear_hgrid, generate_silly_vt_dataset): + hgrid = get_curvilinear_hgrid + ds = generate_silly_vt_dataset + ds["lat"] = ds.silly_lat + ds["lon"] = ds.silly_lat + assert rgd.get_hgrid_arakawa_c_points(hgrid, "t") + assert rgd.coords(hgrid, "north", "segment_002") + assert rgd.create_regridder(ds, ds) + + +def test_fill_missing_data(generate_silly_vt_dataset): + """ + Only testing forward fill for now + """ + ds = generate_silly_vt_dataset + ds["temp"][0, 0, 6:10, 0] = np.nan + + ds = rgd.fill_missing_data(ds, "silly_depth", fill="f") + + assert ( + ds["temp"][0, 0, 6:10, 0] == (ds["temp"][0, 0, 5, 0]) + ).all() # Assert if we are forward filling in time + + ds_2 = generate_silly_vt_dataset + ds_2["temp"][0, 0, 6:10, 0] = ds["temp"][0, 0, 5, 0] + assert (ds["temp"] == (ds_2["temp"])).all() # Assert everything else is the same + + +def test_add_or_update_time_dim(generate_silly_vt_dataset): + ds = generate_silly_vt_dataset + ds = rgd.add_or_update_time_dim(ds, xr.DataArray([0])) + + assert ds["time"].values == [0] # Assert time is added + assert ds["temp"].dims[0] == "time" # Check time is first dim + + +def test_generate_dz(generate_silly_vt_dataset): + ds = generate_silly_vt_dataset + dz = rgd.generate_dz(ds, "silly_depth") + z = np.linspace(0, 1000, 10) + dz_check = np.full(z.shape, z[1] - z[0]) + assert ( + (dz.values - dz_check) < 0.00001 + ).all() # Assert dz is generated correctly (some rounding leniency) + + +def test_add_secondary_dimension(get_curvilinear_hgrid, generate_silly_vt_dataset): + ds = generate_silly_vt_dataset + hgrid = get_curvilinear_hgrid + + # N/S Boundary + coords = rgd.coords(hgrid, "north", "segment_002") + ds = rgd.add_secondary_dimension(ds, "temp", coords, "segment_002") + assert ds["temp"].dims == ( + "silly_lat", + "ny_segment_002", + "silly_lon", + "silly_depth", + "time", + ) + + # E/W Boundary + coords = rgd.coords(hgrid, "east", "segment_003") + ds = generate_silly_vt_dataset + ds = rgd.add_secondary_dimension(ds, "v", coords, "segment_003") + assert ds["v"].dims == ( + "silly_lat", + "silly_lon", + "nx_segment_003", + "silly_depth", + "time", + ) + + # Beginning + ds = generate_silly_vt_dataset + ds = rgd.add_secondary_dimension( + ds, "temp", coords, "segment_003", to_beginning=True + ) + assert ds["temp"].dims[0] == "nx_segment_003" + + # NZ dim E/W Boundary + ds = generate_silly_vt_dataset + ds = ds.rename({"silly_depth": "nz"}) + ds = rgd.add_secondary_dimension(ds, "u", coords, "segment_003") + assert ds["u"].dims == ( + "silly_lat", + "silly_lon", + "nz", + "nx_segment_003", + "time", + ) + + +def test_vertical_coordinate_encoding(generate_silly_vt_dataset): + ds = generate_silly_vt_dataset + ds = rgd.vertical_coordinate_encoding(ds, "temp", "segment_002", "silly_depth") + assert "nz_segment_002_temp" in ds["temp"].dims + assert "nz_segment_002_temp" in ds + assert ( + ds["nz_segment_002_temp"] == np.arange(ds[f"nz_segment_002_temp"].size) + ).all() + + +def test_generate_layer_thickness(generate_silly_vt_dataset): + ds = generate_silly_vt_dataset + ds["temp"] = ds["temp"].transpose("time", "silly_depth", "silly_lat", "silly_lon") + ds = rgd.generate_layer_thickness(ds, "temp", "segment_002", "silly_depth") + assert "dz_temp" in ds + assert ds["dz_temp"].dims == ("time", "nz_temp", "ny_segment_002", "nx_segment_002") + assert ( + ds["temp"]["silly_depth"].shape == ds["dz_temp"]["nz_temp"].shape + ) # Make sure the depth dimension was broadcasted correctly + + +def test_generate_encoding(generate_silly_vt_dataset): + ds = generate_silly_vt_dataset + encoding_dict = {} + ds["temp_segment_002"] = ds["temp"] + ds.coords["temp_segment_003_nz_"] = ds.silly_depth + encoding_dict = rgd.generate_encoding(ds, encoding_dict, default_fill_value="-3") + assert ( + encoding_dict["temp_segment_002"]["_FillValue"] == "-3" + and "dtype" not in encoding_dict["temp_segment_002"] + ) + assert encoding_dict["temp_segment_003_nz_"]["dtype"] == "int32" + + +def test_get_boundary_mask(get_curvilinear_hgrid): + hgrid = get_curvilinear_hgrid + t_points = rgd.get_hgrid_arakawa_c_points(hgrid, "t") + bathy = hgrid.isel(nyp=t_points.t_points_y, nxp=t_points.t_points_x) + bathy["depth"] = (("t_points_y", "t_points_x"), (np.full(bathy.x.shape, 0))) + north_mask = rgd.get_boundary_mask( + hgrid, + bathy, + "north", + "segment_002", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + south_mask = rgd.get_boundary_mask( + hgrid, + bathy, + "south", + "segment_001", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + east_mask = rgd.get_boundary_mask( + hgrid, + bathy, + "east", + "segment_003", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + west_mask = rgd.get_boundary_mask( + hgrid, + bathy, + "west", + "segment_004", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + + # Check corner property of mask, and ensure each direction is following what we expect + for mask in [north_mask, south_mask, east_mask, west_mask]: + assert ( + mask[0] == 0 and mask[-1] == 0 + ) # Ensure Corners are oceans and set to zero for zeroing out values + assert np.isnan(mask[1:-1]).all() # Ensure all other points are land + assert north_mask.shape == (hgrid.x[-1].shape) # Ensure mask is the right shape + assert south_mask.shape == (hgrid.x[0].shape) # Ensure mask is the right shape + assert east_mask.shape == (hgrid.x[:, -1].shape) # Ensure mask is the right shape + assert west_mask.shape == (hgrid.x[:, 0].shape) # Ensure mask is the right shape + + ## Now we check if the coast masking is correct (remember we make 3 cells into the coast be ocean) + start_ind = 6 + end_ind = 9 + for i in range(start_ind, end_ind + 1): + bathy["depth"][-1][i] = 15 + north_mask = rgd.get_boundary_mask( + hgrid, + bathy, + "north", + "segment_002", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + assert ( + north_mask[0] == 0 and north_mask[-1] == 0 + ) # Ensure Corners are oceans and zeroed out if land + assert ( + north_mask[(((start_ind * 2) + 1)) : (((end_ind * 2) + 1) + 1)] == 1 + ).all() # Ensure coasts are ocean with a 3 cell buffer (remeber mask is on the hgrid boundary) so (6 *2 +2) - 3 -> (9 *2 +2) + 3 + assert ( + north_mask[(((start_ind * 2) + 1) - 3) : (((start_ind * 2) + 1))] == 0 + ).all() # Left Side + assert ( + north_mask[(((end_ind * 2) + 1) + 1) : (((end_ind * 2) + 1) + 3 + 1)] == 0 + ).all() # Right Side + + ## On E/W + start_ind = 6 + end_ind = 9 + for i in range(start_ind, end_ind + 1): + bathy["depth"][:, 0][i] = 15 + west_mask = rgd.get_boundary_mask( + hgrid, + bathy, + "west", + "segment_004", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + assert west_mask[0] == 0 and west_mask[-1] == 0 # Ensure Corners are oceans + assert ( + west_mask[(((start_ind * 2) + 1)) : (((end_ind * 2) + 1) + 1)] == 1 + ).all() # Ensure coasts are ocean with a 3 cell buffer (remeber mask is on the hgrid boundary) so (6 *2 +2) - 3 -> (9 *2 +2) + 3 + assert ( + west_mask[(((start_ind * 2) + 1) - 3) : (((start_ind * 2) + 1))] == 0 + ).all() # Ensure left side is zeroed out + assert ( + west_mask[(((end_ind * 2) + 1) + 1) : (((end_ind * 2) + 1) + 3 + 1)] == 0 + ).all() # Right Side is zeroed out + + +def test_mask_dataset(get_curvilinear_hgrid): + hgrid = get_curvilinear_hgrid + t_points = rgd.get_hgrid_arakawa_c_points(hgrid, "t") + bathy = hgrid.isel(nyp=t_points.t_points_y, nxp=t_points.t_points_x) + bathy["depth"] = (("t_points_y", "t_points_x"), (np.full(bathy.x.shape, 0))) + ds = hgrid.copy(deep=True) + ds = ds.drop_vars(("tile", "area", "y", "x", "angle_dx", "dy", "dx")) + ds["temp"] = (("t_points_y", "t_points_x"), (np.full(hgrid.x.shape, 100))) + ds["temp"] = ds["temp"].isel(t_points_y=-1) + start_ind = 6 + end_ind = 9 + for i in range(start_ind, end_ind + 1): + bathy["depth"][-1][i] = 15 + + ds["temp"][ + start_ind * 2 + 2 + ] = ( + np.nan + ) # Add a missing value not in the land mask to make sure it is filled with a dummy value + ds["temp"] = ds["temp"].expand_dims("nz_temp", axis=0) + ds = rgd.mask_dataset( + ds, + hgrid, + bathy, + "north", + "segment_002", + y_dim_name="t_points_y", + x_dim_name="t_points_x", + ) + + assert ( + np.isnan(ds["temp"][0][start_ind * 2 + 2]) == False + ) # Ensure missing value was filled + assert ( + np.isnan( + ds["temp"][0][(((start_ind * 2) + 1) - 3) : (((end_ind * 2) + 1) + 3 + 1)] + ) + ).all() == False # Ensure data is kept in ocean area + assert ( + np.isnan(ds["temp"][0][1 : (((start_ind * 2) + 1) - 3)]) + ).all() == True and ( + np.isnan(ds["temp"][0][(((end_ind * 2) + 1) + 3 + 1) : -1]) + ).all() == True # Ensure data is not in land area diff --git a/tests/test_rotation.py b/tests/test_rotation.py new file mode 100644 index 00000000..db89c503 --- /dev/null +++ b/tests/test_rotation.py @@ -0,0 +1,286 @@ +import regional_mom6 as rmom6 +import regional_mom6.rotation as rot +import regional_mom6.regridding as rgd +import pytest +import xarray as xr +import numpy as np +import os + + +def test_get_curvilinear_hgrid_fixture(get_curvilinear_hgrid): + # If the fixture fails to find the file, the test will be skipped. + assert get_curvilinear_hgrid is not None + + +def test_expanded_hgrid_generation(get_curvilinear_hgrid): + hgrid = get_curvilinear_hgrid + expanded_hgrid = rot.create_expanded_hgrid(hgrid) + + # Check Size + assert len(expanded_hgrid.nxp) == (len(hgrid.nxp) + 2) + assert len(expanded_hgrid.nyp) == (len(hgrid.nyp) + 2) + + # Check pseudo_hgrid keeps the same values + assert (expanded_hgrid.x.values[1:-1, 1:-1] == hgrid.x.values).all() + assert (expanded_hgrid.y.values[1:-1, 1:-1] == hgrid.y.values).all() + + # Check extra boundary has realistic values + diff_check = 1 + assert ( + ( + expanded_hgrid.x.values[0, 1:-1] + - (hgrid.x.values[0, :] - (hgrid.x.values[1, :] - hgrid.x.values[0, :])) + ) + < diff_check + ).all() + assert ( + ( + expanded_hgrid.x.values[1:-1, 0] + - (hgrid.x.values[:, 0] - (hgrid.x.values[:, 1] - hgrid.x.values[:, 0])) + ) + < diff_check + ).all() + assert ( + ( + expanded_hgrid.x.values[-1, 1:-1] + - (hgrid.x.values[-1, :] - (hgrid.x.values[-2, :] - hgrid.x.values[-1, :])) + ) + < diff_check + ).all() + assert ( + ( + expanded_hgrid.x.values[1:-1, -1] + - (hgrid.x.values[:, -1] - (hgrid.x.values[:, -2] - hgrid.x.values[:, -1])) + ) + < diff_check + ).all() + + # Check corners for the same... + assert ( + expanded_hgrid.x.values[0, 0] + - (hgrid.x.values[0, 0] - (hgrid.x.values[1, 1] - hgrid.x.values[0, 0])) + ) < diff_check + assert ( + expanded_hgrid.x.values[-1, 0] + - (hgrid.x.values[-1, 0] - (hgrid.x.values[-2, 1] - hgrid.x.values[-1, 0])) + ) < diff_check + assert ( + expanded_hgrid.x.values[0, -1] + - (hgrid.x.values[0, -1] - (hgrid.x.values[1, -2] - hgrid.x.values[0, -1])) + ) < diff_check + assert ( + expanded_hgrid.x.values[-1, -1] + - (hgrid.x.values[-1, -1] - (hgrid.x.values[-2, -2] - hgrid.x.values[-1, -1])) + ) < diff_check + + # Same for y + assert ( + ( + expanded_hgrid.y.values[0, 1:-1] + - (hgrid.y.values[0, :] - (hgrid.y.values[1, :] - hgrid.y.values[0, :])) + ) + < diff_check + ).all() + assert ( + ( + expanded_hgrid.y.values[1:-1, 0] + - (hgrid.y.values[:, 0] - (hgrid.y.values[:, 1] - hgrid.y.values[:, 0])) + ) + < diff_check + ).all() + assert ( + ( + expanded_hgrid.y.values[-1, 1:-1] + - (hgrid.y.values[-1, :] - (hgrid.y.values[-2, :] - hgrid.y.values[-1, :])) + ) + < diff_check + ).all() + assert ( + ( + expanded_hgrid.y.values[1:-1, -1] + - (hgrid.y.values[:, -1] - (hgrid.y.values[:, -2] - hgrid.y.values[:, -1])) + ) + < diff_check + ).all() + + assert ( + expanded_hgrid.y.values[0, 0] + - (hgrid.y.values[0, 0] - (hgrid.y.values[1, 1] - hgrid.y.values[0, 0])) + ) < diff_check + assert ( + expanded_hgrid.y.values[-1, 0] + - (hgrid.y.values[-1, 0] - (hgrid.y.values[-2, 1] - hgrid.y.values[-1, 0])) + ) < diff_check + assert ( + expanded_hgrid.y.values[0, -1] + - (hgrid.y.values[0, -1] - (hgrid.y.values[1, -2] - hgrid.y.values[0, -1])) + ) < diff_check + assert ( + expanded_hgrid.y.values[-1, -1] + - (hgrid.y.values[-1, -1] - (hgrid.y.values[-2, -2] - hgrid.y.values[-1, -1])) + ) < diff_check + + return + + +def test_mom6_angle_calculation_method(get_curvilinear_hgrid): + """ + Check no rotation, up tilt, down tilt. + """ + + # Check no rotation + top_left = xr.Dataset( + { + "x": (("nyp", "nxp"), [[0]]), + "y": (("nyp", "nxp"), [[1]]), + } + ) + top_right = xr.Dataset( + { + "x": (("nyp", "nxp"), [[1]]), + "y": (("nyp", "nxp"), [[1]]), + } + ) + bottom_left = xr.Dataset( + { + "x": (("nyp", "nxp"), [[0]]), + "y": (("nyp", "nxp"), [[0]]), + } + ) + bottom_right = xr.Dataset( + { + "x": (("nyp", "nxp"), [[1]]), + "y": (("nyp", "nxp"), [[0]]), + } + ) + point = xr.Dataset( + { + "x": (("nyp", "nxp"), [[0.5]]), + "y": (("nyp", "nxp"), [[0.5]]), + } + ) + + assert ( + rot.mom6_angle_calculation_method( + 2, top_left, top_right, bottom_left, bottom_right, point + ) + == 0 + ) + + # Angled + hgrid = get_curvilinear_hgrid + ds_t = rgd.get_hgrid_arakawa_c_points(hgrid, "t") + ds_q = rgd.get_hgrid_arakawa_c_points(hgrid, "q") + + # Reformat into x, y comps + t_points = xr.Dataset( + { + "x": (("nyp", "nxp"), ds_t.tlon.data), + "y": (("nyp", "nxp"), ds_t.tlat.data), + } + ) + q_points = xr.Dataset( + { + "x": (("nyp", "nxp"), ds_q.qlon.data), + "y": (("nyp", "nxp"), ds_q.qlat.data), + } + ) + assert ( + ( + rot.mom6_angle_calculation_method( + hgrid.x.max() - hgrid.x.min(), + q_points.isel(nyp=slice(1, None), nxp=slice(0, -1)), + q_points.isel(nyp=slice(1, None), nxp=slice(1, None)), + q_points.isel(nyp=slice(0, -1), nxp=slice(0, -1)), + q_points.isel(nyp=slice(0, -1), nxp=slice(1, None)), + t_points, + ) + - hgrid["angle_dx"].isel(nyp=ds_t.t_points_y, nxp=ds_t.t_points_x).values + ) + < 1 + ).all() + + return + + +def test_initialize_grid_rotation_angle(get_curvilinear_hgrid): + """ + Generate a curvilinear grid and test the grid rotation angle at t_points based on what we pass to generate_curvilinear_grid + """ + hgrid = get_curvilinear_hgrid + angle = rot.initialize_grid_rotation_angle(hgrid) + ds_t = rgd.get_hgrid_arakawa_c_points(hgrid, "t") + assert ( + ( + angle.values + - hgrid["angle_dx"].isel(nyp=ds_t.t_points_y, nxp=ds_t.t_points_x).values + ) + < 1 + ).all() # Angle is correct + assert angle.values.shape == ds_t.tlon.shape # Shape is correct + return + + +def test_initialize_grid_rotation_angle_using_expanded_hgrid(get_curvilinear_hgrid): + """ + Generate a curvilinear grid and test the grid rotation angle at t_points based on what we pass to generate_curvilinear_grid + """ + hgrid = get_curvilinear_hgrid + angle = rot.initialize_grid_rotation_angles_using_expanded_hgrid(hgrid) + + assert (angle.values - hgrid.angle_dx < 1).all() + assert angle.values.shape == hgrid.x.shape + return + + +def test_get_rotation_angle(get_curvilinear_hgrid, get_rectilinear_hgrid): + """ + Generate a curvilinear grid and test the grid rotation angle at t_points based on what we pass to generate to generate_curvilinear_grid + """ + curved_hgrid = get_curvilinear_hgrid + rect_hgrid = get_rectilinear_hgrid + + o = None + rotational_method = rot.RotationMethod.NO_ROTATION + angle = rot.get_rotation_angle(rotational_method, rect_hgrid, orientation=o) + assert angle.shape == rect_hgrid.x.shape + assert (angle.values == 0).all() + + rotational_method == rot.RotationMethod.NO_ROTATION + with pytest.raises( + ValueError, match="NO_ROTATION method only works with rectilinear grids" + ): + angle = rot.get_rotation_angle(rotational_method, curved_hgrid, orientation=o) + + rotational_method = rot.RotationMethod.GIVEN_ANGLE + angle = rot.get_rotation_angle(rotational_method, curved_hgrid, orientation=o) + assert angle.shape == curved_hgrid.x.shape + assert (angle.values == curved_hgrid.angle_dx).all() + angle = rot.get_rotation_angle(rotational_method, rect_hgrid, orientation=o) + assert angle.shape == rect_hgrid.x.shape + assert (angle.values == 0).all() + + rotational_method = rot.RotationMethod.EXPAND_GRID + angle = rot.get_rotation_angle(rotational_method, curved_hgrid, orientation=o) + assert angle.shape == curved_hgrid.x.shape + assert ( + abs(angle.values - curved_hgrid.angle_dx) < 1 + ).all() # There shouldn't be large differences + angle = rot.get_rotation_angle(rotational_method, rect_hgrid, orientation=o) + assert angle.shape == rect_hgrid.x.shape + assert (angle.values == 0).all() + + # Check if o is boundary that the shape is of a boundary + o = "north" + rotational_method = rot.RotationMethod.NO_ROTATION + angle = rot.get_rotation_angle(rotational_method, rect_hgrid, orientation=o) + assert angle.shape == rect_hgrid.x[-1].shape + assert (angle.values == 0).all() + rotational_method = rot.RotationMethod.EXPAND_GRID + angle = rot.get_rotation_angle(rotational_method, rect_hgrid, orientation=o) + assert angle.shape == rect_hgrid.x[-1].shape + assert (angle.values == 0).all() + rotational_method = rot.RotationMethod.GIVEN_ANGLE + angle = rot.get_rotation_angle(rotational_method, rect_hgrid, orientation=o) + assert angle.shape == rect_hgrid.x[-1].shape + assert (angle.values == 0).all() diff --git a/tests/test_tides_and_parameter.py b/tests/test_tides_and_parameter.py new file mode 100644 index 00000000..1614862a --- /dev/null +++ b/tests/test_tides_and_parameter.py @@ -0,0 +1,193 @@ +import regional_mom6 as rmom6 +import os +import pytest +import logging +from pathlib import Path +import xarray as xr +import numpy as np +import shutil +import importlib + + +@pytest.fixture(scope="module") +def dummy_tidal_data(): + nx = 100 + ny = 100 + nc = 15 + nct = 4 + + # Define tidal constituents + con_list = [ + "m2 ", + "s2 ", + "n2 ", + "k2 ", + "k1 ", + "o1 ", + "p1 ", + "q1 ", + "mm ", + "mf ", + "m4 ", + "mn4 ", + "ms4 ", + "2n2 ", + "s1 ", + ] + con_data = np.array([list(con) for con in con_list], dtype="S1") + + # Generate random data for the variables + lon_z_data = np.tile(np.linspace(-180, 180, nx), (ny, 1)).T + lat_z_data = np.tile(np.linspace(-90, 90, ny), (nx, 1)) + ha_data = np.random.rand(nc, nx, ny) + hp_data = np.random.rand(nc, nx, ny) * 360 # Random phases between 0 and 360 + hRe_data = np.random.rand(nc, nx, ny) + hIm_data = np.random.rand(nc, nx, ny) + + # Create the xarray dataset + ds_h = xr.Dataset( + { + "con": (["nc", "nct"], con_data), + "lon_z": (["nx", "ny"], lon_z_data), + "lat_z": (["nx", "ny"], lat_z_data), + "ha": (["nc", "nx", "ny"], ha_data), + "hp": (["nc", "nx", "ny"], hp_data), + "hRe": (["nc", "nx", "ny"], hRe_data), + "hIm": (["nc", "nx", "ny"], hIm_data), + }, + coords={ + "nc": np.arange(nc), + "nct": np.arange(nct), + "nx": np.arange(nx), + "ny": np.arange(ny), + }, + attrs={ + "type": "Fake OTIS tidal elevation file", + "title": "Fake TPXO9.v1 2018 tidal elevation file", + }, + ) + + # Generate random data for the variables for u_tpxo9.v1 + lon_u_data = ( + np.random.rand(nx, ny) * 360 - 180 + ) # Random longitudes between -180 and 180 + lat_u_data = ( + np.random.rand(nx, ny) * 180 - 90 + ) # Random latitudes between -90 and 90 + lon_v_data = ( + np.random.rand(nx, ny) * 360 - 180 + ) # Random longitudes between -180 and 180 + lat_v_data = ( + np.random.rand(nx, ny) * 180 - 90 + ) # Random latitudes between -90 and 90 + Ua_data = np.random.rand(nc, nx, ny) + ua_data = np.random.rand(nc, nx, ny) + up_data = np.random.rand(nc, nx, ny) * 360 # Random phases between 0 and 360 + Va_data = np.random.rand(nc, nx, ny) + va_data = np.random.rand(nc, nx, ny) + vp_data = np.random.rand(nc, nx, ny) * 360 # Random phases between 0 and 360 + URe_data = np.random.rand(nc, nx, ny) + UIm_data = np.random.rand(nc, nx, ny) + VRe_data = np.random.rand(nc, nx, ny) + VIm_data = np.random.rand(nc, nx, ny) + + # Create the xarray dataset for u_tpxo9.v1 + ds_u = xr.Dataset( + { + "con": (["nc", "nct"], con_data), + "lon_u": (["nx", "ny"], lon_u_data), + "lat_u": (["nx", "ny"], lat_u_data), + "lon_v": (["nx", "ny"], lon_v_data), + "lat_v": (["nx", "ny"], lat_v_data), + "Ua": (["nc", "nx", "ny"], Ua_data), + "ua": (["nc", "nx", "ny"], ua_data), + "up": (["nc", "nx", "ny"], up_data), + "Va": (["nc", "nx", "ny"], Va_data), + "va": (["nc", "nx", "ny"], va_data), + "vp": (["nc", "nx", "ny"], vp_data), + "URe": (["nc", "nx", "ny"], URe_data), + "UIm": (["nc", "nx", "ny"], UIm_data), + "VRe": (["nc", "nx", "ny"], VRe_data), + "VIm": (["nc", "nx", "ny"], VIm_data), + }, + coords={ + "nc": np.arange(nc), + "nct": np.arange(nct), + "nx": np.arange(nx), + "ny": np.arange(ny), + }, + attrs={ + "type": "Fake OTIS tidal transport file", + "title": "Fake TPXO9.v1 2018 WE/SN transports/currents file", + }, + ) + + return ds_h, ds_u + + +def test_tides(dummy_tidal_data, tmp_path): + """ + Test setup_boundary_tides function. + """ + expt_name = "testing" + + expt = rmom6.experiment.create_empty( + expt_name=expt_name, + mom_input_dir=tmp_path, + mom_run_dir=tmp_path, + ) + # Generate Fake Tidal Data + ds_h, ds_u = dummy_tidal_data + + # Save to Fake Folder + ds_h.to_netcdf(tmp_path / "h_fake_tidal_data.nc") + ds_u.to_netcdf(tmp_path / "u_fake_tidal_data.nc") + + # Set other required variables needed in setup_tides + + # Lat Long + expt.longitude_extent = (-5, 5) + expt.latitude_extent = (0, 30) + # Grid Type + expt.hgrid_type = "even_spacing" + # Dates + expt.date_range = ("2000-01-01", "2000-01-02") + expt.segments = {} + # Generate Hgrid Data + expt.resolution = 0.1 + expt.hgrid = expt._make_hgrid() + # Create Forcing Folder + os.makedirs(tmp_path / "forcing", exist_ok=True) + + expt.setup_boundary_tides( + tmp_path / "h_fake_tidal_data.nc", + tmp_path / "u_fake_tidal_data.nc", + ) + + +def test_change_MOM_parameter(tmp_path): + """ + Test the change MOM parameter function, as well as read_MOM_file and write_MOM_file under the hood. + """ + expt_name = "testing" + + expt = rmom6.experiment.create_empty( + expt_name=expt_name, + mom_input_dir=tmp_path, + mom_run_dir=tmp_path, + ) + # Copy over the MOM Files to the dump_files_dir + base_run_dir = Path( + os.path.join( + importlib.resources.files("regional_mom6").parent, + "demos", + "premade_run_directories", + ) + ) + shutil.copytree(base_run_dir / "common_files", expt.mom_run_dir, dirs_exist_ok=True) + MOM_override_dict = expt.read_MOM_file_as_dict("MOM_override") + og = expt.change_MOM_parameter("DT", "30", "COOL COMMENT") + MOM_override_dict_new = expt.read_MOM_file_as_dict("MOM_override") + assert MOM_override_dict_new["DT"]["value"] == "30" + assert MOM_override_dict["DT"]["value"] == og + assert MOM_override_dict_new["DT"]["comment"] == "COOL COMMENT\n"