From c8ac4a8b923fea9f471e0c577625d2e7f3fd4743 Mon Sep 17 00:00:00 2001 From: Rafael Ravedutti <rafaelravedutti@gmail.com> Date: Tue, 12 Oct 2021 00:25:07 +0200 Subject: [PATCH] Apply proper changes for pairs to be used as a package Signed-off-by: Rafael Ravedutti <rafaelravedutti@gmail.com> --- LICENSE | 21 + examples/kernels | 834 ++++++++++++++++++ examples/kernels.pdf | Bin 0 -> 46823 bytes lift.py => examples/lift.py | 0 particle.py => examples/lj_embedded.py | 17 +- examples/lj_func.py | 45 + examples/lj_ns.cpp | 825 +++++++++++++++++ pyproject.toml | 6 + setup.py | 46 + {code_gen => src}/__init__.py | 0 pairs.py => src/pairs/__init__.py | 4 +- {coupling => src/pairs/code_gen}/__init__.py | 0 {code_gen => src/pairs/code_gen}/cgen.py | 40 +- {code_gen => src/pairs/code_gen}/printer.py | 0 {ir => src/pairs/coupling}/__init__.py | 0 {coupling => src/pairs/coupling}/parse_cpp.py | 10 +- {sim => src/pairs/graph}/__init__.py | 0 {graph => src/pairs/graph}/graphviz.py | 14 +- ir/operators.py => src/pairs/ir/__init__.py | 0 {ir => src/pairs/ir}/arrays.py | 16 +- {ir => src/pairs/ir}/assign.py | 8 +- {ir => src/pairs/ir}/ast_node.py | 2 +- {ir => src/pairs/ir}/bin_op.py | 10 +- {ir => src/pairs/ir}/block.py | 2 +- {ir => src/pairs/ir}/branches.py | 6 +- {ir => src/pairs/ir}/cast.py | 4 +- {ir => src/pairs/ir}/data_types.py | 0 {ir => src/pairs/ir}/functions.py | 6 +- {ir => src/pairs/ir}/layouts.py | 0 {ir => src/pairs/ir}/lit.py | 4 +- {ir => src/pairs/ir}/loops.py | 12 +- {ir => src/pairs/ir}/math.py | 4 +- {ir => src/pairs/ir}/memory.py | 6 +- {ir => src/pairs/ir}/mutator.py | 0 src/pairs/ir/operators.py | 0 {ir => src/pairs/ir}/properties.py | 14 +- {ir => src/pairs/ir}/select.py | 6 +- {ir => src/pairs/ir}/sizeof.py | 4 +- {ir => src/pairs/ir}/transform.py | 14 +- {ir => src/pairs/ir}/utils.py | 2 +- {ir => src/pairs/ir}/variables.py | 6 +- {ir => src/pairs/ir}/vector_expr.py | 6 +- {ir => src/pairs/ir}/visitor.py | 0 src/pairs/mapping/.funcs.py.swp | Bin 0 -> 16384 bytes src/pairs/mapping/__init__.py | 0 new_syntax.py => src/pairs/mapping/funcs.py | 55 +- src/pairs/runtime/__init__.py | 0 {runtime => src/pairs/runtime}/pairs.hpp | 0 .../pairs/runtime}/read_from_file.hpp | 0 {runtime => src/pairs/runtime}/vtk.hpp | 0 src/pairs/sim/__init__.py | 0 {sim => src/pairs/sim}/arrays.py | 4 +- {sim => src/pairs/sim}/cell_lists.py | 16 +- {sim => src/pairs/sim}/grid.py | 2 +- {sim => src/pairs/sim}/kernel_wrapper.py | 2 +- {sim => src/pairs/sim}/lattice.py | 4 +- {sim => src/pairs/sim}/neighbor_lists.py | 10 +- {sim => src/pairs/sim}/particle_simulation.py | 56 +- {sim => src/pairs/sim}/pbc.py | 12 +- {sim => src/pairs/sim}/properties.py | 10 +- {sim => src/pairs/sim}/read_from_file.py | 8 +- {sim => src/pairs/sim}/resize.py | 12 +- {sim => src/pairs/sim}/setup_wrapper.py | 2 +- {sim => src/pairs/sim}/timestep.py | 8 +- {sim => src/pairs/sim}/variables.py | 2 +- {sim => src/pairs/sim}/vtk.py | 6 +- .../pairs/transformations}/LICM.py | 10 +- src/pairs/transformations/__init__.py | 0 .../transformations}/prioritize_scalar_ops.py | 6 +- .../transformations}/set_used_bin_ops.py | 2 +- .../pairs/transformations}/simplify.py | 6 +- 71 files changed, 1973 insertions(+), 254 deletions(-) create mode 100644 LICENSE create mode 100644 examples/kernels create mode 100644 examples/kernels.pdf rename lift.py => examples/lift.py (100%) rename particle.py => examples/lj_embedded.py (65%) create mode 100644 examples/lj_func.py create mode 100644 examples/lj_ns.cpp create mode 100644 pyproject.toml create mode 100644 setup.py rename {code_gen => src}/__init__.py (100%) rename pairs.py => src/pairs/__init__.py (53%) rename {coupling => src/pairs/code_gen}/__init__.py (100%) rename {code_gen => src/pairs/code_gen}/cgen.py (93%) rename {code_gen => src/pairs/code_gen}/printer.py (100%) rename {ir => src/pairs/coupling}/__init__.py (100%) rename {coupling => src/pairs/coupling}/parse_cpp.py (97%) rename {sim => src/pairs/graph}/__init__.py (100%) rename {graph => src/pairs/graph}/graphviz.py (86%) rename ir/operators.py => src/pairs/ir/__init__.py (100%) rename {ir => src/pairs/ir}/arrays.py (94%) rename {ir => src/pairs/ir}/assign.py (83%) rename {ir => src/pairs/ir}/ast_node.py (88%) rename {ir => src/pairs/ir}/bin_op.py (96%) rename {ir => src/pairs/ir}/block.py (97%) rename {ir => src/pairs/ir}/branches.py (92%) rename {ir => src/pairs/ir}/cast.py (86%) rename {ir => src/pairs/ir}/data_types.py (100%) rename {ir => src/pairs/ir}/functions.py (85%) rename {ir => src/pairs/ir}/layouts.py (100%) rename {ir => src/pairs/ir}/lit.py (88%) rename {ir => src/pairs/ir}/loops.py (93%) rename {ir => src/pairs/ir}/math.py (89%) rename {ir => src/pairs/ir}/memory.py (88%) rename {ir => src/pairs/ir}/mutator.py (100%) create mode 100644 src/pairs/ir/operators.py rename {ir => src/pairs/ir}/properties.py (94%) rename {ir => src/pairs/ir}/select.py (77%) rename {ir => src/pairs/ir}/sizeof.py (69%) rename {ir => src/pairs/ir}/transform.py (92%) rename {ir => src/pairs/ir}/utils.py (82%) rename {ir => src/pairs/ir}/variables.py (93%) rename {ir => src/pairs/ir}/vector_expr.py (92%) rename {ir => src/pairs/ir}/visitor.py (100%) create mode 100644 src/pairs/mapping/.funcs.py.swp create mode 100644 src/pairs/mapping/__init__.py rename new_syntax.py => src/pairs/mapping/funcs.py (75%) create mode 100644 src/pairs/runtime/__init__.py rename {runtime => src/pairs/runtime}/pairs.hpp (100%) rename {runtime => src/pairs/runtime}/read_from_file.hpp (100%) rename {runtime => src/pairs/runtime}/vtk.hpp (100%) create mode 100644 src/pairs/sim/__init__.py rename {sim => src/pairs/sim}/arrays.py (82%) rename {sim => src/pairs/sim}/cell_lists.py (93%) rename {sim => src/pairs/sim}/grid.py (97%) rename {sim => src/pairs/sim}/kernel_wrapper.py (87%) rename {sim => src/pairs/sim}/lattice.py (95%) rename {sim => src/pairs/sim}/neighbor_lists.py (89%) rename {sim => src/pairs/sim}/particle_simulation.py (82%) rename {sim => src/pairs/sim}/pbc.py (94%) rename {sim => src/pairs/sim}/properties.py (84%) rename {sim => src/pairs/sim}/read_from_file.py (81%) rename {sim => src/pairs/sim}/resize.py (84%) rename {sim => src/pairs/sim}/setup_wrapper.py (87%) rename {sim => src/pairs/sim}/timestep.py (91%) rename {sim => src/pairs/sim}/variables.py (85%) rename {sim => src/pairs/sim}/vtk.py (84%) rename {transformations => src/pairs/transformations}/LICM.py (97%) create mode 100644 src/pairs/transformations/__init__.py rename {transformations => src/pairs/transformations}/prioritize_scalar_ops.py (93%) rename {transformations => src/pairs/transformations}/set_used_bin_ops.py (93%) rename {transformations => src/pairs/transformations}/simplify.py (90%) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5f40490 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Rafael Ravedutti Lucio Machado + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/examples/kernels b/examples/kernels new file mode 100644 index 0000000..6fcb7d8 --- /dev/null +++ b/examples/kernels @@ -0,0 +1,834 @@ +digraph AST { + node [color=lightblue2 style=filled] + size="6,6" + n139866028692368 [label=Block] + n139866028640632 [label=ParticleFor] + n139866028692368 -> n139866028640632 + n139866028694664 [label=ParticleFor] + n139866028692368 -> n139866028694664 + n139866028640632 [label=ParticleFor] + n139866028694720 [label="Iter(0)"] + n139866028640632 -> n139866028694720 + n139866028694888 [label=Block] + n139866028640632 -> n139866028694888 + n139866028694776 [label=0] + n139866028640632 -> n139866028694776 + n139866028694832 [label=0] + n139866028640632 -> n139866028694832 + n139866028694720 [label="Iter(0)"] + n139866028694888 [label=Block] + n139866028695056 [label=For] + n139866028694888 -> n139866028695056 + n139866028695336 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028695336 -> n139866028694720 + n139866028691808 [label=neighborlist_capacity] + n139866028695336 -> n139866028691808 + n139866028691808 [label=neighborlist_capacity] + n139866028692480 [label=PropertyAccess] + n139866028639904 [label=position] + n139866028692480 -> n139866028639904 + n139866028694720 [label="Iter(0)"] + n139866028692480 -> n139866028694720 + n139866028388816 [label="*"] + n139866028692480 -> n139866028388816 + n139866028390552 [label="+"] + n139866028692480 -> n139866028390552 + n139866028392120 [label="+"] + n139866028692480 -> n139866028392120 + n139866028639904 [label=position] + n139866028388816 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028388816 -> n139866028694720 + n139866028388872 [label=3] + n139866028388816 -> n139866028388872 + n139866028388872 [label=3] + n139866028390552 [label="+"] + n139866028390384 [label="*"] + n139866028390552 -> n139866028390384 + n139866028390608 [label=1] + n139866028390552 -> n139866028390608 + n139866028390384 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028390384 -> n139866028694720 + n139866028390440 [label=3] + n139866028390384 -> n139866028390440 + n139866028390440 [label=3] + n139866028390608 [label=1] + n139866028392120 [label="+"] + n139866028391952 [label="*"] + n139866028392120 -> n139866028391952 + n139866028392176 [label=2] + n139866028392120 -> n139866028392176 + n139866028391952 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028391952 -> n139866028694720 + n139866028392008 [label=3] + n139866028391952 -> n139866028392008 + n139866028392008 [label=3] + n139866028392176 [label=2] + n139866028216728 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028216728 -> n139866028694720 + n139866028216784 [label=3] + n139866028216728 -> n139866028216784 + n139866028216784 [label=3] + n139866028217512 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028217512 -> n139866028694720 + n139866028217568 [label=3] + n139866028217512 -> n139866028217568 + n139866028217568 [label=3] + n139866028218408 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028218408 -> n139866028694720 + n139866028218464 [label=3] + n139866028218408 -> n139866028218464 + n139866028218464 [label=3] + n139866028218576 [label="+"] + n139866028218408 [label="*"] + n139866028218576 -> n139866028218408 + n139866028218632 [label=1] + n139866028218576 -> n139866028218632 + n139866028218632 [label=1] + n139866028219192 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028219192 -> n139866028694720 + n139866028219248 [label=3] + n139866028219192 -> n139866028219248 + n139866028219248 [label=3] + n139866028219360 [label="+"] + n139866028219192 [label="*"] + n139866028219360 -> n139866028219192 + n139866028219416 [label=1] + n139866028219360 -> n139866028219416 + n139866028219416 [label=1] + n139866028220200 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028220200 -> n139866028694720 + n139866028220256 [label=3] + n139866028220200 -> n139866028220256 + n139866028220256 [label=3] + n139866028220368 [label="+"] + n139866028220200 [label="*"] + n139866028220368 -> n139866028220200 + n139866028355656 [label=2] + n139866028220368 -> n139866028355656 + n139866028355656 [label=2] + n139866028356216 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028356216 -> n139866028694720 + n139866028356272 [label=3] + n139866028356216 -> n139866028356272 + n139866028356272 [label=3] + n139866028356384 [label="+"] + n139866028356216 [label="*"] + n139866028356384 -> n139866028356216 + n139866028356440 [label=2] + n139866028356384 -> n139866028356440 + n139866028356440 [label=2] + n139866028359408 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028359408 -> n139866028694720 + n139866028359464 [label=3] + n139866028359408 -> n139866028359464 + n139866028359464 [label=3] + n139866028388536 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028388536 -> n139866028694720 + n139866028388592 [label=3] + n139866028388536 -> n139866028388592 + n139866028388592 [label=3] + n139866028389712 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028389712 -> n139866028694720 + n139866028389768 [label=3] + n139866028389712 -> n139866028389768 + n139866028389768 [label=3] + n139866028389880 [label="+"] + n139866028389712 [label="*"] + n139866028389880 -> n139866028389712 + n139866028389936 [label=1] + n139866028389880 -> n139866028389936 + n139866028389936 [label=1] + n139866028390104 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028390104 -> n139866028694720 + n139866028390160 [label=3] + n139866028390104 -> n139866028390160 + n139866028390160 [label=3] + n139866028390272 [label="+"] + n139866028390104 [label="*"] + n139866028390272 -> n139866028390104 + n139866028390328 [label=1] + n139866028390272 -> n139866028390328 + n139866028390328 [label=1] + n139866028391280 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028391280 -> n139866028694720 + n139866028391336 [label=3] + n139866028391280 -> n139866028391336 + n139866028391336 [label=3] + n139866028391448 [label="+"] + n139866028391280 [label="*"] + n139866028391448 -> n139866028391280 + n139866028391504 [label=2] + n139866028391448 -> n139866028391504 + n139866028391504 [label=2] + n139866028391672 [label="*"] + n139866028694720 [label="Iter(0)"] + n139866028391672 -> n139866028694720 + n139866028391728 [label=3] + n139866028391672 -> n139866028391728 + n139866028391728 [label=3] + n139866028391840 [label="+"] + n139866028391672 [label="*"] + n139866028391840 -> n139866028391672 + n139866028391896 [label=2] + n139866028391840 -> n139866028391896 + n139866028391896 [label=2] + n139866028695056 [label=For] + n139866028695112 [label="Iter(1)"] + n139866028695056 -> n139866028695112 + n139866028695224 [label=Block] + n139866028695056 -> n139866028695224 + n139866028695168 [label=0] + n139866028695056 -> n139866028695168 + n139866028695000 [label=ArrayAccess] + n139866028695056 -> n139866028695000 + n139866028695112 [label="Iter(1)"] + n139866028695224 [label=Block] + n139866028357336 [label=Filter] + n139866028695224 -> n139866028357336 + n139866028695448 [label="+"] + n139866028695336 [label="*"] + n139866028695448 -> n139866028695336 + n139866028695112 [label="Iter(1)"] + n139866028695448 -> n139866028695112 + n139866028216448 [label=PropertyAccess] + n139866028639904 [label=position] + n139866028216448 -> n139866028639904 + n139866028695280 [label=ArrayAccess] + n139866028216448 -> n139866028695280 + n139866028389152 [label="*"] + n139866028216448 -> n139866028389152 + n139866028390888 [label="+"] + n139866028216448 -> n139866028390888 + n139866028425288 [label="+"] + n139866028216448 -> n139866028425288 + n139866028695280 [label=ArrayAccess] + n139866028691864 [label=neighborlists] + n139866028695280 -> n139866028691864 + n139866028695448 [label="+"] + n139866028695280 -> n139866028695448 + n139866028691864 [label=neighborlists] + n139866028389152 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028389152 -> n139866028695280 + n139866028389208 [label=3] + n139866028389152 -> n139866028389208 + n139866028389208 [label=3] + n139866028390888 [label="+"] + n139866028390720 [label="*"] + n139866028390888 -> n139866028390720 + n139866028390944 [label=1] + n139866028390888 -> n139866028390944 + n139866028390720 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028390720 -> n139866028695280 + n139866028390776 [label=3] + n139866028390720 -> n139866028390776 + n139866028390776 [label=3] + n139866028390944 [label=1] + n139866028425288 [label="+"] + n139866028392288 [label="*"] + n139866028425288 -> n139866028392288 + n139866028425344 [label=2] + n139866028425288 -> n139866028425344 + n139866028392288 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028392288 -> n139866028695280 + n139866028392344 [label=3] + n139866028392288 -> n139866028392344 + n139866028392344 [label=3] + n139866028425344 [label=2] + n139866028216560 [label="-"] + n139866028692480 [label=PropertyAccess] + n139866028216560 -> n139866028692480 + n139866028216448 [label=PropertyAccess] + n139866028216560 -> n139866028216448 + n139866028217064 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028217064 -> n139866028695280 + n139866028217120 [label=3] + n139866028217064 -> n139866028217120 + n139866028217120 [label=3] + n139866028217848 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028217848 -> n139866028695280 + n139866028217904 [label=3] + n139866028217848 -> n139866028217904 + n139866028217904 [label=3] + n139866028218240 [label="*"] + n139866028217400 [label=VectorAccess] + n139866028218240 -> n139866028217400 + n139866028218184 [label=VectorAccess] + n139866028218240 -> n139866028218184 + n139866028217400 [label=VectorAccess] + n139866028216560 [label="-"] + n139866028217400 -> n139866028216560 + n139866028218184 [label=VectorAccess] + n139866028216560 [label="-"] + n139866028218184 -> n139866028216560 + n139866028218744 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028218744 -> n139866028695280 + n139866028218800 [label=3] + n139866028218744 -> n139866028218800 + n139866028218800 [label=3] + n139866028218912 [label="+"] + n139866028218744 [label="*"] + n139866028218912 -> n139866028218744 + n139866028218968 [label=1] + n139866028218912 -> n139866028218968 + n139866028218968 [label=1] + n139866028219528 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028219528 -> n139866028695280 + n139866028219584 [label=3] + n139866028219528 -> n139866028219584 + n139866028219584 [label=3] + n139866028219696 [label="+"] + n139866028219528 [label="*"] + n139866028219696 -> n139866028219528 + n139866028219752 [label=1] + n139866028219696 -> n139866028219752 + n139866028219752 [label=1] + n139866028219920 [label="*"] + n139866028219080 [label=VectorAccess] + n139866028219920 -> n139866028219080 + n139866028219864 [label=VectorAccess] + n139866028219920 -> n139866028219864 + n139866028219080 [label=VectorAccess] + n139866028216560 [label="-"] + n139866028219080 -> n139866028216560 + n139866028219864 [label=VectorAccess] + n139866028216560 [label="-"] + n139866028219864 -> n139866028216560 + n139866028220032 [label="+"] + n139866028218240 [label="*"] + n139866028220032 -> n139866028218240 + n139866028219920 [label="*"] + n139866028220032 -> n139866028219920 + n139866028355768 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028355768 -> n139866028695280 + n139866028355824 [label=3] + n139866028355768 -> n139866028355824 + n139866028355824 [label=3] + n139866028355936 [label="+"] + n139866028355768 [label="*"] + n139866028355936 -> n139866028355768 + n139866028355992 [label=2] + n139866028355936 -> n139866028355992 + n139866028355992 [label=2] + n139866028356552 [label="*"] + n139866028695280 [label=ArrayAccess] + n139866028356552 -> n139866028695280 + n139866028356608 [label=3] + n139866028356552 -> n139866028356608 + n139866028356608 [label=3] + n139866028356720 [label="+"] + n139866028356552 [label="*"] + n139866028356720 -> n139866028356552 + n139866028356776 [label=2] + n139866028356720 -> n139866028356776 + n139866028356776 [label=2] + n139866028356944 [label="*"] + n139866028356104 [label=VectorAccess] + n139866028356944 -> n139866028356104 + n139866028356888 [label=VectorAccess] + n139866028356944 -> n139866028356888 + n139866028356104 [label=VectorAccess] + n139866028216560 [label="-"] + n139866028356104 -> n139866028216560 + n139866028356888 [label=VectorAccess] + n139866028216560 [label="-"] + n139866028356888 -> n139866028216560 + n139866028357056 [label="+"] + n139866028220032 [label="+"] + n139866028357056 -> n139866028220032 + n139866028356944 [label="*"] + n139866028357056 -> n139866028356944 + n139866028357168 [label="<"] + n139866028357056 [label="+"] + n139866028357168 -> n139866028357056 + n139866028357224 [label=2.5] + n139866028357168 -> n139866028357224 + n139866028357224 [label=2.5] + n139866028357336 [label=Filter] + n139866028357168 [label="<"] + n139866028357336 -> n139866028357168 + n139866028357392 [label=Block] + n139866028357336 -> n139866028357392 + n139866028357392 [label=Block] + n139866028359296 [label=Assign] + n139866028357392 -> n139866028359296 + n139866028357728 [label="/"] + n139866028357784 [label=1.0] + n139866028357728 -> n139866028357784 + n139866028357056 [label="+"] + n139866028357728 -> n139866028357056 + n139866028357784 [label=1.0] + n139866028357896 [label="*"] + n139866028357728 [label="/"] + n139866028357896 -> n139866028357728 + n139866028357728 [label="/"] + n139866028357896 -> n139866028357728 + n139866028358008 [label="*"] + n139866028357896 [label="*"] + n139866028358008 -> n139866028357896 + n139866028357728 [label="/"] + n139866028358008 -> n139866028357728 + n139866028357672 [label=PropertyAccess] + n139866028640016 [label=force] + n139866028357672 -> n139866028640016 + n139866028694720 [label="Iter(0)"] + n139866028357672 -> n139866028694720 + n139866028388536 [label="*"] + n139866028357672 -> n139866028388536 + n139866028390272 [label="+"] + n139866028357672 -> n139866028390272 + n139866028391840 [label="+"] + n139866028357672 -> n139866028391840 + n139866028640016 [label=force] + n139866028358344 [label="*"] + n139866028216560 [label="-"] + n139866028358344 -> n139866028216560 + n139866028358400 [label=48.0] + n139866028358344 -> n139866028358400 + n139866028358400 [label=48.0] + n139866028358512 [label="*"] + n139866028216560 [label="-"] + n139866028358512 -> n139866028216560 + n139866027164896 [label="*"] + n139866028358512 -> n139866027164896 + n139866027164896 [label="*"] + n139866028358400 [label=48.0] + n139866027164896 -> n139866028358400 + n139866028358008 [label="*"] + n139866027164896 -> n139866028358008 + n139866028358624 [label="-"] + n139866028358008 [label="*"] + n139866028358624 -> n139866028358008 + n139866028358680 [label=0.5] + n139866028358624 -> n139866028358680 + n139866028358680 [label=0.5] + n139866028358792 [label="*"] + n139866028216560 [label="-"] + n139866028358792 -> n139866028216560 + n139866027165008 [label="*"] + n139866028358792 -> n139866027165008 + n139866027165008 [label="*"] + n139866027164896 [label="*"] + n139866027165008 -> n139866027164896 + n139866028358624 [label="-"] + n139866027165008 -> n139866028358624 + n139866028358904 [label="*"] + n139866028216560 [label="-"] + n139866028358904 -> n139866028216560 + n139866027165120 [label="*"] + n139866028358904 -> n139866027165120 + n139866027165120 [label="*"] + n139866027165008 [label="*"] + n139866027165120 -> n139866027165008 + n139866028357728 [label="/"] + n139866027165120 -> n139866028357728 + n139866028359016 [label="*"] + n139866028216560 [label="-"] + n139866028359016 -> n139866028216560 + n139866027165120 [label="*"] + n139866028359016 -> n139866027165120 + n139866028359184 [label="+"] + n139866028357672 [label=PropertyAccess] + n139866028359184 -> n139866028357672 + n139866028359016 [label="*"] + n139866028359184 -> n139866028359016 + n139866028359296 [label=Assign] + n139866028389600 [label=VectorAccess] + n139866028359296 -> n139866028389600 + n139866028388480 [label=VectorAccess] + n139866028359296 -> n139866028388480 + n139866028391168 [label=VectorAccess] + n139866028359296 -> n139866028391168 + n139866028390048 [label=VectorAccess] + n139866028359296 -> n139866028390048 + n139866028425568 [label=VectorAccess] + n139866028359296 -> n139866028425568 + n139866028391616 [label=VectorAccess] + n139866028359296 -> n139866028391616 + n139866028389600 [label=VectorAccess] + n139866028357672 [label=PropertyAccess] + n139866028389600 -> n139866028357672 + n139866028388480 [label=VectorAccess] + n139866028359184 [label="+"] + n139866028388480 -> n139866028359184 + n139866028391168 [label=VectorAccess] + n139866028357672 [label=PropertyAccess] + n139866028391168 -> n139866028357672 + n139866028390048 [label=VectorAccess] + n139866028359184 [label="+"] + n139866028390048 -> n139866028359184 + n139866028425568 [label=VectorAccess] + n139866028357672 [label=PropertyAccess] + n139866028425568 -> n139866028357672 + n139866028391616 [label=VectorAccess] + n139866028359184 [label="+"] + n139866028391616 -> n139866028359184 + n139866028695168 [label=0] + n139866028695000 [label=ArrayAccess] + n139866028691920 [label=numneighs] + n139866028695000 -> n139866028691920 + n139866028694720 [label="Iter(0)"] + n139866028695000 -> n139866028694720 + n139866028691920 [label=numneighs] + n139866028694776 [label=0] + n139866028694832 [label=0] + n139866028694664 [label=ParticleFor] + n139866028693656 [label="Iter(2)"] + n139866028694664 -> n139866028693656 + n139866028692592 [label=Block] + n139866028694664 -> n139866028692592 + n139866028693544 [label=0] + n139866028694664 -> n139866028693544 + n139866028693320 [label=0] + n139866028694664 -> n139866028693320 + n139866028693656 [label="Iter(2)"] + n139866028692592 [label=Block] + n139866028426240 [label=Assign] + n139866028692592 -> n139866028426240 + n139866027930848 [label=Assign] + n139866028692592 -> n139866027930848 + n139866028357560 [label=PropertyAccess] + n139866028639960 [label=velocity] + n139866028357560 -> n139866028639960 + n139866028693656 [label="Iter(2)"] + n139866028357560 -> n139866028693656 + n139866028426744 [label="*"] + n139866028357560 -> n139866028426744 + n139866028428480 [label="+"] + n139866028357560 -> n139866028428480 + n139866027930064 [label="+"] + n139866028357560 -> n139866027930064 + n139866028639960 [label=velocity] + n139866028426744 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028426744 -> n139866028693656 + n139866028427136 [label=3] + n139866028426744 -> n139866028427136 + n139866028427136 [label=3] + n139866028428480 [label="+"] + n139866028427976 [label="*"] + n139866028428480 -> n139866028427976 + n139866028428536 [label=1] + n139866028428480 -> n139866028428536 + n139866028427976 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028427976 -> n139866028693656 + n139866028428368 [label=3] + n139866028427976 -> n139866028428368 + n139866028428368 [label=3] + n139866028428536 [label=1] + n139866027930064 [label="+"] + n139866028429208 [label="*"] + n139866027930064 -> n139866028429208 + n139866027930120 [label=2] + n139866027930064 -> n139866027930120 + n139866028429208 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028429208 -> n139866028693656 + n139866027929952 [label=3] + n139866028429208 -> n139866027929952 + n139866027929952 [label=3] + n139866027930120 [label=2] + n139866028425624 [label=PropertyAccess] + n139866028640016 [label=force] + n139866028425624 -> n139866028640016 + n139866028693656 [label="Iter(2)"] + n139866028425624 -> n139866028693656 + n139866028426800 [label="*"] + n139866028425624 -> n139866028426800 + n139866028428200 [label="+"] + n139866028425624 -> n139866028428200 + n139866027929784 [label="+"] + n139866028425624 -> n139866027929784 + n139866028426800 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028426800 -> n139866028693656 + n139866028426856 [label=3] + n139866028426800 -> n139866028426856 + n139866028426856 [label=3] + n139866028428200 [label="+"] + n139866028428032 [label="*"] + n139866028428200 -> n139866028428032 + n139866028428256 [label=1] + n139866028428200 -> n139866028428256 + n139866028428032 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028428032 -> n139866028693656 + n139866028428088 [label=3] + n139866028428032 -> n139866028428088 + n139866028428088 [label=3] + n139866028428256 [label=1] + n139866027929784 [label="+"] + n139866028429264 [label="*"] + n139866027929784 -> n139866028429264 + n139866027929840 [label=2] + n139866027929784 -> n139866027929840 + n139866028429264 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028429264 -> n139866028693656 + n139866027929672 [label=3] + n139866028429264 -> n139866027929672 + n139866027929672 [label=3] + n139866027929840 [label=2] + n139866028425736 [label="*"] + n139866028425792 [label=0.005] + n139866028425736 -> n139866028425792 + n139866028425624 [label=PropertyAccess] + n139866028425736 -> n139866028425624 + n139866028425792 [label=0.005] + n139866028425904 [label=PropertyAccess] + n139866028639848 [label=mass] + n139866028425904 -> n139866028639848 + n139866028693656 [label="Iter(2)"] + n139866028425904 -> n139866028693656 + n139866028639848 [label=mass] + n139866028426016 [label="/"] + n139866028425736 [label="*"] + n139866028426016 -> n139866028425736 + n139866028425904 [label=PropertyAccess] + n139866028426016 -> n139866028425904 + n139866028426128 [label="+"] + n139866028357560 [label=PropertyAccess] + n139866028426128 -> n139866028357560 + n139866028426016 [label="/"] + n139866028426128 -> n139866028426016 + n139866028426352 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028426352 -> n139866028693656 + n139866028426408 [label=3] + n139866028426352 -> n139866028426408 + n139866028426408 [label=3] + n139866028427584 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028427584 -> n139866028693656 + n139866028427640 [label=3] + n139866028427584 -> n139866028427640 + n139866028427640 [label=3] + n139866028427752 [label="+"] + n139866028427584 [label="*"] + n139866028427752 -> n139866028427584 + n139866028427808 [label=1] + n139866028427752 -> n139866028427808 + n139866028427808 [label=1] + n139866028428816 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866028428816 -> n139866028693656 + n139866028428872 [label=3] + n139866028428816 -> n139866028428872 + n139866028428872 [label=3] + n139866028428984 [label="+"] + n139866028428816 [label="*"] + n139866028428984 -> n139866028428816 + n139866028429040 [label=2] + n139866028428984 -> n139866028429040 + n139866028429040 [label=2] + n139866028426240 [label=Assign] + n139866028427472 [label=VectorAccess] + n139866028426240 -> n139866028427472 + n139866028426688 [label=VectorAccess] + n139866028426240 -> n139866028426688 + n139866028428704 [label=VectorAccess] + n139866028426240 -> n139866028428704 + n139866028427920 [label=VectorAccess] + n139866028426240 -> n139866028427920 + n139866027930288 [label=VectorAccess] + n139866028426240 -> n139866027930288 + n139866028429152 [label=VectorAccess] + n139866028426240 -> n139866028429152 + n139866028427472 [label=VectorAccess] + n139866028357560 [label=PropertyAccess] + n139866028427472 -> n139866028357560 + n139866028426688 [label=VectorAccess] + n139866028426128 [label="+"] + n139866028426688 -> n139866028426128 + n139866028428704 [label=VectorAccess] + n139866028357560 [label=PropertyAccess] + n139866028428704 -> n139866028357560 + n139866028427920 [label=VectorAccess] + n139866028426128 [label="+"] + n139866028427920 -> n139866028426128 + n139866027930288 [label=VectorAccess] + n139866028357560 [label=PropertyAccess] + n139866027930288 -> n139866028357560 + n139866028429152 [label=VectorAccess] + n139866028426128 [label="+"] + n139866028429152 -> n139866028426128 + n139866027930344 [label=PropertyAccess] + n139866028639904 [label=position] + n139866027930344 -> n139866028639904 + n139866028693656 [label="Iter(2)"] + n139866027930344 -> n139866028693656 + n139866027931688 [label="*"] + n139866027930344 -> n139866027931688 + n139866027933088 [label="+"] + n139866027930344 -> n139866027933088 + n139866027967152 [label="+"] + n139866027930344 -> n139866027967152 + n139866027931688 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027931688 -> n139866028693656 + n139866027931744 [label=3] + n139866027931688 -> n139866027931744 + n139866027931744 [label=3] + n139866027933088 [label="+"] + n139866027932920 [label="*"] + n139866027933088 -> n139866027932920 + n139866027933144 [label=1] + n139866027933088 -> n139866027933144 + n139866027932920 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027932920 -> n139866028693656 + n139866027932976 [label=3] + n139866027932920 -> n139866027932976 + n139866027932976 [label=3] + n139866027933144 [label=1] + n139866027967152 [label="+"] + n139866027966984 [label="*"] + n139866027967152 -> n139866027966984 + n139866027967208 [label=2] + n139866027967152 -> n139866027967208 + n139866027966984 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027966984 -> n139866028693656 + n139866027967040 [label=3] + n139866027966984 -> n139866027967040 + n139866027967040 [label=3] + n139866027967208 [label=2] + n139866027930456 [label=PropertyAccess] + n139866028639960 [label=velocity] + n139866027930456 -> n139866028639960 + n139866028693656 [label="Iter(2)"] + n139866027930456 -> n139866028693656 + n139866027931352 [label="*"] + n139866027930456 -> n139866027931352 + n139866027932752 [label="+"] + n139866027930456 -> n139866027932752 + n139866027966816 [label="+"] + n139866027930456 -> n139866027966816 + n139866027931352 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027931352 -> n139866028693656 + n139866027931408 [label=3] + n139866027931352 -> n139866027931408 + n139866027931408 [label=3] + n139866027932752 [label="+"] + n139866027932584 [label="*"] + n139866027932752 -> n139866027932584 + n139866027932808 [label=1] + n139866027932752 -> n139866027932808 + n139866027932584 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027932584 -> n139866028693656 + n139866027932640 [label=3] + n139866027932584 -> n139866027932640 + n139866027932640 [label=3] + n139866027932808 [label=1] + n139866027966816 [label="+"] + n139866027966648 [label="*"] + n139866027966816 -> n139866027966648 + n139866027966872 [label=2] + n139866027966816 -> n139866027966872 + n139866027966648 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027966648 -> n139866028693656 + n139866027966704 [label=3] + n139866027966648 -> n139866027966704 + n139866027966704 [label=3] + n139866027966872 [label=2] + n139866027930568 [label="*"] + n139866027930624 [label=0.005] + n139866027930568 -> n139866027930624 + n139866027930456 [label=PropertyAccess] + n139866027930568 -> n139866027930456 + n139866027930624 [label=0.005] + n139866027930736 [label="+"] + n139866027930344 [label=PropertyAccess] + n139866027930736 -> n139866027930344 + n139866027930568 [label="*"] + n139866027930736 -> n139866027930568 + n139866027930960 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027930960 -> n139866028693656 + n139866027931016 [label=3] + n139866027930960 -> n139866027931016 + n139866027931016 [label=3] + n139866027932192 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027932192 -> n139866028693656 + n139866027932248 [label=3] + n139866027932192 -> n139866027932248 + n139866027932248 [label=3] + n139866027932360 [label="+"] + n139866027932192 [label="*"] + n139866027932360 -> n139866027932192 + n139866027932416 [label=1] + n139866027932360 -> n139866027932416 + n139866027932416 [label=1] + n139866027933424 [label="*"] + n139866028693656 [label="Iter(2)"] + n139866027933424 -> n139866028693656 + n139866027933480 [label=3] + n139866027933424 -> n139866027933480 + n139866027933480 [label=3] + n139866027933592 [label="+"] + n139866027933424 [label="*"] + n139866027933592 -> n139866027933424 + n139866027933648 [label=2] + n139866027933592 -> n139866027933648 + n139866027933648 [label=2] + n139866027930848 [label=Assign] + n139866027932080 [label=VectorAccess] + n139866027930848 -> n139866027932080 + n139866027931296 [label=VectorAccess] + n139866027930848 -> n139866027931296 + n139866027933312 [label=VectorAccess] + n139866027930848 -> n139866027933312 + n139866027932528 [label=VectorAccess] + n139866027930848 -> n139866027932528 + n139866027967376 [label=VectorAccess] + n139866027930848 -> n139866027967376 + n139866027966592 [label=VectorAccess] + n139866027930848 -> n139866027966592 + n139866027932080 [label=VectorAccess] + n139866027930344 [label=PropertyAccess] + n139866027932080 -> n139866027930344 + n139866027931296 [label=VectorAccess] + n139866027930736 [label="+"] + n139866027931296 -> n139866027930736 + n139866027933312 [label=VectorAccess] + n139866027930344 [label=PropertyAccess] + n139866027933312 -> n139866027930344 + n139866027932528 [label=VectorAccess] + n139866027930736 [label="+"] + n139866027932528 -> n139866027930736 + n139866027967376 [label=VectorAccess] + n139866027930344 [label=PropertyAccess] + n139866027967376 -> n139866027930344 + n139866027966592 [label=VectorAccess] + n139866027930736 [label="+"] + n139866027966592 -> n139866027930736 + n139866028693544 [label=0] + n139866028693320 [label=0] +} diff --git a/examples/kernels.pdf b/examples/kernels.pdf new file mode 100644 index 0000000000000000000000000000000000000000..54c0d45a7732838899d0d081e18c622211358f87 GIT binary patch literal 46823 zcmV*eKvBOXP((&8F)lR<CAICY`wBE5Fd%PYY6?6&ATLa1ZfA68AT=N`AW{k-ARsSB zX>4?5av(28Y+-a|L}g=dWMv9IJ_>Vma%Ev{3V58|y<LwaOL86fp1-0V@7=`|!`<T( z*cTC4EtY@)aYZa2M#N&&9P*N?qR63k1^#>aImgUA!lSA?qbsW$SW(lr%{t99Bh1{~ z+&<IOQ2+0Dss54I^z`NR_Aj@;eEOGLnV;(aA4`79!}eUZ>FG~@eERFBf4Ze7{NJDc z{^`&DFg*SJzrOv!zq<|3^R^CUdm5hCWt{5z&s)L&18Gj<^EPi!Wqr<Ne0mMUSjm>T zuCzW+dFes>_!mdqp33yRY)f0O1O4-V$49DE_^IntJj?q(^8flj{P~9GG^BZ4p8m&e zc>0U_zkj^_{%`6Bho`^2rQzv6JpId4;ycuz^#%Uur~6M&e|a1D<@MG6`Cr}A^O(!9 zj>cJsa;iUi8A{3^ozpO-<>{|pZ-4f8zZ-sspZ`~Xcl-S>fBtJ8e|h;e4Zr-iU(@=_ zmtWKT%YXg#Z~p2pZvXpV@hyIpvGLBn@?O8^h34l<@ib1)(=_pg8e)0gHoU>~ysbT? z4}S@`Jf~D&YS0pX>el}9^yhcJ&7nMROP;40q+7-1?ff?X<F9%6<qvp=fBH40U;aDZ z>p$Rc^}SAd&40wd{(F3mFZ@sbuJs%0`+DPb)b~54r?OEFUd7opL!j1iw0)SK#`@ej zQ=FD6ZTWevub~r{uY5~gWtg$Ep9g+PT_)!Oc$wCx7a~STb$(ukr6PVi(ePb<O<uk# zD5sxPDu?qlKFw8x>hrxm1tLGsm8O)XN_Y?H!(SYpmiqh0ThI!A>ejwn4oblz=Lv+< zTvu9um=uilolV%w%bdZWQu#ekU^}Iw{(CC*d8g-b!P}UtQhA!T=RD^7rGR8rY^JqJ z54IlO;#3({7aG%8xsFeaRlX_$AA}g3h`uQYX<45u)l<f<tXt}JhncumT2g(#Z^5GY z;+VR_>poc0wp*fyokZtCCB$cNFzgSy&p8}^(v#kKMx><@ED3T2+NtES<+DKlpTDLo zG5#YY_)h@;^DmI-0n+=Qe?1%+E?nP#pjJ%-t+G6qk>_buGvin_PkqX&v!VW~`7v(K zvmJ9)-lz0Dj0NgHRb{l!6vn*X`0wkoJ<aJkr{o`>tIFirTS1_=<#|myn;{Zu7^yu2 zF6Fr_+s#hv9qL^;XPoLgf?Pi^@+6s`)0pZnEA?O>Cp)m}m({H{&rsQEt0V)Zl+Th@ z961$C&+A+&*Xpib09Vbo<lFt*8<eH0YA}1KHi)D#SN)E)U~Rl;^{mzFYsLmYlRa3| zr){e5q;AMe9an#rBkC5d225J3)*H$R)W^R#;`THR&tqk5kawVe{!V3|wkjRd(^Tr8 zDUEOJjIWwcUps8a=V71;GZb1lRR+eo^+s@`es48x$_f$3iI1O;?OkO&*SCK^w=3N^ zEufotWTb6;E-Mk(IxqY81k-`M?uj1E>OAE7q;q3+AdI*5+3{+6Fjy@_usX;)@G`4m zM6F|e>+iC=YP-Ms$8RxKtb%p1%8VMR#lYBl-+~#59bGw#Qx(6qDo6bIx$dtE##*lD zI_cK6nEd30Tq{$iwU(Zj`Uv$C&`Pq_I--YjcB2yAan=xGC0|8ePoQ(k5IfEqc?VwP zEcESCg}gH1W1OWqSs6PHG`|d9pA)}C&{i)QWd~J>y291EcyY4$iu&GP>?tPyNAdIc z@kd+V_5N8^gP&_K1r0Hg50zE?MQ2z9UmSC*sDb({R_H({xZ4JY0l=FrXqRak-ZI1A zw_5ViYWa#eOa+}_?Bmi<-$A`>WL`O@rRwK;wBtOS>rv19n80O(=~17@5jVqhA8;_G zm3y@jq?~C=kHbclpK{gHbzk4cDh30L#9R#)-do11ah7T=r3^`Ys=J^1CgFB4=^g;9 z121a0aCVSx(+eK+?Ch^A0#of5zY5g9rIN{czY84c9xj#(Z|-ybPs)Bn0iy1MY9yBW z;MjvbsE>bf#O-OG@Ir$62>GY)mdI*}O}rLXzN|~t@Q*STO0@yYFu{J^j1L=Zgernt z8u^Q>9L)9dH?QPKJq7B+yx}VP8na1Lw-MK$c_z&hH>ub>0WpT^IS@Sj)?dG8n0E|z zgmV;E(e(s21``nscIqQ^mBBE*hjCulcR75=8B#_#pTIi24Lq5{ReLy4%s(M$e4cZ< zz{yHBHM;f{6P*Mv_8^mgfXwV^9?j6Il5nAD40VKYaI8XG#kB{6p+W>ho%#q}W@tUC zzp`KN;%1?eZacFIS6xh7bLH<&BVTn|W_g?vH4Ut=3oNb2JmhZTwv-oao45gSZG7Pu zVP|4TW@Bkb^YHuHh?{5g%mqTexU_CGi+a$VZHBnHH_pjB@TzkT_qDAW(p7DJ#XWb) z?N+~^+?_^xTJWTXkopU7wwtDb3zhbTt6Jv$!02{gv+5EKcv}45by4d`9?j!*talXn zEvkJ7J>L*3?;2@YaM+wce*BBWH~2jYOqL+;VI#Pg$#6!%VO5W%x}Uanx?=jJdrd#Q z@C<*loHMT!t~HNP(C{<?gj=WXZX7=V>m8Dcb~OpdmE%?w%%*>ysv)_|)jAV6SEf~P zriX7U)qcoNl?d0yJPh;%ZON_^1aEXpr9pQkeZn#C!rNxr#xd}Z&0D(BX9Bodl5{ex zg%@YKspboJQ4qp<1>qu}(pv37Tz1P?IfTn6J_9=zpUFjD<1^i(1sDQ2?+l4R=%9gH zwdC;x`blC4KX-!q2wgmP(ozrmc}ZU}B);2Jgv{X{QbjgVV%M3ce$~Ph(Y30OX@kV# zKk)peT)_)x5xs@bt`K8;qll(exZX_YJcKkQZ3E+TNApQuhv0G`#8!7R^q})Cybj`P zP#>X-T;BN{K44(r7=+~j*EMgSX`8u6D?{Ps!Iq{)F)Fk<6vk*=1p%I@kroCIDyX}` z3MV?^nG>xj_@FQNDD-9clI#wybx9Hdd7i3SG!T(JOxV$UhD#BT)<nP%biqRh(j=hI zAMcO`utfl<dSPn-zVV!`ch?{_D0G4&>XoRG@`cC3fNuP(eJ}qxeiJCWUwpy9DNyIb z_P$*G{+ECEYqrQE&%Hn31pGJX5&i>Xko<!&$bbDcjrET^j>CHFO$?)~X7SaBA9)YO z;SbMpJ(TO=$Oy$Y$!}6+W4aK2q^BF3W@M^_;sA4^m@Ya=>KDO8)c$mb^?~Nm$4Gr9 z9-LtZ1;PxUiJq4e=ys6cW(Ng%4_~x{VB#vj<9$=;m;dG4T4uJ)h=N-LpKnqmt3D8v zd#ZbZaVkWka#1*PVKfQ`(1pVzk#!(sx&Y2X_=*_US|%PJiC!aM#P8qEWZ#Z1*S(DJ z&@Sd082L%?h|3}v)*asE#_tsjuFX}z##{SHy=W%B1zRHE2-5~e|FtFbqHw~rZy^FC z@jHZRztfiJo+LuplS0^e_#rXu{~y24djsY5{<ke~@qIN={!dV|ymI^lthc`h_#6KC zFZjdmoK-Qu;17O;`j<DA|Hn+d>89L~e+K-A(ANJDsU-jQ*l2saMTDPC!8t}5KMmeY zWBGd@o-f5CVaTk>>0S>E%qtZDm70Ho+rKAzuzH{6DakqU{`UG5h|J6Y-0yHL%EcoA zFm4?Dg6nsxYU$>fY1Ey~$OF{!Um8Nb4I{7Dq^fg$`CGtW;`{vr{_8~E{rbBP54bDf z&)i5lEmL{JkYFAYZ3s&4KZkJtDX!OUS4_I3T(>LWv%;RPuWRHr8}<>7w4Aw9@qm2& z3W(IBi04DR{&nOny}tg5DGG>`jC#F@OjrU%&ND8(&=6G<WbER4?S;29;p{=`Ox`Gh zw^X+`FA4}UjjQRQjD(zeot<#=uP-k#!((FtR>Fm9&HQ(Ss-cGJEojI$p6Lkere)wq zv7_*~yajF&>iOCkTHwwF-8kzEEtV}*c{}S2%`~&|na%IoJ=w#r+J$##OM21IA_Ael zdLN`sfrOeK_AD7g+{mh7S=$OH*eLEclNLI9L02VcuBXFE(EmBKGsTvQ*|YZS4*pM< zM0x52Ii<ZISJ5~NazbK~{mcn5Q!Ilwlwej;$i{Uq$gr)UIVuJTns|XcEi25&p8WGw z2(F|E%@SFDlU$Lw+Cg~hmciC}5wq4sm^GQ6?&%&aV?{2sCS#6pnW|eKp1BhoGA6`M z#$w4Hz9?h$J&bvq*Yzu6c84jBR|rd-%5XFp8g-aJP1to&$}pW}s9sKS6T0DfV5)2j z4^#a6g!iG{zmuUXGn+EABFxMnG1!XJB;^r`??%KlTu3GcC9e=zY38M(zWc1DVW7Qm zacR+o4hhQ8iR{sbeZ3>jJ2mC7NzAm--_nCF4FOYHZb5C*b6osx;hCYh8MF9`?EJ6a zmYrlL9o*BflV<s^fuJ8snL)X};$`JMp2>)nEpTDn%~{<4jciQ%7W_prg$o;;k7eN} zmT@LqdzuF`buA{=##D!miwhm_9ppT6&^Q`PiKEAr@8;-QEmdU$e2k-2!58gz+2!y_ z4J%oQ{az15INtbUhY^obiVPbhhu+Q6N+<1JPYSXJ{@QIZ3kfV;7P|3?7<4H=5#iOm zsj?-58&gMKnU;cxBruHhm1I|o!8CAI5Gjl=)~-Nj7X^A@(k;apS`XAT&Mb!5SzpM> z8WmXL&2n61;uV}s)hbI!nc@c`;dWYO6~Y>XZ=7N+dkta@`;8`EyJ;>gzPQQo8fLmK z=tdcp$;s%!DtNjQPJwqNi!Li`b1`=>3OuI8+$7nqxp;f-COOi5*7+NLut1pOE6(2@ zc28KGzwY{q6?*uhD{OcEzV8Yv-*$!JbXv{!pLs(KOk$#JgR|sy2jkXo;e>P{72*D? z3hxRpdaM#3(Fxg;ebNc(Ob%E)jT5p1jb8y58S_Cc{vH><azaX*e#Ff=TXj^hHW1=$ zfMV<pyu?@L2QEAQ#6r$hJ<WluC!z;4bxF(*38n@tF3w8XJAuZffQ_j^Ev6n9zn`h~ zWL)dz;j7;3^li2lmOJVEki6pBgJWi8WQJuOB`Y#Eo8B)ptM6y(qKXJSG1F=0<yp#R zWW4?bE7Op!pIDWGbE0`LPq%DxWjqa7Ok5WwP4}QNDPZGiP>ZL>#qT$Kw)*tdG$|k3 zs%yRZj<OoIB7+X58<|>P>8iv;FcrC)^-(5!(aU<lm9pw4LSdj|aYcF2My8Iqp{%Gs zl3k%~dZPFwL)KXuuz2W(>=7~!IcWS0Qt|V+@)bk2C|BVt{LJ6x=fDJyrg{S*)f=Ex z?+(1Ade>xzpli`s$W^bN=b(B|L~k0hRm*sV)-c<}Q95y<*Ku}BXQBN<Ptd-gtBRJq zl%ukuVUkLeW*Y79*q5_M*^<mlck^vGMatl&9Ce&rvoG=EU?&!j!X<@OHkNqObS?U_ zZOF~M+>?D%_WiJrpiv-H=jgUV4|-(A5H~M!4Dt><M#fmm_Je9WfAkaH8LJ9&>D@q8 zn8J^VAccwJ0i-}EeiWd>M-E<$9=Va^aiCbnV@GaSwb)Tl^5)*IXWhutWu~y#leDN( zv_4Kf%$~N9-ZOx3;BKSxXWHEn4y<8PWK#t&3;#=F0F|NlZSKi-_fmX!Pqw=+C1~xp z=^ESHcK3SP-SZo}`!2_un+PHNfsnMjh0%j9%!UZz5AqH?Ztr#eaohVxKjEF*duL?* zs11(X)^)eP9oF`CNW0shi<_J2u~XZrzKZW{KJ<QT_XLl2cA%be+9&-4Lgv>t?Q@?U zGV{toGsYUNxjBxD-))X<D<tKk7vVIRI)X97_A2;2^c~ZhNrY$kaAD3M_B7;rQ02YO ztCrh5Y&Qx&i^33W9OQ)qU#{xBrPFy=vI@Sc@>tdUAe9$<Yk4q%kq$7%caU#zhq?cE zV&PpJy5(KxZ4~pT<%gvD{OCu#Q|UF)|6w|BRjjQkJx7?<bI{bDfmik3YMa9Ko-gBy zPY-_3d>zTdHJ?%xcAC!-=GL_m_A~5mULkgF-dLfBFS>aL^tMqF*2gs9V#=y%z?DvX z+I-tW7_N3{z^dNRfn+;sKu@cN)rW$B`d@zyu<F010jE#WfMf18;M{A#bXI`lT>*n& z+)g_<#+ui-Fr47X>I>-zo#0FKaF_Eq<R54I{iG+oHyd%c5q^|D#CI|r+0q09V`+i` zTbiK5SJMR1AZJ~hhHDE&njl}mF;B3kdbD0l6K``(F9yQ&U>Zz^^swtiA$EE(R_Ni2 zdNHAQPu}R^`-onw-!Gr_!Yi+yQ7$yoi)mKi(e+}Qm4vj@iyMrt8wHbDI4FBH+c;fT zi)*hHFI2UET`iW-iut2j(b?8?MPN)fxG0?9&=nyYt{Y;B9`3c`_5-!z&w0{&wc>6Y z{4lMU3SHPctr!^7iUFHeboi=PtaQx&2(1_kg;wMXC<m?BQ$1WOZVbY-q&!D>5?&hF zBJu=BQl1dIq`X+Nhc71ORozskDnaFAX*iHaj~r*lqkxe$nAnviu|unZ^6(r29xXze z<|}D)=<zsMK19*$9N7?tQ7A?hfk_rqM<$K9+|xap&AG7BupNGZ@WXDY2Ss@Uj>C_L z-QgE2^zhZ(j{ynwED`ufAQ?Y!-lhYaS7i<dn^!b>*|B+JE#P;sS?N&DLfbXlfy=8! zuEkMtxhH!xmq#T`H7*CjxLUU7w?OBy;8y7t<UM?m#bfqP#vik9>J@D+in?v`6xCmZ z(puU#VCm?w<%RYolFO!T+}k%3atJmZU#K@svkL#I@6)@PV$##7kUb=dt!Cgvrr3Hl zl;<g5DiCI>m~16vI(VwsvU7(0_6FUzZ5(G^JNW}+C%p+n55~Dq#O~M+`X25KoU;8u z_t#H&%zLey-6r^9)=mA+@mLxb7_)8yHtWXWtJckEEhECZiG{+t;R`qzH$BnAGafhj zy<5eBA>5d$ij6&JdpL|6A@&sqzGM$yG;XR2-R9K`M!ws&L8x+4GA+^yUzu;qk^>xi z&{hT3SK^_^ib|9aWor{MTv1kI%f`rqSe)3)Zr3Jcv`|vvK`S2jWRGU@G%LF{4!uBl zJ@>$z;4>Tr-bCz7n^>WTFP?ksSNTD+rl>0;lBuRLnGmaxYNOG}8@mZHO4aHM*O3<~ z*!9?)&~cRsI=I6_`DG=hqNBoC?UEusdIt7ptzFcU9B*it1!u;$tt}~Yt<se{eI=aS z9%j}oI-VvK=b<~#3)jx}<@gblqMq#09Vn2JKQ2v(8bU&YDz0fKL=85PFhmogwn7hI z6CzYXR#V`^#uExq+36I{Ar_e6C!>yt#?v|xPC6_Y!+=43$g)SX?J9#eo)&QEv2Al| z<_cRoK{QRVU+Zgaj?@xutv3~Zqe#NqTGJ59O7HvaO!ZBv2quJm&@fY!>yfc1*w6dM zX)_7h5<PshgtFr5KgJUJNl$w3Y?GZ(|0rV!h0<)w9>!3^tj}IbEqJpno1%^T6=Mi= z^W4muwvO9E_WXNes3&^3h8wKp(`=zYnC-*)6uUyJfTIt-5X}~9OZM<JTL_9Keb^MD zuv(U??*G7e-ZAd~(10wqxBEZf&5~>{-T(2R*(yDBk!QJjo_7uaEIzvpVGe*Z-J_YD zW;3?@7z>0STS}HV!*Preu{*|Mg&w|mjG=8^efVMi+A;R+Tx5Q~S-j5X*-F)&%{F%_ z*gQR#{2g4bbhEjK<dowMfID)><xw+?cFw#r-J`jTqPBfGNJAJ`@u<7VR)d|(LhQI4 zEA;S1F4xab)s`+_%{afqSSiKc^kS`c`OBuQ87q~$tL1l0Rw5!FVpuCV<NfROVz3L{ zMKvh{*1W6-!IxU7k#N$<1+{J?VX{`*W;0f3)uJ`;){K<{)wit`=R!Nf17l~lbM^$s z86K?mGdq^(;m%qqKQLVXlb-ZmYh@?ZKg?QzgJ3*ZD}h;~7(}pHD-K_^R<KdGT|!b@ zD9jbUfI}A3iR$4>Zep=evsWD9_K97HPjJ{PLhS67Sh9yN+AH;-saI8%RDZ-`u@h-` zl%X<dTia2F`*&`EDZuE>as4dAsG{7?DSMrErMI)pis23x%ZcvcY))3v6K9zt?Ci=D zd&`|+Kg)#JpJl#64`01_uh9nJLl#R(Hb1Jd*}Dljn{7ghvl)eR)ABuR9xS~hOcrc{ zJ(DY})Zm@La-w>;A9i6I$zA2SBRmjQkL0<$0Y_wth<)X`uh7F6U373VeKaAvEPdKd zRFG(l5S)1E;_Su>oqF^9v=2*V&#FkYui<m_%$%jXn|4!<VJYh}5Mim&)cEBF2A)AP zMLzam$%m}FQ)}h*>D0jBK=<valyj|xYXal(8Iyz)+yXW(8XlpEC3?6IO#R3)f<Na; z?~P5_F8E<_DdgA=)6TeQ7>i2<Y;h@vug0Y?^k&}2rDCCoOZmgMxKvN{@aYSKh5*^z zAoZr#SRl6kMr(bxo$J7uGh~>Xl4KABh$Va2N$ypM>x?@LIutWMBCX{-DEA(vxXRc@ zdPmVnz;$D(KOSn#nLm-WwCILaX0~P?FcJz~t5DpJ0SR+Pr~7&mqjxb7Fica{gu{Si z09B9a;9DTj;9F(4fyo2a7khLkb%lcaJFOmK3thcV78Jy2AC5E3&x1;N(ejX<>LM>V z9`w@1(w*L@E;cu~&2m&k4WCKu4w&so|LqOB&k|Tz&eL`f*cFYmLtc-NKD`&$T-3EO z$a~mHzC&CyM|dpdyE@09Spb{@kb;%^IWUQhI~$y}!vZdh0AHB5u&Cg`2=`w#G6nj@ zA1gkic?&(=qiyl2$Wi8|xWi_7vklW*uv_9n>@0C#paU=3;fM$3tjw*C_>{(#6JK@# zFiZT@-dQX;3z^XsoLO$Wb0-zmhunB_B-1TR+naRo%nF7KSGtoNJVWZ>O@ER+6@$-o zE#_fra~XQFZ#$HX1I^3g2y?19OHXh(S%SyzRPhx$uyZCUX!L_ZUqAjS?{y^YMEQp~ zlBS_Gv#@>b7;_{AY>p&{uR4-2g|>`4M^Y>ljwHT-Lx%H->d{&abEfw_BLm@%BQ!AI zB?Sc>jwB&=j-*(!hc7yk#`z(wBPp)K!NY)YwPhC*88vl2JPhMzITlwv3>bVn=e;8d z55MhmU-4z`Gzv%3iSFTSRu{!~dIiFdtHA;VJsigu5xe6nR_Ni22iVA#!RYMzp;RD# zzxB&?Hlt^6-m!U7hy7slXt_X_**rdP`+RinfwCO9JcidOJV`y-!$*0n99_DzLjyz0 z6Z7h5NFAZDLxtJdp+VlmSM5-A5Gvb%*(vYaq4x~)Sa|ZIDM`_smSxa&2^}{%xN4?) z;<a_#!O@D`Ft<SUA91*Koo|>`t%jG0orf_>6cvzwncNR0eJ!zPvi9Z!9Y(KQiau?4 zvIaSmMkVB7@!6e8J>6%CQjAA#7^`%1@j1b9+YE8Cfyix%9=<psc`r`yPDsAzT4Qb6 zAx;Rrzdkk0N=vfAo9%!pT6vD^m7)lY?qEmQ!6pH;r4nnHUi`7*Gv0UnNcUNsZr+yI z<#Mlto;ZTd+Y)?s?@BD$!&kj6n8^$G$X9$VcVqzv599J07`wa%Y?s%7uU=lATkY~1 zOU32YxxBx;p6DLVWleY79}SM-VSuUiC7+-;8id&&4Nl&}SC0k^MU~P2m80Q~OyF6K zz`<oJaGK3?X8C34dd!)o=s1nE-FXoA>mw|ex=>+?i}4g!S)}Q1Y$gqi?`61b^nRvd zISwbfM_YOGVv#Yo@&aL29cCr&dM-BDtvn%iR$i>o!xybQ&Pv<9KH2mhHwDIdS=z0l zNqNrE&W9oQS?)%w;m+Xtp`#hDr`7DUJY5`J+eG!x)R)2XbkTYomgyB8A9RJ?D9lq~ zj*48|Q!&cuMd&m<6$i3!dn%j@?GhgtyR|!KPjKAggVla*k0pAz^H$71Ff#O$p7dUi z#ZIb!n8#u^W3zcI0%IPFfX!nu@66LH9*cR}O{>~{PjgtzJKNM879G*URotj#;qX^D z!u=D|YLVd%4u6FZJAXwi*~1t86_`=MDQX||S3q3H!$o#hntxnmXV2ZRi!9E*<$F?f zF<W&zr0U|~%OO>FF5#O9f5nOJ;cOl>c%z+Uj<A!f8YF3#Bhg?#$%NRSWWGWVUv;>n z3+^_2y-m{{i7&HFtlqJCuykW%bG0g#lp32SM9#j0%av~OS{wN*>K;&o-r#b@m~SH7 z6(_QXk6=eYZrK~9fuR|?Sbj(cg;6TZ&L|D?9=>Xn)+2ddIC0@){)*KGZeY}b#vrVP zO}X$)W7U%!6F(_v3$Gxer}SswRyZz<4ld7SMO9guRK@M_uqu5pEdy>Yjt<kow?MQ? zPDfNxW7&6wH^~PIuKic-qr7MZZ$=c~@tVA+CA$eMtLDs&7bCpvo&iJ545<1$Hbr(| zH@$G-)pBd_Q`~|&(mh;KW!LZAA%XG6KbwjNPjI+HgxR@6Vu>EU>JC{sqa{xt^oFbh z^E%k^SK~n{#vO)|iu$(JB5w%rXfM9WIRPQQ5ad<UBYHJ91$ou0h;pwfZ0K)po{uP( zJ<)xZN^0Ja&>?bvgcdr2%^MO*$-N)3WDj5UhExHXmKEN?kNHFDiyhF!bQjEbj0f`_ z_F%rlmxK9(x}olZ`My;6Ll*WJIL7jOvWE|JoJ`c?<Oz&?;~Rt5J=8qq#OzL<An)PJ zClAUm<n(&~<oULB0W~?Udv6G4T3LP(c?zF4y?o{kslOQI&DXslaDJmsx_Ltu4%XXy zLn?;fy>o_~$R6(U+Sr%`?sK`;9kFQQWMMa{4$_CeG(?6Z-WqY1WF8m4<hjo3Y=Gw< z#(MQU5A6K+m`uyzoG&pJ*(TF|dy+k7uhvED4;(C8A~6!Ou#pf0Cb+d*`YRp;jRz{# zwNC7n4i*i*&ED?HnQ2SWO^{>NF_A7a2~7U4j^^#DYTHKhcHXEUs<ApKM-C5wF!GQX ztVKR;1vEyK6XELXq!+GAc0CMlgfXweZ3qL`%*JA0dc-@RY^2-n^K1@*JMJKV5sUM2 zEN<(wB|4jtv`yYSoG01J*p9N8VHL7wTPZTrcP7HEN*-L+$f=uMsU{1qhE_e1J^Ipy z#@Y}q-*JJ^9@`Qt=Q}8NoFi<<1+jKqxA^@#ZbOSW+}FOg<2c#;|HU7#zy2=I$4Tc2 zlg<}SI=^G)Gg2hM?s=o_{K}lkrE&)Xj4cNcTP`7c2@u>km@_qAF`+iq{((-j2eDAK zlj{4jF?!p~;NW8IAb&g4JiNo!OvjMzpx38BjI=b^?WC%r9`p@qh}+X*!CWKn!1(;# z4Yts!mIZ2<y_D<TJ=;zH+Z_>xk-5>!<XPGEf(%t#1)8S*lo&IFnYL;O4(B-~UidC_ zl3DmQs|pwN644}YRiVxc5g3rm0YJvtp6KBQ)4)@@an=#W%2}mZJs6x7qH)&9JMc1R zITd;|t^GD<fB(y$|C&dfq&DlCqul@N9s78mF_i(Q$)c#C;6)dAgI2Q#1Z}MCxNwRt z?51sW@f{eky66<uaBBO2PSK9$;dYaaT#vR;j_@{6(`p5R9URUCA$Dz{V#yx9I_w-1 zuG9?iLw%uU>si+ZVb0$5$Od5oUgUbyFV@ZX`XJ2NTL`F(+P=z4bZrpk?CpCp^|H9! z)4gph)i=qcE8NIUN{fv?-kvF##Y*r8doY_I810YdRl^MUsJP5m3vRLDc`Q+=0<R9Q zBQx19m??|Z*N^^|mo*AEy%KzB#io<@DDLSVJzH?%tA(M7va{DGL%`5P!@w=891U|r zmJ!p<*dolpFHmxjm0NrusnpEK4fN%|G=z*aBgbKkN(wE13;2tFza!%3ioE;v_fNY+ z-N?Y|p$*aMoX;1_-~aL-arOAquPIAc{&Uzt#PKHbZ@~S#U-KkQ`UU^`NBr$ye@){( z1`?hi>1UvX>y@2-$E0Ucb>G5E17C1fARi&zVWed0{>?Uo!^SKr-p7lzSSk8v&Zovq z?o0Z3)4=SBt)Fyf^lrT}tZ`pjV%oP~YYs#YA6b#v`o_}HUY`PCjasYR)my!0qt}zL znthz+XW$o1{Hm|-);?f8#f&~cPj?FhT7M=ZXUi5ihqU}H;4ke57$$z7=)2#4|2&`) zQ;#!hC#N!><+aM;4B1Q)&_6&JT|iAXuM6n9szo=%kCPTR<-%6^<H$5M%18s#nzy1_ zPxMtu_PW`&G0m!j+D2Vq&@gP_gf;e~LqneN$}E*hx3@|st+-j&0rc(R)SqosxCoBL z#iptBM30{7>AF$%Vy{hEZakL|?LeTc2fe(^5I4M9I5va41O4;&>N<{XVjktdX1Mcs z4$I#$sdbT2Fv!jQ%3-XN1OpRRDwudR)rESURbM(32G_2PYK51elA)&N73;7O)8HNc zDnjyCBIME2Jo<>-WCH|W10hCMQDcI94?3R=5qu5u4!p?M4H2(zu=U&K-)1c!!Bz&Z ztHQ&E0UvP-!GuJDg)yi4EVRxB4$i%QzmA+0g(sd@ZC5&r236Q{y9%KRJKU}v&7-HE z=Z>p^5F6{UE5oM)olAxYt_FDrUgRp`%pd1!RV7fbu);9N@|AAC**0svuvI&k{Tl0! z1y}tFGF&tf=Ay=Bm2TVY9kPlCQ(QJ|PR{IJh$w?nyiP=K8}oxr>#Ya#r~=nP6WxHB z?I>m39!0@~i$pojdIaxMT5#B_jxSl0Qubhjja8YLtU3ovev!3>?2!z=6+u=_WL!mW zgxRY-Yl7&7W~Pg^o|*ZEUU@NOBfG_O+b5lgz_=&lMD+<BadY0a`fCWvA^Xy5{JHK( z?5=7vAG~Gkg4*m``^X3n@NS8K{Yo5&MKNBj;9R)1FWIrheuiP%&$K0u&vC&UwtVIG z{QINpbAan}mFx4r;1AvkXm2qz!H>|a`tSPNx4kM=q-CutP0xfJdILg^9|$2wryU46 ztob*D90#)e3n+B2mN%<Wv$h%heN3Qg?-J9?iry}wI&76cnM`Naf=ti$Zih?brYoH{ zd0aGanoi2igj}7yb>9JI<OJ&9-k^I^Bh-VRJ=lhopQdTRP)35>Y3_Dm^FTO>R)r~d zmgqo#0xZ$00dKrmF0uxpXW$uE8^|k_3@~qp#oFV7e>lgA`bT2JzVQ4+B5vBui}l-? z=)s$MS(HLs-vmU4%3lchz~S(w_ojpN;V%urnAoimD@N8We)mpe7<6OAD2;H|ZPWN2 zc^SyG!TTK+-oswu>SP%kk7@dwM{;!_+u@(&{UWnp#NB*d7FB5`bVA1)teXdO98xy6 z(k-L6v{<rdPxDDuXmB+U<fB`i9pqdJgmE>9#no={D>f)ykojv|{r26$Z|MW)YP`m+ zy)u=TZUfUGgSmm&|Mzd!Md{|Gn|EJh(($6lDe(zz)}H9$4h`k*H@-FuS&0*YDW^T? ztTN0knAsNS;fvhGVY7`J_4WJg{dPGDCY@rmM`bUjp-^=FV$2Ml!5qq%7dB}K@sK2~ zm)cPcS;tLE?o7k+If=!}*Tvgf*ugw8UZr`0J>4hWHG;>1AW!{n(Lv6wK-k_5VzIYd z{K`#(d$)XS?@rrs?*^>B>!9u39e8Q)BG_@*hOv<ET|Uln@1BSr%+_gA`=4NIAjrs3 zS*$(eYzl<2HHgL5Zt?rs${dsFYfSxi##FtVaLhyO*vU+E+p*Q$h7-s)>|{gHF78)k zrEe*=;w#pXvhm$o5j6X4V}hwCqBo7jQ0>z*FOLDw%&Q1+(edZtN>}^!6Ge2pui5Aa z-JK|FWd59p9zLgU*!#x`6*}k>a(19sPjD1>J0`IS#7*P^p7sl0I71MhUnx!Rd9LrU z`!ET6QG@PmgJK6Y;Yk{}LQP-PA)W(i$7k!~p0DH^!2gt&=m)QXw7hntjU|;YT$&*P z*!VtP;zakRR902ZhH~{O1}2-LTyMzMcYKAngj41!i1QJil5y`%U*s;k>9Ixx+*$3% zI}LsDg~zA|Bep?KSa`)T$2_qB55F5Xo@7buX}cE7+>&mX$#Z(PET;&X<TGRoA0n*H zJkaezsqcv%ed$puR1^F_NY-b~|L7nWW`kYooz?`uTl@YyPkjxFGJZt#QNju9DXAI4 zE5yQe8Io7$Ssnws$j&yY5Iny!ZU?WRh>37Xydp!3Esuk%Ok&)KSS0o*nny=e3S$Y# zhQm?$`V<I7!xy;%PM|*i#Su656RfYy$vZGUe{VzuKc4dm(AcZ;V9V#si{E{dv6huw zmw*fFmExjjL*3=1obW_jd4shelQ`3sujYfE4fer=fM$j1+DvfiwvW5&m=up^;BBUn zu$sCm_$q}omvO#bIKGu(DoI<-{DB#eRqoB>TaKN9`i{qUPxQ90Co{N%e8rJgB^=tN zh|?Q$=-_@uPAN3xIxFc6$%I#GY}T1AN<b$TtjbnowgF{)ofyAlvY?&cC!$AdvZ1>W z27-3vJnpZ90lAeJ2zTEMhr3|6_}wBu^Mv_^UHR?H0+ODot0vYcy+T{b2%hK#U;I#? zcw=0w`E@%0H(t~<!KHE>*(6zZ98SJB55TM=5B%Jc20tWaCE}PW7QII|&MPP2I%-+n z7dIFmI^Ccmc>=1<*AS^ZC!$9yOH0*`6EF}u^WejpPmmvJ2Kx!<v~~h^Yu|qYRy8!* z?7|P6fScxd#0iL&(zK&=0>ZaA#Q|8K1c~*R55Pq!!@C1;adS!M-(t?}cK)469?ep} z{<ta#gnYM~3XeM|Jh_fARj{_p6jVXC`2D9JM%Qi<<qxQW)n;3BpmwrI|132}hx}l+ zvKm#RgJw2^K400YMPWpobnI$`3?6ZHW-Y*GQN*MIUvtnOX&%ki&Cbc#sgBUztcTsk z`2`*5o6iup*quh+fmb&x0xa{AzLsNjpNC#2%w!?U)o(E~W6|qq!=V;EoXwU%FyunX zO(kQ;^R!yv42_m8?P}sdUB72BjfO}8Pwt-R(JuNyfoQ9Pe0>T8H3kxKhJ1qb;V%t= zl*p=rgLu>iI4*uaSC?nns`{#Vp7QXO?fO6=Uu3^phiB#s2{AF2Qt=$Sjct!&gv4u$ zgI}P1;itVhW>LRFCl64|e`yG1+Z(wTm}>c3z+c+;+XwvDS+f4|*WZ8OEgt3q=~g8# zy-{KFe<L67kCBh}-w{3jZz!u_-rgZw&pvl|w%%+FhF7(Ufc-kHlDU;SAKA7mmCD4w zW=rI~cjFbc5?nbCmPQ7vu2shNf^{?Bdtz2Ow_Qi_@CZs`Czd8@4I^3E)Xmu?3596$ zPSRkQCHT5r6gQ1Sc0qN}MIjIp6_JM^arM2R#kX6jbNo1w_doys*jw`I$)6-@a=3@6 zA(O165H(o9n`DjF@pVz#l+N#>#G@OxgC=ZsVN|}GWcks3pn3axxl=Z*{R+gweDVNS z=AH$((Gzq3Ug3C^ple@)7WO=oP_;xQq)%|S^h9s_x3daZ>l0wK8BGYSWQp`jJL4*w z^4%e0xFDq~$E+MHpqu?3?lU8>r+Lh>gdLAG*naPc9`4{Cy99@Zu^8#PPjP5q3z-tL z3z^0OJ$yA}ilLa_%yYP-S<0}{8qn0pY++%PI^m&U7$Z2VG?GQV{svh;X}jd_PU;{B zvniWfo%s};Ny@5}!SB#|i*k2&WDn=?a!A7mhaF>~i<A!T-3CV}Lzvqxd|^xU@a2#O z7@IzNsYRWKxk6^W`lNO<GL-TA3VZh@8w6#EO|)JwRb4@b2N5Fh^vb2YiUFN$UWgGx zR~|xS@`>)@TwYnr*-~&DMoG7LCCVJ=;TXvx%q{Y6+Y&u|F%cJBUi13lR9vc(&GOdN z$0rpz(g$78$=RZyIDE8tCXH22tVy}VX&=>Voq6zj1|=n76wHgHY}Dez)Hr>ldo-tW z>KqvjBNYv$)?67442><!PGiRcJ$zYXuXp$}?&!IitS|PC&$FU?!RJNuc!JLhH`{mc zSq-U-g|=^a*==mLStZ6&vAH9AIG2@!x975B#8$LC$tNgyEX1v`)Tw*;DvL9Fnts%I z%{Dy@vAFk|9d5=c+}G^UlbZjU{bYuH7zWy4MEWV!I6EIDOH_s7*7AFI1!bj;Bwv&q zh29T5d(m16$xG&YhCOg8TZ)B+S=OlCo5s9zW8*U(O)R@?sUzKI$x%D~17oMXiB1p3 z*-ymo=nu*1;LAsUlcbLv{YcfGO)Rue9HI1-1}`T04qr@A0ihCCJ=vr!<tZxmOz|1= z_(b>cIiHH~?auzd*jb;=-aWx__6xH+`(ue7zIyg&xKKx)2_HK9A!kUnZ)XC!$Fb1K z&V+3J0{l!sLBqCw$C-e({gysvXFpyKPx?3%@)GBKoc$-dhjV(?fU0&X1V-mT8Q7Zq z1je}_%<k-u1$y}E!BDE<!@<2DJp1trhi%X2Vl4}t&n1~V+W1^@Bz0cnb5V1u-Qiy` z3o9Rj&m}$gXa9-p(J8L#0oHuqfuOe=opi0s(;jkPb|B369mMi|cZ*+%S})TN_Ipp8 zIg8vI83?%(r&&Es&Dl5=_0$M&<haRMM)>x`#yLUkkh=;UmMhUo<!FqR2_ml}zS=(E zKTOo!55M~*V?I=(uKYQENX*4ZBmIyg{mbZ(kQ8S@ttu)iH@O7S+-+J|*NT@gU2*0i z3wto<BdwnLHen62iLEk_XUi_i%u!^vOHcIZT#+JIw#%Bs79$zxDR9}E)fTCV8ru3z zYm+tf>_(NOkq77k5eNxPkV~9m`H;8xetp1yoCRnOKmGnKU0|YmZ009On>{6h>jjCZ zI|LFO<1HxlGQh;<`uAt!Eozx*bgzfETUc2u-DV$PHeOHjrso({ri#L?6dAlww4Q|P zdty&Vwnc$=e`XkMGWYJK!Z@g0#G$sqyjzR97a-RT=N~Jmc%4yFsuxflXx{w&i}mga z&o_SYI)>*P9m%#WJm2+uDYI8S-<+nqgkPHvzy?p@`K~_~HO}tl<`eWppA=xW9;~|n zGkV6f2=W2454QmG44$SIU>5w;Eq*1ytSHpN`rl<c_glWBV11?k5&bz=wjl_FZqNZ1 zwWV}$<Rjf5&rtL9(Hg_WG82;#Uo2Q2pI|iONb+_(N!@Pn2H+}Zpod+o7nx+}_&O`J zkGo_27>kw{dGha<$-(;R&XyH9D+ApTFIbrwu=Rng*z`p6@HU6;0txdzFlNuM%x67; z&AcaOXWqvGJ$%)?$CyU6&G~Bm+8vIcvRVjaqDl42-&{OzAJ+V0NkkJ1*8$6s5`G`l zZ?jCB>1677%@M%3@{i>`$4^q}FdYAM{CJAXBF9g%R9aPbUvT_Db<%-TJYeoki_l<A zj-SE21XB*b&yno2M5+0G0%MLI7oHOwo}VU6=IROI>EO$*pPev$#P>5=$Gh<T1j2kj z0h{k9;H$o$F<HuY_<mxk@cr<ij`c}rx`*?5v1Tvf`w5KsdPW@sXE=O6!t8uMu|yAF z_5EOc>5wLC&Gh}g9|+np9x#?@6hxoESZz6s5OSZunAN!WvQGd#lP$^Hd_SXg@o7GR zF@>Ked_O0;hqo88xkK%62#ijHak6^-4vfP=nBCzJ3-s{i!vT{W)IakhrIP%G<H5&Q zF^moepJz5DYkZ!g#ll5CFV^ECd_SY*C^t6G;pYk8&x!2eY+fy|zOmUc;_H;zYUBh4 zn}yl4*%#>Ht87NSsHWF^%m$b|{61O#GyG;r-bBU&9xd?|2hEf;hpO2C=%-rPj>sl= z<k8;4q;i*cYyhj~vdZ|`Y=X(7KdQ=5&(n)WK+<WRy}y#%8>q=R8UbbA83B8;&yuBP z1O&zoeV3jS97aHsCOh;)dOG;B5wMe{j~D^d#A|gk0s>)1K)_}M1bo#9m?pJvY(_vV z6-L0M&is2D;6(QD#>#5(zOw-WV`u)P<h(N+Hh?fY8z7eG;j1<PdUKVPBJv>{psrJn zaRD?CTXwl0lg*m)vw=>;@5%j`l(D?C0q}a#;c%!JKkvf^IMF?v(>8d%9S(ufX)vSG zV>^R!I0&;l9AbeUzIr&IU)=|ff6TUB4`v=ZSf`ztN4IHdEXEMl{2d&glPXu@@P~LG zjl5Yt?!)QdlRZ3(tC(}cBR>tJc*L-B#zhBtD8~>tkM%U_9=;g-N$g1rOa2E(fD)P% zjCtplZy0&jm9>__6_0FBxwPFikG2Eom)ky3$m3WcVE3OljOUe4o|#W~eESYhOmDx! zhj96?v=zGNxX|-~ZV~pi{wYp+uzoTLw81}#-SXw8AK1%+9uNBIk*r+b4!yan2I^eM z#nPNgW}K_BdtC}12EA6AQ7SFNN07OrT&$k#6Ow51vX?<em;j-r<kW&gNSRR?LWp4E zM30>eB7bd~cT((d$Y5Yxf;1GQ31NIo2x0sVA1!A;(^fb>#)Zuf$5m1e{Lc}=LVb&{ z<dkMhQs)TvMg2GMvOHeHm&SxHZBTLGZV}w%wPuwro0g!zsTDU_BA2E5@-@2%_GIrg zVzn_Q5i!~}X4HDb2$ct0iHOmvPAHcnMxa|Kj|Z{RU`f+1U}PfT;UTLuIMBTP05JLo z1>hBg#hYIjsb3`W0UnZK@_C8u)4etxVYS^@5rT(hSNLqPAGRa#MiRIqUU_EC%1RzL zP<um;e`5b!JmID&8SZBG&_|-rI?&Oa#xm0#gS&4W;T@z;?+$cK@I_1hpzdL(xNx9P z)5>5zMt$UUd}G+~9acH2KbDP)Ai@2WKbdipc~rD;P_uKutY#Y)jega@kT1F!vmx+2 z^ES0jlKOe2=y*-otSIr-#sVA;rxt|+0}DWu)mrPYFYLVXx9=JYG@^I5fjWHS8PvC; zVHV4-HyGpa5CaZ)r2p!ILbB1BAS~nls}N}$rI28q#Yd!&da}14WE>c2M~@IW2#Opq zUW&v}3;X5sD-A?%kadbs%ye^1_W=jfDEcoAGs&Y%#XZQ2P^cA<(4RESCSOwABd<Cz z(bYeIr^Z5r;*Z=cNozyS^qzXM&l+8(z*8Gtwy6WR&noLc`}l5j*}CYY@bx;-KYzE! z76CB!-C2<kHoP%w{P*?BmeyaMfBjwkbGqZ09t#5?Yq1uAff!|uI5^qVH3QX;`-11T z(7aru`?oK&(Bt<)1k7{$g#5N0(I?C?LuE>1vmu<X%C+gi#%3WJn|-|wyvpVo2i%Ml zmanjxwwW1Y^^ew``=9O}X4ZIau(8}A<G4Xr8E%8g8pCa!;I|Dk+w;4pdH6i%RR-vw z*?q514KuZJQZ{6r*i)?4EDP4)?y8$_?IVktcE=I{kCxofFvVtSsR<AZ7nWU3z9B#o zzeAYzJ8g;XNiIwjUJ(UjH-v!=0G6{);8U*!*c3yeWNWC>!rFyx(2<LwU|X`@e7c=h zg9Br7Cf=4%>0A#b^tWWj$*TUgn16-SlzE0Z3OO#!rY<%<DcKk>F10udAh5WWY_mQx z`)ul-?BU7d3ojjZHoravVv${pQEAXvYrT;cWm!)SePMPzESH=AJI7K@LG55O4Gb~K z>N0YB{aXFD<A#5`|GWJ*qdxxj3&jUWEMt+$hVc~j3Vh0_`cx5}RgTCabq~Ox0txaq zF3dqeHy(Hd%F3+v-5Xh1cDAvr%gx?FdeZD)Kt(SId*DLOyM}UXQ7Vgs|ABm(SVzx< zo2sohH4{?Cdq?zW(S#7KX(yVFFyX>GSVA(<Ypg24CYmda$0nMqVt`KVV2Gw8Ot_5P zMNiA`Wz)Xi|J{C@Q6GQ%{i3NMP#8e{lSFf47bqliD#o$M=Er@RK8nO<t(&GcCU!KU zG+y(x+t8_P^pVo_xosg-)4s@4ux=7S^RxFv4-bqco_S5)9AOeOsx`CA(>SReNeJAS zb#jNU+$52%Nev8vbA*YE$U~sC{9fSv`|Sh%>x}&P>o3^+NLyLp#QJH<(7G@Ayi(j> z{T4o<MjYZcTPn&zrF3n^@uXC7Xhr#|$IUy*6uOJ?32NQ3%{cCf9)35FfzqVS5hgAR zXRf&{E%IA6VMFSF-3+1K=0%TW)DDKQIl`pH$X%AS{9f4X>;2#Dw>kCUw_mt;AoCgJ zU_VRN*g_w!zO4A3X4G$4PAR+;PN1a8g&v5qJv90B?m@H=U65JU$D#xhNUc;`{Qw&C zVbWW&q>ql~6C%Wz3EO1N5iTvNfOc8Jr14>I<xT7y*fiTzo|k6i85E*su<Ipt9Sp6t znQtg0&A;3};6KgCk3aoV9?8b3j6X}%)JJ_MYokt1lQmX_gsjafF~2Npvu3xMC@Er% zzcpb)2wSgzaLv{eJ-l7mtnl14amc{yQ^P2Wn~6{e$edtNd~wW;nMTNyX-o95lUx|N z!uCPR0a}JNy)o7M&+hPXPi!ZEbdq(khvaZ}B%o|^X(NpZ63?2IVU_z6Lo==oUD<fv zF-s#)764^^1N@WnVh)<`iqGI6QzltY_X&(vc1XlA0%MU2jRZS^Es{aZt%WXPfgZjZ z%HUWx<tV)u$@u**skt(TdxpssRmn1=hmTw6kJc1Hb&SGg4EH&SK#||2iokNE`6k^i zMVffA*^E@GcrUnDyb!^7BR(>XF(lzg_E}roT=)B}t;W)AD|c{n_Q%#9(ZF<UOPpXQ zxv;gZfB>|0GcNNfBz;$FFzdlq%|rzNfnl=6G}v5^!b%Mo-7NkYsLi3AP!M~8&qdd& z$y?ONcTdH-<tCf=%g<P!)id4uk>$f<j0%j$V~p&T&>o}y`|>@HF*2dmf1-WU;UTO) zp8a5#)+5y?^sS@<90xj`lz}TuVb~D2OL+BqP@n%|h?~4F)7t2JI4JIIExCBNcig{* zrON(yjdfeq$P8r$Bj<jtijt0_JWO`<VE!j_oCf6^jT*Hg1&q=5yzOlAGZtzzBzA6u zHxr3<y5jGIS94Y-`aDarvxKWKs;EI>y5p4?UT`LRyE&tVKjOKI$=g6no)sXQsU21Z zFrLhAqEIha8e6js57ofriHArIFN&{~$)5q$!n&=u?mY*xhesK#Tn)*Yna6Hm<U*jQ z1a=kLj<sAM0~KSaZ~PV?SZ1EjPVS)A|I!e=9~rf*kgZFA1L8~j0r3(4fm)$^f=khb zaau5!6|_rzYi}hT{l{PPAQPSgWdAv4%o4}hvHu2KHSo>0r<MOl{OxW7KT=zYU-Y&? zIu2QV^iR%;Y9mLB`6LGCnSS3dj=2S@|46{t$h;UhhPkgC@;s;m50YJ(k?)AeyzepZ z!#3L25EwXY<<{2pIFCvDZrNCzIck$$xEgPo%r(Y4LqRuM{*P)Y@xry)w`Js%Pu-4t zvbRsWRY?MgXYni3(rALD(JK2VrucwA$tv^_17$YSr5RRWebz$Tq_3J49!iVfyHE>` z!;LxDYdA2EbZ<Y$Vtqo;rEucaVli=G9yJ{Zj7=qN%Xw7>L(<%{3%AEr$xw+M3tr_U znv{pQj4V)@SJm6%!Q%edk-fu>EG@y-hkQp#lV0jWAfFpBM}#N2^8gc%w{xleCKeiI zdmXfM(Dj!)ab_aRi!h@W*O0N_-k^K1qRxwE6*E6>grW`%wqD(F@JAuy*Mau=FOIoM zjL?5Jmh53Cxl@y7xZ*ao`9M$Gx_R<;)}()DO4K|erY7%Dj>@K@l4hrjjH8pOJz3=# z#VlAzLj@<xo+QWk<XK(5(Pj}73*k?(6j>Grp{K&CcQste8vr3o!64(<gLubuY9-io zRWi6VI%%XeGN(>dj~__{ZH{(Xin|12VqNY$a%{Z?R9rE;Hj2BuOL2F%;!vQtyAAH{ z4#kVRySqCShvM$;?*32Dcg}y$z3Z}An@Pw_cCz42_M1mmC;y9&9OzSz!UZH5+)r(- z!9zLONP4osUFOU&XM4%7vm}})cGI>a^$5xpt47eGNOUykANFX?APs#?p>PfV<I<jD z6V#Q%p$vz*EtKW6{>9>rKA)3*AeZILnz;joM)~Gz-V;O0!5@LnhE>CE-q!&rJ^{I? z$Ipg}osrSznX|1$Vvx)qj%7BAO=?Aj6yeGhH*Wixt8a(ka0mZ8!EJlt3?*J-ztZQ6 z_x?>^V%hqPA|=|?T4dTip7F=qprA-kVO+N<M7^1SO>^p7(M(&UL`$G8U<}q#HUi8) z0<b8L5CMX9_TioH;U41<Kip3*ZTbstz?Tjjo{WzKL0J;x8Pb+-^_!${%PS-{;?c(K z^60X!YWiQ?p(hu+Fp+Uq4f-cyz7h?6-_B)KH(XY47@0-Zzcb}5eUEw!t9gO4MeS_k zM6~dRUk_tqU}s68H=uhaut#ySwy;MPWuQX3KgDtmV8Zu`44rdZj|!kaI?ZEH2&tpH zfgosRKFJZupQ$F0rQ5X66?OHemhI*5AxMTFM!e+En26tw%sc1T#8pEkR3n7jCc64? zW=s%2FmL3~3l9)KVomJ$I92|_37W&%kpMV5R|DKHKxt7=Kk1(r&cg=jetMHW?0B$r z|Dj5S+(PgAfQaf)+#7o{-0QiPB6zG%wN-Iq${ao3)0u}l8cQT-X032$mUsU>(-dA9 zVdUh96GKB=T*t#BnICr5p!)LA;d6*%L(l89bPIL<HpKi^bqGu$4pt52_Z?K=U#yX- z?lc}?l#Xppf};nOAuU13B8v0_&$hv3!br7Jc*B8@SC;8Is*3cuW$Sa*{ZtV?U>04g zW`ql7b?!&Xu2I&-1}Ctt1?Iy>Ze)Bie9z^CgET9PwD)wO^Y#oueyQAw%``=!acZjr z@t|Q$rxb_$HC}{s$&Ql{vU)M)C$dk+Z<=Vxdz4o&8|!B9A4GYr3DAKlkJ>12&Xaq) zPg{T0kR7_cf_jb|Iqzme?DTm!T<Tc?819QcYNjZm%0tbrBq~#&-7a6&3LVL?dYIN= z>=jserXc2ri3Pk^lX7Plwu;8G$H?4S6V@VeyZO~f?Mb=~3z|g;XOTs)kv2_olP1n| z_@+^$I}3KE(E0MUQ#ei5L!Jf(Id*J8IAJ{<I~TRur^4pRo-Owup}2o`_CjC3IZ<g2 z5dQTpV&f#c{xggD_CTj>*S5qKpH?%$(y-dgKil>ck+KUPU3sF6MPpEN!#mSy7P~_W zgcIS}TE_V}r|Dbx&y=Kb9UxabI%1kGZG3^?cU9zyPNMYySoc(RlyJ;zu_O9Vy#uq4 zvv95r(q7<8f`2q?bVQlef=4KBSFY<rrI>ahsRymh_kq*7V?qF0Q8};F=q*4k4y-pX zDUbwK3RIuWv&CbRA@db>CM(9QJ*P#LL$^m`*@l3;ZA)tSm5{~0oee3q^O}FMBKYMF zr;uO|hA;o4C}R0``QKV1o6|!SlY6)KLZ?C>;vZW=o4#LM4-W|Pe%gLtbAIk~!uh|& zjOaffEY!jl3d^44O*x5Qu>26^9L3gOk-2eRw@@pLikY$E55v_g2%y{2U0?kGwLy^W z+ah&V_mwoc=P(jg7kT)dMecW>67Pt*ejFWSL-_P>G_|Z&8haHU3W?lQj~K{8l$;sb zhiXy=Chp{$Zfp7jxhUjT1Ln2@yX_x&QCy2N-Xmbb2xJF1^LG(>(Gfuymf@4OSU76{ z3&DXxckGyE8Mq%lBv?eqvkKNb`ox4(G3*$8n7K^qM53aECz~^kmSO<~la2+>Q_jic zA5?Tnh;b;J!Dq0E90BmS`K9loKC|WAq+~`Ob7?2`9rUiLNZlM_9o`T_p3H^9cpx@J zWlMm;zr{vy7nd!36*us+epOo=CTTJSh+8JSIYr)u$DV6*U3acjX+<8}gwhknLfNmL zc?QQj0g)7DR*xyE*Pv%$v={M_VTRLVxE;X=t`o8RmiqY;u};4i2^h1%R|aGrRN$M( z-(X}}B%6mOvUW!HQ4X<&)#+yjQk2=Yx6)LfUoOBe=$MGz#ya8g`S|I68I$1gvtAn* zxK|_p(*6R4)^?&7-BvQX;XEwdQPASphDoDs>DqIT{(NE{Ew2hcWV9x!kCERQmqW<Y zcO<}W^IzcU(ztt@KkN<l^OV`)+MMg`a-bdOA<sX>CoT_dL@I*5xeN+2P-^Wgg@@Tw zGT&8VbSc82&#%GLw)n1Bj8gPajKL1e;>7mKP8d$KX=Rv%XD+@HQ1^Em1||6fk(;(M zWac5_=d?zCSk0mgnG8KL|JP<!N_PeB?dv&i));Ed53W(nfe-$gO_@-$dDe0NA9#=U zq#<U_tGAQd9nTl3Mg<tzny?DyRBX$*p7~xS4^nY&I4cjd3uB8ZE^3r3+*0`{QmkBC z`8tg^KWvHDrRlpj*CUaaP%rbjk*V5mA`g4(Yt~FI2hle=Mwt{Bg>GSBC#;hakeJYN z{nhmpnJ|;*qL}+X)NLk=YsVZr8pL7~&^P#2ML*)27cQ^d<#X4X35BdjUh|Q@WkjqF z)3K<acyf4abp=4LDXJn&^kd67G2G^O9?XYdUJTb7p0wsx1YqNTkLF)}(J#G{OIvS{ zgEpJ1T1+(zVFF>PHB_V?Hq%6~+!>?i$)q?3cOTr;sA541)|iT!Z&WnuDjg)GwZZnm z<wwnycP;cXlW!7P$PaxEU0&{<7jB;$7RXFZu@4Aq2v3C3cavEm4Daf6ii!OdBCx_| z;SloqHPm0Eu@F*+^7N~X9gDH})wPQQhhn|1_LQ;3cSMBzo9qFf#;?pSj#lG^%z@@3 z16{AWObz>SHhg3gJE0f$h8*>^pt+HA(5)b4OSx}Y+2W0#)mMFTZp3T)r@qzf*Uiuj z)wXYP2<In6-oYv1n(OdK;!6jF62T{BxuRY~UgnKI6$3_?Gi-%ru1{KTH%eR=-1SDZ zLg<l`aP107{R)GA3S@dfXC4$(Ohx6Iew3xoL-$OSa<AtLn!Eq_1p@H3!LI(}&8Mo* zw9;O*JxcN-v!nVHLRWyjsC0gM2L!0hcqAw+-l2C;25ul#$QkJ^=v6^C;IhVOa92GY z&V%K|SZ(DnhWqj?^j4gr1{~_h#dFnD2o2eLm}=%D_&N72)OVMQKi&3EPLfmnWGkNO z=~JC0FmPk$XIr5+^o@6B(1U5bN}m7+gJ|chsv=$uKc0E>TJ&EB<a0%(6JcV&-nl0; zG9@5ZB5deQdwMND$kAR?UAs3^fVrY~8P4C2B)dm+OJ8Vr+9|ye_BU=>$T-V8_DH1R z^qF{nmfXwrkNf9E$7zPcm3)5NZy<3)ge&PLSdUT+s8cgnjQmdgs;1zsGgXT3nb7xC zVG?2kFhu(v%0%+#puY`HBz?G4CSMs62XNJ(1QUwV`lnJ<rY<jncSb<VWLTC4o&po* zr!M_3+x#9aLvRPnyD=^Bvol(}2G>Yr1b*J=RnjG;fNk%{+~yX$iY?dm>zWqiXFImr zJ-Z%#33%^<aG$+R^}rnJ{DRw{lod)*ta(EkoJ@~L>`gvHa~pVlFp>5%gYLYJDY2&6 zKjU+08k}0fX9kiaY5)wQf&qD;rpUdyM+4wu=EpQ@1|BN5a~kzIm%qBgp?LxPH9Y1V zcm7qNAITlj={}SMUElZG?Xgjwh}u85Twy(bp5CC}kMLfAC)G?2I06|wi2HO|a6;-d z{Zw7DYT=?Bx(}QA{qd|-2*UQPmp>>p4(v-XB5A}Yo%^(dCt=iy5~*j;DqM9|TCW3t zs-(g$$!#9_r(SGKp$rGk6xBLnz19_?@a2bP9J3|a&xOVOmdKc2>0clWL=@dT8E`NR z7QEjnt?jf@4iX{e?Z-?n)!ndo=n}lIc|u<P&kWha_r8gPoKu~MdPS<@?0|bkFGcL% zmUSJNHg&`V;Db{?jpJ9R%$+)4SS<!%oxr1VA6}p*wgAujZ$r7d&!_YyrHt%9vSmi_ z89%)o1_Ue|#5nG!UrJyrL`iL9m^~aU6DYMar=y8mm|Fav^a1n3`o2Alh6-m8N0;(w z&2cZY<0dgvtYyyV<@SlT0|Jml(K^EHJR-5?rgj@l)=7*qVE`yP_gZsO)yZx2peP{f z@O2CL*V~_bkYmw*2s0{^UAC#aJU!{D<2IYD0*yAtFxlyb(<Dl21MHo}GKI3LTiy2a z;S==DM#A^~;we&F>qF!=A*w56Mn^WIn1C5V)Iqe~gr?vO+ghBT0&JYFVeB%cxiW91 zLMf|P197t0eup+dzV{?Fr9x^b{BULy**T?7A%<}Pu^_`bbgsOu_%5-MXzQvU_X<gx z{U**q>Gzg8%yLZ`VnJjj!^~y>h4womfsp90M>?C3OP<T8rrwmK6P-66bwl^x=EY?u zn5G?YF*R_H1vnTfYpPB#ca@B^hVTWcP4yYgob5}y;)a4l#W!bZA3x`{!NDW0o;GAx z)=@`a)xp90z9FkoiyF+^{Gg4y%s}55cqo9vZW#|JeRmC5p&p@W>X1|#>D2uhAB`S` zY`(Al8{RqvU2^$CWZ&Uw`u1%++^5H{*RMK`*zW@p5w=hN82ueL1)clUz%TDu$yNyx zzv8|hS_f(}yso-zFtF}{u(!jlC*ltd?83!&cRD*|qo(ur^tv$l?Z=?dHnj`qZ=UX^ zKCDy<$0NO|p&9Ct_!&@{RbHOT@oZ3vlYA6BnmvsQ4M<_}2vKF+40X!!Hw<~?dv2-8 zQU3`jdHzBy0=GvNBd?k4rZirScbZNiG_yFxO3ORM2c&6F>-EaNoeZhZhjfy|@i2&& zvDA*hoFUU{oX<gbk_(U7S21vkJ+$@nu#J|BOr=<&?qr{?e+@}RW5dm&7Voe|3hRED zBB+%~+5majwgf{h&)*LXFXo{_!Qg{UrbaJ5)^7Pe%=NFnE`=6LV|zYCMojLF-;YWq zy&_qHzoDdypym!KK)5>~K^{-%F#~@55fS|Lt>zrJE<@BI-=ncr)e6(HG(3Y;#{g?` z$-zM+_R3;ybS?0chUV`ce~mEj)nPOWGYzWr$ZrOk>miPZEYjddbX_szo@ZZDQ8Rd# zyLV|3&bW|@Kq~jSkYR?v-v!xL`~J8{zSXXUU6=<~n{>tmTEg(?`LAOsqq&4sm7+t* zAx<DWH%_Ey;Y2p~q~KPYh%FAm+BQ-<>FJVqu;3O)aevp!@0LQWGdx;De_$*JPoh>Q zt35f)7SG*!6-;#t2^t73MRo7h^yqJMx`w|<L*=09rq=>R;%w_fZ_5}$Y8Uj!U~W_m zjTzh>75iJRc^lB1<yg!U=*52l<4%}RD)O>Y4tQR&%QYHHoets!|2rz-6&&Amb<1Ob zHO+$raczkJ7lQWU3Yh%j%;jSDxAe_HJ7(E;F$R0@KpE2Cie;2S9S4NQFa=#E<rweW zfU$g;Ir`z(TqDtaTDA_TI87uSY3KDCsonNEFoYz7Um2zcngjQu)CpDY5uPHOesZ9O zimLD2w3b}qgpf`>_VP4%Fd<i3^a%%I57*3fKEjFT5E9~~kg%2X-F$(Hk;bWN)pN<` zJCO%`zl^XBiTs)%m%p&{@4;yD-4*>)H;v+5!p@`Wb~N^aN(I*F>j(+Ns5G%V(!x#M z=_MZGXtJxN0`pma=$i>U;Zjk+<$Ej@gIrpVcFQ;;anA|pgi!$I&rSMRhTc~!33zKq z1DW|WfmFlia{BG`vHgTt3`fHG>iZxv2};!~!}CXw5-ZhpQ#E85s&&6PS<&M`qB0)| z#p&$JK7OJ(>(T4Kd%eHPjFtM;kf8<;=G@o+-8erH`YvLSyohhu_!c9_cjlZf*Xc2N z{7RS2;B?~2d32^}c7wSGJPIQ9(578obK7#(D*YGN)ZY=e{6EbIp(no?wsgx`3;yG( zLnjGxx(Md?^B<ruFXQ8!L9$$`ygUn7dW#`f+UWIkdt4cw6$V^L`$Y9F&b+FbbUWX= zDC5s2#kXpBq;c2~uw3)nEH*jx+l{Mvkt;ihfo3ge>z%H`h@91o&4Jg%wLOk@{nlxh zV(qL^lYaoXa@<46VAWSzoy5<;aqLKC`J`?{G1|)R;vh>*PLQ+Va*Uvec!FgpV@)<~ zXmc=UR%>!d{9-Uuo6IM|PhXX52u)qTUk|@TKfke2KVt~e!Er7#_`_dCMg3zqq)j|0 zLSl0O`%SGEP9J)**0;w&ylszuZC+}Gva9Eot3kH<(q?{`1w}yW=X64zyHlS|b#w|e z>4P!Fgw<`Xo1z<Bq6N+AB$BSX(50ymaPu))$28o!=Q!YBQ?PLU@VjAxIeI+0GmOd6 z;}1aBw8OVhVDy*X^zm}sf{@;ki_)Yk3n5iV_2QK~Ia0~U!KxH8N_{tP#oh{C69s<Y z;Y_;sHrp!IZP*$8*@@t|iG?gu)bc6TII5+rYtUdC9+1?ZG+Oy()_tO$nt5pe6ncul z^UZn*j+yy>4`sI3J}`FQ)_Wkb^b7s6$FeanZDtkk+3e3j_T>&1{44Hx+Bu9Prr9vQ z!ZkPZB7nLydT@B*>WEn@f+D5lYHM&MqH2|~IrwCG=mB&Ybfv{1ZmhFA+9ChvnlC<f z^x~?GF*lRD!g=#e_$8a{ETNkyU6{CMa9~pa>|!yY{+t_gQs~TB$I_e5q?`Rh`%aS$ zKF(S*=vp)4^J(*>U^jQO4L#<XTCB@@GgUj6+(ca00#<sI=A%_TfE6<cYWbRn{LGB+ z?_@m^zSDkb_IV7O?t`YZW@2QFGyi<sC{z(RfwJ$iC0j+Hv21w~<29c8noM%Rsu)T5 zL%b%hmhyF6Laljn|1^`Or#ZkvQCsB+EeAM>2H{Ydhy|e;hJ~5i<`&ozksRyR|8hl8 znO+44A4Hj3oN{$Y_`722^`VN|^-y*IGhFW`mX*|m!xNmH%ZhxCGyyel3H*W*FE8Wo zbVvm@Q6UlIT;h4N#R_%fY>9DNR*iB2#Uu}S9tFQ*%h?Rhu<ymRH`mausnRSuh#w(B z<42|Gg^7kD)ti1_kUn_@vb{Wd88s6TnYGLFzN{tN2VZ~)t;yS;!x*~q^{XHER=nk9 zeG;!C4IU0PU7+BsA%U*B+CSgA8YHZJ*#1f~;=0aj-m^U(CDIe((cp@OiG>{6)lTqC z(!95trKk@X9-2I4UWM*|vE2s+5`dW_Y%KzG-6wkTLx#_(+@0xt^9Gk<V(m#I0yM=I zp&qD)hf&s7F%oq&s3KFrI%xZXlFd}3OgPL%qOj}~d)9FSc=#wrgP^?XHeXIycT>w~ zk<%8emG9a}Cu)R6;X4cu28*fG+;!-vSU)^PbS#6!MeZso7gI<oL>c>&gmyzB>HLH3 z8ajir&uv=pq1)OK$}7pGABxj9j&69vj_WuoI<E{cguSR@YAW#YWAq@#Z_7X9!!aWh zs#O)9)PI1?U|J^RHzTT2K8DwmorJ)I{{CSp?oU-OX?On$c}_YbA{BG<Y&Z*l+^fqS zm#Pax1B`zaq=n@JGt7?z!i9<nlkuhxTJL}PTmg={b)TbS`Zm+mcCaMntcz^6zbKLq zR-n}S0>+UzBV8woO3}5_Ynq$((JGl_$hLl;n^L_O=hS084L+*GVnxV-j%O)w4;31W zTfT1w$WaHc!2Tm(s)rZ_2|xO$qEkXCIsmLTVxMogrDPW;k$#ht8iKYTEQA7dSu4St z#Kdk6MC=5Oa1~M@R~STBVQ1RKEx|=XP4O!=SMy`+Aqj&k<yIXB71k?Faj^2;?bMJ# zs>Tw1yn{IncN;On73CkV!Tt^cibF7XhW>;mK^{PG(x3sT#Q%{Clk#B;#tvZKQ!$dv zgdA1+Iag=6Zwn36jsekJ2?lZ~ndg7nI!qiBMI#&zN4p~w3vi@|nOdf-D;BV_jyDDQ zA~~viCuJ5C#d!?5>0Zd0S2lWTqk=KX@v0Gp4@7uuRcds~Qv0->%SKt@BETqSJqQ=5 zob|b1EAc}?sm@xaMNxfkV_;Ej;ebp}JYU)cJ>|5+;ePqS&|lx)*`K9_G|X|6S!40e zsNj=#Gc~Ox=A2J<+ta`5YX@)Xs!EMM$K$$&YMUdM(%*H?PKbOQ2<M@Ej}{ORR@!aw z=$3^0OblHE!hyuc3ZlQD4Gcm=KD5Wme!m2Fa<jDWVPl!6qit-hqVQg;kCiD1VrNQ( zA)6*`qM6oSkLSWK8=_L06Tr!u+b<l0@e($iZ?f=#k<^7sea_V5`+b=;rz_|BG9nq5 zYfyv3#!jTIHA;CyPe;L;(&f;iF=2r`5NyRqU5QZQz{9*x7Y{n_85lU;57dwN7mmlB zJU>J0yN!wE8_I^4hv$smhB$9c<brI-_5zmMZ%!pb)5Z^vG#UK&PiIh8mPcG1iZEkX z8lPmJ?BD99hue)E3`XW1nsS#>;jrKvj2(VIU8`crgL^Jvz<c?)@sCvvC!+)=Yerre zKU;3kZi{M)z##0(l^<(~z|aPB36*l*MY}^g%D|+dWxz7O3`|y|Z>;ILvA?qKO{dd8 zTUS+DL-!8uDVhTb4Uq+Bkax-ow=ll>s9HXw=2&v_GJ39>(p%`-tA~Qk><m8E7LBr( zjduma$AaSo7BTm|BTht=Be1T+?rhTQE=0hvsjC0_m;B{78=;(NY+VshDnY=&shH1u zB~5Uoui>tESZPOY$(XR~gsR<*APV1$YezcXF_>j#OkyW$u`Aptc!s+obN>e(3{4J{ z9NEtMbVxPT0z7#)Axsuji|J*8l~Q)qUt#GmRr6(+t`R0$nk9uH0>Z5+=NuQMutcsX z>86~&RNRI9Kdll@n}JBT#9Qtvp>MkyCTlY8B;?zmwg4^i91<_-PQ~vkLs^MKB8=-7 z7U}jmr9{3?i#UIED<*p<k~?|LD~DiXy3_g_ZJ+-!;8!8h3A+<)r>@)vdWOR)s}HQn zaw<<H5UE`pdshuk2S`YJC8ieH2t$&vV=P(V7&4b;25>y}GYEe^M>PdLPVBR-P+e<& zPQk!JNel?v`>E6VAWKHcr*hJh0|8@a!hHPQn3<i#jrflZ-5;@hlxiYT04u1x$2W{h z4#_v4-o5G%!4H8&y$_`~AC&qWAsB2si1Z_mC0}Bkheb`B<H5Akoq+s>eV%3ygGxe1 z0@+&XE?vg?*=D=aab^2ej`^x)D(Hu2IM6U7m?)Ql1+<RP_D_l#c`o0Ohq-8d3p(d1 zho0b><_&iZzasG=WLS9P-`OtT6!X~Q(RtkAXAA-@`6|_v{Vh})r#%EB%4xebnMH_a z9u#4jy=xNUk&5Y@nBkl(o!6~zSuMHo<!M6Qaam+vC(iqR0Wm1M9U56`<~6;o%|Dcm zsah>+3PZi~s=R^oTG{o3j^#Px(evZM&ExX`c}a|74P;wEhdOGo%V!z^q<7UQ5(5`a zQ?6wq1&NUkF%NER&<JM2v~RhdG{Z{&O}**S$Om}x-|Yjz!HL+yydmJUD$FUwWzr4( zaKjYSDqurU0%WuTaYTJ}`jf)cMO9;yI<e0UH!o&x8kFGr#8BR}%qplOmTMS){~(Iq z+03iJUK<%V?U?pBGdnPHr5{H%bV=e;u1Ku0#AnZA(+~GK7kW~GG&zzZrITvBhv&Im zi%CYxwgwb+94~}Pn6V?*%zp*gqiwh*PFLD`Kl_*8&Pa_UFvp1HkY`t2guo~2!^#oG z8l34K?zYilQZJtMR!okRyJJnB`Lu8i3ZN=U?e#MfTHH2ACaSwgi8u~f64w5XV9~7J zu15TVY05>Vt1a}vm7OKM8%rJuqQQ+`Z++ucwH_G-h^DT18#LjnrAaQF58y*5y?;GI zt?+?$vG7<bD^owbQ+`wK1*1RQfV1CV)Qo&L%m8#;bc>7b>HYeSl;|U(eJgc$tS5ZT z>1jX7g)p)3dh1&K0@a4T$UJGcHsbZ1zr|VLNLix?`Mj~|@ecBmj!l;U4sdic`>^17 zQLv=M1J9gfA{SB!tr5k{zOBuljOAgc<jBceZ{pu8ysU5x>sMRM#4;TiKntC+Nb4z> zf%G+I+#D3?GEY-g^e#U1y>MV31}<QlMi{;Yp>a9XVn+}i=%wNDFX8`Wh-T~>v5R6` zV``D^cm~|&nH`BZ+}TdJp3C2;o$${8qRy*1e#K><rdoP`^J34Ld2{A1jqFtrp3s!e zB*ZusNzH190j@jcjDQK8<uS>~(Q9z-pPcz*9%@@Cu`#(N#<*nMU<xM`d5qJf!kT5L z`sI3q%U&MTt2u}JJ&8%4%L7(DPe*f$Ih)I`IW*`tSI|R`?c;s0F<r!tJ6;0+P@i6Y zRM^C;Z+GOP#TOsF%bUo{k3iD?(<i^cTEW_8Y?9H{Sy_x%50#fY_IN(EK_Lv31W&-R zRcVzI1liUUGlO_715m0#8Da&$O39mD9Hqy8uGj03pdyECnB1}QX~Z?=_&ZYSq|A!J z<f~+<*KVk>IxP|uw9>8m*$w+aR(EaR*7s64-+R|cM<lb&3|lek-~6m^?|~#QcElH~ zS!Sw+DiFQ{@JoPKB37{o7bm_rpJehTWpZYIE|K3c3Yp(XC4DU+fHJZI;^hRB<AoY; z(DlC4N~$l0*$;EfW3LwWoHK6EMvKTW3zEGJZmUY!4+X>N$eKdH#qY=!(dUPhK`KPx zXD<T<d9D;JDj;W#gFsoNovHP!S?B4zMOozX7h9f3<zQ;nFVm)5re(N+5hC6nH*9_z z<+kk|IBb+shX;U76--zU@>IrLT>!XaTeV9pu8CPxI~_?<|KAN=d470<sg6SyXdr$! z63ZAVYA{h3>!<ynR8da;VglgWvw(B=lT#1_@E8$@Wrh?5nGW78)i97EI$5#q(4pZ( zkJ$$hSY%oD&i8swB$8v<z{KPpDu+?yx%8~X#Dr;}qy6`gZK>E7!Fu_P=~FTSPAwx7 zRE}wD#u8R${(jba%`!R=&X46y;hV#&l4`(|SE#O{gja?o5}Otuy8+Jp_Ps&}NG4FP z1OP9>E)I;%e)Wdm2<O{{Upmp$&w)BFDVSZ}LBule+6z`zQ#-Ofx_kD`);@do^<w$s z1b^{DY}UP!-se;oxHIXul-DuByxQHgvM6FIf;wDPOB&GHh$?e3s~m7=zo|9zCbYPD zb+iA0^`YewXHSvVXBV={9hczSA6zZ9un}0cvzzYPtJG!J?dR(N4>;XZHO^G+sm*KX z2;zhR@8V!2$jNATnMxG)u&OFx#T)86j^u29TC^_T`YU$znAva>HEmesQ&eQta@hZX zI;<<SH+}-Ud5so)m#0XXKR(`WmuQj0!#;-4-jZY7$ffJe`oztalkW(2BeTB~W$hyb zh$anT2>$z=qLXdB*eGO*-pOhkGKV<4WDScY)jB9=ErmM53xw0YVLyxpk)N#VBsRB~ z3sLvRudsU)&L<*aw{f-ta1WXkR-ioVOOJi#RW3~pX0B`XqP+6v*3I7xRM9p8xT^Sf z8hXJy<hu($pZ}p)-pcMK+zF6+H4BQlNF~}ePyiVVO@i&%j;VhR#Pptv7YDOcX~#{W zA6FtxB`0w<j<|?^5nYzwh9+ifOfy@$_~SB_zZmbBXHzE0xD(PyGCEjC`53HYOgp~% z3smG9E}!&bnOC9h(tX<^^9?dwwVQ|A5MB3c6A$s}T1FP?N#WLqL#t<&`xPRN8*~~m z%Q8(zD%>miAYst_Y8_`^Gaa%r@s30%Ug@TBFuwTp4VH3S4&Il?koOr2#(hy;Vhw*N z9o0Y&*<C^2lNUBw*vaSi53atO9Wu&a4Q}~jzMEcx3%!<-zt~2N&1RdKqnqoyD5!_3 z3n^vqA_#a|lA|=T!JW3euX7^=f>9oMg5g7GYX}vR(vk|cK|he~a{}Ity8GJ+Z0ot# z)AXy7J42Ep;38G6q=lJ&@Y-gKCz(KbOOC$zB3ygd(1Q9y(l51eH1s>Q9lc3CUTgYP zRF6%Po#HqJ{2YXPjxo6V1=n!*YbYMbiXhWk__1;F5_Exs1ovB%3M?;s(<^o0lAv>W zj!!;ad&bkLrKq!{MPP2OyW}bDaz>UheXhm0-Z-jaIkKup#6Nnp|2&ldC<~`bX_oq( zjAJfreKYlvTZ(V_7w*12c9W%~1`oEKZb7j_n>*WaNcQ5}i%#O{=pmFx{Zd(x+T*(C z&h7x93yHqf0T}-?Do%I_o`9cTQ!tz6SzD)>N|<2`l$;m?XfzD;f*%=Ms}X<W9MxzV zh8l?K+&gqw(B;xBto}6F?402<ZJiY;MJoq_uxL1bQ%56fCfW`yv6PR)M39XhqOYtS z;WvKU8tet&a9_=9=sdC<iqyIAv@cXe^_Ftfh3O<OAhon}>_7~IP)xB4XUpAdS_*Hd z#ywQ-{H34~PY~W1{oC9Jw^`lDDMS##!^%rvI$r$aT}sJRT?Hj`gvhr!$#{7AJ2NF4 zV@FIKVg!twL1mS>g0}x*>uZRz&99wW;*%Qxw90#DF+a%nZx6C6lq?32Ll_l9n=~1n z=2D*B?9EA8+6refhNdhfVE*DZjg)jw<KA?FjSt@+%pdE=zEA?;qgcDt#^ZQJ7_K6L z55$bX<()RN&Wso(b2N>otcsd%jp-)e`d!4dxQv=_zzaaA$AoDbq;S~_-0`WgeX1p9 zIgJQi@|oO(pEuB_4DI#)t}tvR$lG>UX81ezPkV-6@5(&EQ8E=XFVP#O0cxnf5>z{t zW4ppoZCxH&4sBHl6)^eZmte4_yfgCA?W)U(9nLN0(FkW&?sh%17h_Er<HrZ~`jn~j zu-N6KI-l@XT|yj$-}=~|fheCf9ot7+V^vgp9;@%L8e>H?ePmVCCRcK_p>|tiV$<?C zRr?gHJbnsz0oiiZ9N9dQ3D?i8ihm+nZT$7*A;lY#{q!F6x;<B+bzKCt7YF_|mj`vu zJ{@aHbt#e+jVo6Nzz3v78t1My3Hm*p@=ZqwMUJ3?FkL=|J)97yFkugrm+*q_h}X)# zcM}Grv04<gH_yK}%LfD{W#c@)I-5K9cWB5Pf6T+f0&d8S8?=Ag%kaAL4WT3c<G`i6 zw>B6HCc2yR+NQYU;K=YJETbV4c4xY$qC-<Q{Q(LLq9H%14F4I(KEKcn2sK<(5u5A| zNUPid(?!VO@K(k4?oCiVU90wQnMmJ`<s3*`VJ{7nUF*o`=j)AG#aL9y^Bs0jF73bf zat#U046|Nu+QPiUPkWxD65HErwe9%E+zh`C#obp&*H3w^i}G*H)U9iP6>OxNUUlO? zkLX>lhFNwE8Ax%1Z11!U^Iq4WZH6Sa610s(-zd0aG`QI3Y{L3>jAON)#hC=7p>M~{ zFxE|H`Jp3lthHy?n6Vkhha=t;qcCTy*pj`e_1Vm%`$)V^98O${*-q6eR9AqO%d^)0 zd9Q%w>8cHH*Jj5&Xz^Q=pY6j>nZLX{3s=}whRmW0VCXdAEI}cmwLRa&10#iDB>Y^8 zMLvy#Em9j)&!~0x^X@T8jPEc6=Tzr?+}bc9`#g)f-felZ*?nT4?!K>%#eCLjFUaoE zViPN=sbbcznQ~I?MM!SZ?@1||a8>{+L$J+#bI2q?x5T0DPxK6Be><dKvDdw=+$vay z3HPwZqjo)R8{u;NPVfrFz#uTbao{qt3_Cx2vaS=t)}>}2+N986VD{nH$@>p7>8?R6 zo6IpW%KJm63>}s%a<Pc#%lQw+(nKKG1SQqv0Jj4N)}k!<DTv0_O*$1s);d^#sRIHh z&e&^JM&t>xXZtva{aRTp^u#f`&P8U8##?AsaYVw^yc?kYi4{bb&dNB9zC0eR0gna_ zNJbH5<!YU8sHk4A4U;i2zq~r6RkddfkHs@&rC%uTWv>n=I>D%c0gR*z2B>qG*m@s= zL#9^r(zZ(R&=m&~iM5}Ftn{~z-!j>yk}V*_>nB2sV+hPxXe;aGWc71%4YWeAr^FV8 z#mV`|%(p9ogybRVA%YM2t=0!WB-VMYByNmc-aJgv3ZZPKVeNRlR7j*xcf}qa70p?s zlOf7NSSPZ-EwQG5VZSl;%fV1?kEo+6lFRSo4hEFtiLD1bL0CBr%RzLmWR489+AFS9 zO6%?_)_5~@t2R39m=aP#AGP!{|BBzqzHC7HlgvqgLkTzR;U4_WhC4=79vum|gHPw| z<U<mgAH>fG?s;V@3@e}PdKcfgwkx{)SXgbBJJQyaX5P3a<9G?W{N$Zu4}l_yVPq-b zqUsc?{my~?4m1-n<Nr2dR$W-+D1JfXZa4x1MtyaCRA$Ht(NWDj>_L1RY-}Mn2@kW9 zLq%6dx4(@5l`efa^hfA@^ndd}0c?zRK@KlsPnv)!TPD8H4z9{<G7K-CsO;sAe}Z&R ztXi)Ex%tRvvSAV3|4)Q5WtZepIczF2V!Eqq?*eW>-CxfQ8m6=#dW>7WN=An&iSm|# z8Ka7?Ea1_=5#%)`)zgloh@6$tD-?Z6Jo~+6%qtP)^WWCLmUIL8X$#ag>XVVF)X2Ar zp#%~$^lF9RW?%fJJ;zdSmm(~7x@Ob7cu~Pg_j4Hd?xYe$Lj?yh??5?TGu#0=TCjpw z-IkD8g^EKL<>ew0VCXMbQBiL7ZlL-@m{-;wBe5f9PRopy4!10#462VPSG9My!);3^ zZt_FkB}(?e#16kas6Doh>Xv&&Q<f_INvygyw%jy&*Z<_37ayja7Nyl}U?QF8y!uN6 zD*WnOOI}np&%Aouq2m5-xWXbenRxtFF1@}x(LkPW?i)RP@j?aE5W%r+Q|7jPX&C0- zL)kxmqD$#jWhyeye2Z$z>!AX26wf?3XIT3{3gM|al@I~JX`Kr9{DX#M*lYM@)_(6K z`-BnAI8I#cIesho;sNvDL^oRgU0HJl0Zk{bcKe2T+I*>Tb6AgErrYM~(Pwj(m63;r z%7?|yQ6rY@H_!anN@Jg;-a!`1Y2U=0ZIo;7)dIsvrkMeCNN=}BKdD}-Gl?|_erC#T z&<uY*Z_VD42aly?uO~UV?gtggm&;M2>JiG9Wo`BC-qIDfO-?yK{=QAWCFYL9t$$;& zS<#Ngn=<`UxVtiJ98>!Et**zI+N}6BKBI{hWt0ZgOps=&^e&^M&;;XO8(j?vtCnW} z)WdR;n?)RrDNn|jN$>%S#k`43H87Z`#U|J%Z%2yq<oM?5<CF!&<PM+PvwXO|thl*- za4Hu){B;R_cz2!F^5t`HDr}x*Ng4*qS)e2KP>kN7ZcKXChq3vZ)VZEzoWXF6L2AcU ztORXBFQHV~RsTaSceg3P%ieqU*jy5Zz)$loT&`i!X@&@dxTE>9SFA|9mMStwPt$~= z#GX|%(ZGSJJ;LK+;hvi(oBBk>m1grq341-nul(pw0==k|0zqmQCbeykyMb-rpe9k) z8ADRJT0ToddXk&WqOg=w-or{lXz-uO{2p9pk9NWc%Ylfe1I>wT`RL!zg@tZ;2#s{Q zb}ZsU?$u}-c*s30p%|bT)Ms;~W~pGs)k?VW19*g1qsNfq9j1MP6gI$WiSZq<EsCr$ zfhUg2{DE8$rQT_U^t{>J)zp5g(SRf(eQ5<4z-lU3)=fvzY&Ea?yGUq`<fK~0XKzhp zXTtJ%2mFUNnn76Xbq^Cp4?$n&MQS&14Z!=C&kS;*!XswYP#n=gqWKxX62xJ^ra{<k zUCY>Bc}2gdK})YDs0PFU&j@&)V$m)lbr*&9B@+*uF4;8-cV{3r;Dh};lyiY8)iQir z@@WCX8D0Q*de$@hHUx%Q$|JZ>hw5KPHBf^6`6RyKk<g5!G|tOGdX-L~Ge1@Ux~;^u zG>%x*F4m=g3yZ<CR#r<D@@p6}SY;ZZxGU9=kW{?Fx8mj0nq!gSRoa90&2Y218WoiJ zz53kTD<vL$ooTT3C70^0qYZ>gst>nZ1fPiRttk+tJkk~zT6=5va&}MdjPI>cBIayH z+eH=`d1tglZpGRG2a`VcAj2`Z=EMe8U=rm(KL&c)E7iy>J3eU+Tv`U#5v(_bKaXPz z0SYLQNk0m$c||vH=HuYB#G@C?!9Y|#`UYcE+?Djy3*2y+Pr-Kx%W9uZ$V@l71?B`Y z#}jBqxpBY>3Jhu`%q2?+5&oPbh5p+$LW_2jVLV*;llk>}o7|eH%KhD+In9q6HFlQk z7};0EEuRrY;4{!f;%8JN-e`}>8toq4bI@x~j148tIqZ~qF;}pcOC?+i><r7=zq0jv zxo6^903?+hSoprq5$Alqp5%1jik|VkHV6Shyk9jBY!8-fOJsL`^H0y%4}M?nZy#Ip z$Vl>jUNQqfeD9v_=QGv2yxZ8p1Ydo=z!tm4^{j}I;5BEZ98xs?kHvEbZ#LWMMJgu1 zMpUqBIq@Olm<YF0Vd*9k;q|c|jq91uaA#ZxriC2z9n``x^c|)Cc^RJTn3m_A1mWxB z;bi>O<D_Q_vJj9El-!#dvODV(IA8>8;RsKWd~8Uya*<;B$s|9Ayvii>NYi6H<-Nw} zHJ^>U(qLgW06Apc>OUFk^jwb^)_pr*2w_K$$+>P_-PDEXmhW|cB8bg<>B^aDJYgQW z(j{5DV&8vm-3nB>ty#6dyY5T`W&=be)+-HmFTEwP6Z+0{sXqVY$vSka+rMTv=acN) zUjqK@?4;BSZO_2XBQ!Jb{&Yq*YiKXIK$aQ4cF&YJOLPd{t;GQNY48HmMI5`u2S`tw zEo_q4;A6}eY5X>lGF|;Yw$T$R)~oNHa2!%?H}Jl?Euj&hMG1ACCJf-os;RuF3NMrN z&;{UYtTjad_RM*!Mb|h4^B#DJYEVdw_ZKd1=PJ62IMj7RYz1(UI1+0({0u)3gr&yH zqo<s&_ARaIskQbi25j+Cx!YDCl*pYH-5N1nm<Ma;Y>bQ-4}Q!(FxLSpW<BVk{$|Nh z7%=HzXKgpnM5y|nNpD`9m4rtv_N6!k4+iRF67I~Ut9zcIDm}W^47gKNDjpcswwjL; z4Qw`dp6!e?%0@omH_f0@)dTY!bHDeu!Js%v1~yy$4}<PbWxwA;tF5Y1`XgC1KgR2~ zp`3CCA&yXMRtWdHRbwQ?>|f->cGvK<I5>PKiI1X;Fc+$m<+SC#QJrx~FA*e4s^3+# zKQg@+)WakX{0m*u=2z~nXS{xH>IN<V5|8?@f_L1cAZFQcINti5_S?c-7k+&I@M<By z<Z>ZDw2hJ;c#Yf`{;e;{=B1U9ik?r)dP|3*hX88!Hj~{Ky1>5B8l0)E$$uMk0$=^J z_WbAP`R^yt(UX;jgNONFi+^Rd|7-pEUuK`;?#`0R&OoD25`O-F6~HehLuO!sgh^DG zgoT93*bsOH+J6Fn@t-S`gq^MP|7s0jU}j(@;rt)_P+%kA_kVZB`hPnkVN&t1Hzi?G zFf=nIp&()Tug(<=9Zi9s#qvMzWs);Bu`m>|b0^UTRxy)sFtd}ea<h=={#R>JV86iT zP9*=_OaEh4D(PtFV*kJH<v)G=SMC1{Mj6<%qoJ*n{lC79J^rU!n#9@B#q@tlqQF*S zrmhyorb?0`|0@4`s7j_zb}o*_rcNaPrcLR8jf@Le{{J|ra{u4k`u}rK{Wr1yv07yz zVP$4x|JTcZSFn<>uyJtw?;17|4t9?Jm+9(7hp9@&Tf0C+hu6&Z<>h6_?w~+xD9GSO zL`UN8B?eu!ctl4B7R{xrrdLiw`=h|o*TJTp+qy{<xs%{$=iO7xzG&&F>U`SZB%xdY zYYdVBz!i%V)W5!|tE?h2y`Za}?8^(lky}K!9epI6U%XfgwFdgd1x;?rKr%A8IwQQ@ zqe~(D9sL@g)D+A&a=O+L@>hoz7zhD~>rYTuMo>my5NLe-D?dKoKnM^l5=mupOKC|e z<ljw2m>MA0Pm&;6#jBE@5)#Ei2z)|9LcQ~QJq#c;xsgpp;Qog~Xq|Po-}xk|ymG-c zP)J@R)>bq#K<O{|Gb?pKC=U<6-}N|}r!9lpfU+*SF8=%(V++D7{rWX=yGYG<w+7FJ z#_=8N7zCm#`o5;OM~!k1rXJ$c3X4+@=_g1QCeAr|FHpY$Q2#vsXV<827X+fA`=Bt{ zl{v+^@v8zKo4l|mu&7e_dqc~PfW}u!)*3H&JD>Z99TvP5^j!}e$b@c|1_xnfmTthU z($^z2HxDl;z3jP;KS&K1-7Ikf1q#A8V9#Lh$OIZB3$#}rpjPSkkh`-3@t$&{-xwa$ z7Q3{?<6X(%Z)Yc^$4F`W9Rz0|?*8VrWJd@UjgPN)eH8(L8B$A&kK|+YQv#gfGdfAO zm*fnn$ibQ1QUtdA>G}CFx-AEL7=z?W<hPzAcOC$uCXH_Od#~qybZFvnn3{Cw8FqVc z;_m>o!Qr+sbZtXd^w3lv<n>FenE%&Bz@Ks>qYwRy53-`ppb#?uuPx=ys;eGK(AxG7 z?G2Fjo_RUs=c)I~u^0m@w(Si2&*Tz8e6F<&)~(IuFZGqrun)VNPocRp{WkKiv3tqV zuL4nAb-oV2i}=eeN3hP5(LbQqlr+6wz540(Y@i=gB<NmNe6e53%U||iFz-*AA3{Y5 z&>5X_WS0gOPg``*wOSn`8h&8u6&gX4m7g-rU!3N=so=t{i%8!wC9%(XF3CUuuAI$Z z9f|{Es}qZ$$Gf-1=YA{xNQYmV$*QY;6Eo|peQ3RXli<vt0kZtRmp36s`z8^uji5UT z$+t`VvLHd|B7?}D86dXz;T}Odvvdo4AbJO(3|v@2K?%?Ov9^0;zW^&=ksnX09~p-r zwdt+?0VGz~YeM8l88sVgm!Fiapp|NN>KMn@VY?o89`H`=U!pf)8oKAQI+dTy-XLo7 zBqKM-eaHqb&LE%BTduuuu3yG}$`EwRa1ifd!`eYuG1a+3f3%&j7Hz+--OnJNiA8TZ zO`G1V2K~_OJ|e$_?Lg7|$Tqpm(u9r~I^MT_T}>9>LU#>Xd_+HQIktbgsOnA-2>Z3~ z_-O}@65lt2%n2RacsBH)zO4xaV?HB4FBN|I+hu8df;)EU2Kx23oGt>(sy1JsTVtyq z;N1&NU*IcS#g5O=-c|!Q#Mf1bCBR1Qx&JPVz?O8NU*O$MJFm#ki=k`8BR6Uzd-~Tx z_qK;{o(UAs`dqaw1J_&2{jV3(paD7l0I4V85|pxGuRke+G!A!xu@NYZTdIr>WCl5O zzuHR=EeL<trmGDvIyXndo~d?sleFg?ZzvGDY@y!c8dgl8^s)N)f{}5YO4?H~udB^n zSugVzgJ5(cv@#ek!6?D*?`7tQGWaSQCMFL~9rgrKV+Qh5LbJ)yKCE;f8pRm0`)ra} z^U!uTYCloi@BF^RZaT_SsTXJGsmbMHc916@OJ6YOIE6+}f1qGY%7N{Gdtn|D6SlQ` zk^BRdi&b1^i0Il>eL;{2L?~15I9$dD#PPo@fRfp|s8?@(6)_oSqo}!V#K}C4-lSPs z@mf)O)*zzHEa#3Y_#2o!F<NJp<ttEdVuv{n=PUC*x=T~N^uwgXnO*UY{WObupoz$Y zu?^K+I%7NT6VVS-15feK3y#Gp={F%!!ODoI67Ri!lI`^YPrLVCZyFw-L`<|xLcsb( z9GZq&;}9Q4ecyM4o5xVQ)M>8P&Xr(Rr38KlG*_w^`@Oec;uSuPaM_Rnlix4Vh{h&> z%jz#HAAVM9A)&_CDKBenW4Urfr>W7NuN@!3A8)Kq$_CKNvsw=e<d}B}rn&ub0oplT zgHFg0i`gy|W7ac7lXoIj)AQU=KY9OiC{>?omZGyJ200&0Cp4PZoBaiKMiLtO-1MdF zb%lEv?}cY;TaZZ9)UMKINa!+j)(x4+r=a%?1oWC30<vzflXf&6d`Z>d;DrR>rWi`w zb@gG>>>n0chv&P7vi#=<I{R24Xk|@Pg_%-jZ3FUeHy_6^^loNq`NY5cfhUzc4w=od z;ByRqh0%?)oE?ExgD&qpJqK8;%lOznnk^*zP#<%(4N)u=?*><>=a@+{=r)(s4VLCx z$cIq0AF>+~4woIQPOhwP4x9S<sP20|W!m@9=F@qyWX_k${356C3>~M*u9{}#=v8W# zhz!ZTHRDlnoGc-IzdANsNNa;-S635XxYQV6J<nZI>sybDrYqRSq=86AZ3nzTlxb7y zSQ+)G-#TN%KXh)CBv3bWvV9bzk+ClQ$@&Z4#DZ`49H#Bf-`O7@(<k_ly-B1cZ9T+D zsRlX0p?_h+s#oo$`B%%3a=L^N?X9>8;7IYy7dnmt{_8L?7Ggk)(vyEV3*oBSXKbq5 zXr~H`_sXpQNIfd7oqJ|3x`q%Ljph59cSp$uEHk$eiAoi@x~SpL(U@EGdiDWQb4@z5 zFd|3jo6U&f!%GBVI`~Y15dPGSRGbsvD<{;q+QSb*M~xp4?N^S;;f3ifn2HRt&QlaS zPm*t>MxLyhIEQqu=BGysY*^9v{8BX($a{4I!&9q&Oz#q)y8-Y}qM9|cQ_YH+!uQS7 z*F}ahMen5b-eO^Ur`~fjEGThXJe_l-@mB`=@{<ROLcal$ne-czd5|jOo)}M|maKKo z`qy4Jg$+aVRQE7{^NXJU%&F`T4T!ZiZhlL=w3(1;T~^mw`g7J9#e1v?$ba|mX}vvG zTe)`s)2$ni4GWtCuXL;0E=1Vjj@^B9;NbII1z#08SE~HP_mV4wIdc5dWRB*$65|}+ zH?O(fJ-tR={HvkQ<wIwN;hz-uZY|PKsk)wNNUsE|RZXO)Vep6TeQuCtJE_$?-E_kc z0(A&Yf38g%Z`YtnTgH>N@<zHx&0U_<=rbJe858W`QAvHa+7<X*mG1Z#0i9o#?t*i} zc}Sx$$df$a^!`7al3@n96m^ISC2u>ENzy{822GkddZK?e7t@=pU7lVJh(LB5sk=}8 z2=%_#YkOd+Fd+KqHnw<w_zoMEr!2!#2N9j;QzcF`A>OpP{6ho#bz|<rSW_OZAF(>* zk3yI6;vGOgV)~;){<n&Fe@vcD6(QQVGm0ug_PXKrTmtS#VjhS#&M@Ji&LIltIAi<( z7V!^EoKaw^VM(8joSKf&qh*d<W@|`C5Mg*2Fhg|X$c9h-!+^DYoDiEQL==j?Hp_kw zh2z4Q&i-ze|A0xT{9O12!bp*Un2}AAM6i)>uOf$sjc4kqYwy{eMrRoN!^i#HOe`in z)1(XY(nRL3*Uw<RfWaE##QnIoK(-8NJ<3Wsb%rO68T03g3>l`o5a;F_ndmqL%U_!G zve+6pWgjEw+d1C2amtW=(mC>zMYjDRQm56hdW;rHXM%INsz?Vc**}i4Z*oa}SsXq} zD^&Od0DOamF5eTCS3#1se+#UW_R>v=JT^<8gIIr6w%1*Q)WRnE@Su3UyR-CkN~L7Y zS5|>!+*XmGS2Ht<A7mva&FS6fT%a4&Ibd=OIEdAby<`IxJW4~1IjEpVfR0s%%qWBJ z@EHt7{Kgh$Yv1CDj;da@IP?@T-CbwAI;gUFE5E29AiZT3#jXn4R}_rqzQ-O0^<^(m z=8JGk@0812gT7<`CR!;xJNZy&xKjAiHK=}qWlrPF)5y`hsR(#@${4KOMS7bhOclKK z?3Z802y|0<l&^9^9-)vc3Fe8rWksua-(BuL)W2a0AL$>(oO?P=^o>a9Yz|MHHPgm} zJvSaKskD(6NE;Gfv>!@IJ)iJC_gBi@gJ(=emD~7KIUN!8$kxe6oiZk^uy762Mer2| zoF_GQyp%teN)KO068=IF9pm<JR7i@hFX5_O$Myi2`EOzHITxd{P)VBcN$#$-Q46K* zqh4R8#O)u&2WpH~(;1eNwo-29X~^rWdc8O=5+FydTt-YC|GZ&Yuw;{fj>6gV)S^az z#J*`G%Ew)A$H3A?P@`LN`Vl_2xI#TqL>AR~3A)*4?L(fnH}|IgBk0^d%JtbhXWV-2 z;1;Lu;5~OYU*f{qYobg~Nj)JBkubB0*Hmv{JGFSBT=fTx(BOumtmuKJivk(%)rYHv zYPx_AyQsM8OPYL;-t9y$f?XFa6>k#@TQ{S7B}ggdtnB1*U#yRkL7(x@jy@P`^A#p~ zk?26fpEiheLV|-)D-E~yq4_x#<<w$=szd}~YtdPZXs=TLr?9U8jw492l`M<NLW`Lh zM=V(uGcz+Yqs7e3U@<c@Gcz-@#po~DyL-EP7xBAeraRwMWmRQW&qVa}d%1>W(x}`% z+aAigG^cU+WQ+gcz$y5yLU|bYfYY@LjbI3+q4^{;X?rkjf^t#2WCU8Nb~nqx5(qw+ z6YZt@14b_N;;>P}uXwJvgByV?669G1<G8%wr{$gT;<|@sDbfC5Y_UY}qk$_Q8QBIC zxmU`P_G?DQ&Dqza#W__GxTh4BT@5{)Vt#{d&a3Y4=$+tV{2e8X_BweKnc(sjBPo!S zJYM<;myqOyqH<D+I2;q<7vCJ{C&v4<ZU?A}nkv`76k3VqFpsy^GZj2TvPlXvNgI<B zDEouI0yqeNi`6eV5OKIldMNJ=IIdX^emN4p*Uk9~0|Q7pcmm_<-Pg>xP^;aO9bo|W zZ=}?WbQIp^W=g;UcD)f%M#5L!ha9z(Gflz>ID#cRy)ADy^aevAO@^R=YT$?%sq64p z4{GAk%_|t0IKGI3F+aBiPz@i7GeawreCgG<f5NA;t|8IGC_`sC!|U%HvYVOyVjg*w zu|Ek!CQz;$Tm`3AGH`g>Z2nWvKwlXaOKpOBWhubnc^5xhCVQpju=m`jy|k6#TF^sT zgkRU}6F~XrYINg!=A5xc=O5m}Z-rcAhkeHzR8s<zk%>!K>8}#sqZu}+iU*E3^r~zu zAr{tHv_8$53wi5$2U4X$YMH!0%#{?CaK-Pvu1>g$LxY>N;V|eb%NiBBeHOK5D?r)h z^|n5-USt&KrRJpjiN6Z9d3&#a&-n2Lt4o^KFXJdnF&cL{zT)OswY*iM37<)SHT!fq zO|~i5M>dYdc%?zI+R!!u>Q&Uq$(9l6i%<j-Ko$ursGPV1US7j-zo8}|AzMrmNQ^XF zjz$kx0=fWpagtbXJ8j-&C5b<;z(;RXcituw6NeGcdS<E8)4kyKH7cvDcVdh?10)q# zzXKBkr-+wkzneQ|-rNY2mv*U3CObw$;<i~5@y$_@%8`BkSs5(d(mfes?&dr_VK{O@ zP!n6AJk*U6%jrFh)L|pe6}V0D>5__-V_g4jd`0A!mzg|_>=8yKFa_VE3;|UBgIrP= z>Zdt7J&Ai^84hvH-GDvBumjUD4^IiC_av5<$Uo)BvF;S@CQNZE1nmk;Ezf#Fl=t0< zoWV|wUg~UcRQ+H^`5aR6EoM0L$e7qt^1>vsVSro&9NG}<5O_F_%3ZInJ^_#~?#-#G zoa}a8r-(%YFhpyhw)d5lit&ESCEhMib9&y?OUqo($WJ`^0CnlS*a}+L=+q#sp@m$7 z*KI7>-%gg{MuKU&_KG_W6y*+@6rv$Jl-c4iA+!rm$i*4ri)1cOkl87%>qSt%Nk#-4 z9>h{e)d$G5^=%q@;;Qs&<-)JrtjoZG9h6i-iE?%o+?Z#5dg^^)wv|X=`e~DTH?rnP z#vNP)Z&4kv7av~$V-hP8MQa~Y(7WSuiS~#=CZ3i)pv64*3(@gQ<t-4bZ08mhS*}i$ z=D-n31OTccHIt(WQ6p4cGY<IkZU9PQ`-X1FLyGq~x~$pTl{r<jRXo$U!IA-ygaknE zd$y?A)c13A<erB8CmrV{y&_&sRWY5=H~d5z_&~XaIQdxr5-ww%v?W@N%HALrq9r#g zRJ~D!G~H~@vw<NNkyyc+TNwwA+QpwO*8zT-Y$(TlnZZMcsEUluBeCE6-@bvZNoEkk z-kbN{?ya-2pn+)XdiGp1#vkO!2&)>62t)KQSk9bix2eWyV$Zx0wZ4QGy2<~ZM?m<x z9NZ|h!*6GRZb#E%89~0|buK^@G?gkkv?vy!GmJ{TN*O^89R)G#5Ehc2&WI!sg0D}F z=0=248-d1t=HaJ=0}4ksYcO<Jiw_Qeh^9$i=5)$FE|DGpB`TaYCwMlv$MdvjUvP6! zr#uqZUwzp7I_P?+7)I<aiq#M|&9PU`?=LE~U>de!h#^-))E(ANS-8q2P!WNfb)KS0 z<%cVIWZA)bMG>59*Qvbp8l=T3eS7%&y5GCQB2VKAiNKx_?y1CHaF8uM?x-NoX=RLr zoeag8ab0_)GRiiJiZouCk%~_GO!|yd9<gP{nzIMj^yR^LXl$^IHa^=`7@DMTfa}Yk zq(}*>oAC^e(m)VxzMZM2#;n%t(}rE~E*j$`4m;Jw{9}q*^EXXaW9eILxk(&qgc^H2 zmW*fE%Q#V`7&z9g=snxiM}qtqmjIm26R?EJ%_;852*g4Q<H28Qha#pT#EI*i55su= zJ9*4puY#cwhFTrSEzoy;X(-vu1+7>p6c`ycoH$Ew$Qw+&ia|7DQguDc-ybxMp4;+t z`Q{9mr-TIVzL<_A*?d7>-emASL6qsOXavVZiw~e6%BxIUitTE@@L8Xp+ufPK2vHdi zM>yKa9#C|hF@xIKiZCKPN$x=vhb$nE-ZhDlj1I+VgE#>ns)8>Bz8yFhe$|kddQ)0k zfo0O3(^mow?tu~*onULZe_V#CKHE*NGNR<D=hEx*+{7ZChJ`nb$MT%}_FeTvi%yN2 z-XVJVG3L#!3+B{62FS(&1l-}sA$T9N^->WIWhE*qJu=Xg217nXOGI<j##7kUnG6ur zj7qZgz#fmxX&hozfzXrvG(;ARHsueHDrc?n*UUMS^E?w!J0Gr9j#l_0rYVhd#xq5; ziG&(b@Pc^hVw#g)N=nWlZj#2FqL=&3*)xy0l`<bfRVrkG93JL|XCHwtyX?&Q>g<^k zE*m?251q&7o~+hjltn?R=`ay0su%&(92h2?Nff#*hSXfuIoxm)(|5DTi=34#P`(cE zcb30dSKzCL;Ktex9m1EoaGJGMh8^<Q_!d!5c!PbTd4JFFo;(FS0jOzL_HB61$GatA zJNIYjXVc$1f=mp96@W8f4g#DgP*;mgqX1Q>U@Z>{-E(N)Ku8p!h%fDiGAG4p{(@mF zLH1o5hWw_R&m{ea8%4k6YdRQDWJKI~jpn?Xh|#6IUb0`rE_acK!mJ4Rn^?4;2ve{S zdWRB)^F4>ky@mb1%3qO(yi!3x@93H9fHo(qi_`JbK|jS3!3QwlYc%X1R1it$eg$m# z?6q8QsK`+3JN`;rjtXJPFKJQ-zqXnaLPav!kH7H{MGDf^HeO2Z^nkk!pDMaG5onuO zRY_P=zJ#tL8}%>$_7Iwa?kOWLM6{xlZj`}3otzp$S{gkTp<puvz9Kn;F;55q%D8I= zXPT%NaFo|(c=9VA*zjuzuwnRhh$Biby7K*o!tk~NS#T?(g~>r<iUI$L?Q=nyQkVYC z=f;$i2&!of)_aVcjI=zvf=mbJ$ZF-yCZ{D96A`ntAHbi-{J~7&IJ2^&>eE;Szp_3S z>RzwA<;7k=VTQXtnq@^6Pr=TF+3WCXYV&n-wdR*5wiA@1S8GdX6J$nLZ5mf;Z--SM zS<~$(RQ_OO4Iz~!L1jb76|M|{h|(j}LK0F%+?C^rH|HGCZe<g~kB>{?R@nEJu0_XY z7(}+ZIFy9*p7puZf;7RFGynE2!+hg(6HS3*^b#(7I1}$025M5(cH7bn3W8o#e4mGj z%X}##V|BV<O@XY(804!W=4?(G;O82i-8ghuMP%iVQ6NAj7a;Ef>;QAG#tubKrgI{z zo>AO`8G){WZ4Ic??NO>mf_=>^cB<PwCG4bOcG*<x#l0BQ5)M8dL5xwHZwSAy(g+x# z2QO@P&wrNu{efZ?Z@+ViZPu;s?&V*E)0q;@lM@L}#Ep&Gv7!7ro-B$CM@%X`cBg4z zkCCESh1=FU(*_{1XYhAhBer`Z3vx&&Xbb&OJv_z1ep0PQbmXAIardDn&tJ}HHCF3^ z97?U%zKuH|{Eisp#qgg*Za}v4S<Q0&!Iwk0(o(CSa8g~P4K@Fk(8pC5{8`F}Ke|uj z9?NKN8*44S8XWX))4Ki<6%Ol3i=u>D!xr3Id@f@W@Oa;0dJBWV*kZq90*EaSVh}+^ z)Zk&-y=#1hIR1|NC1(t%e>RyewS2x9(?|{vrX@NT;$SZb+rncbXEx0G=~J4a$+iQv zBWXcM-I2uaZZrBDHr!|K@4xs*u9cC`baOYY--U$xtoHEAGh8edoF!G#kfVrv0(JDq z7l@=LY>#(rY#WW#i6lu#HGZnbb^=Qv_Vj5eZ&jI!ZJ`SSlj{Gr-L(dIoH~z(DiRhj zS9(wke*ew4R57zM*w;6YPNA8i<TRUjSfFm3(2GG#`0F53%$9hzNC_3;0py;&EBLLo z2ui}R4vVkB8B&b=&h00~#bp-9_Zxcg=LDhs@7$gaCGJ$$r>oqxWmTv_GUvi8KaDjt zuBHPYRPq&zdc{jX?kTrC`6gJU1=VGUM55m{1shpww!CklM@0%YvXVwd#xO=vEKf-u zpPseuiS2j5G0~siSXt=^kq6}=RiD6q%1;=rN|F{5U*BAVkARk#BoXBouAnM$ldSo> zL#qsG2#n~3qcu-=)KkQdAt5hYfqO~Z>{6NzYbtV&hIWU8?2eSj^t(eLXM}EZhU+8o zNu6etH}C`bhp&qC7kn2i{V9I`38Hy<uhJW*!F>bgdsVMk(j6KvPwwy}J#PekwMI!q z3drd~G!YL`=wd`*@vG9N@r06C{<uyhBNC5Rj`OZUP)2aM8v~7&bavI<&aWx5%YztT zC4}Ia!eAv3no=a~gwHFFSE)l8LD+d<!;_lJK=HHQB#NFxJH&B@sDWKgYPG}~;4WZX zH_y7bH4Z`?<B$YAsjC{awrk-q{srJ$;ZAb4cFUAx@zlIQyy`ysfJ00JLvcQ6x1W+S z99Q21S}<NYb=AO51bsN$ZBCcDh_}~A7Nx8)mh$_NDR%?XG92S{s|BBXP6c&N?Upc8 z9;9Nq9%Z_`F331RBMfKP0*do2ik{S#%cItMjA0b6quH~(*4I58;}&Ypx*|KVkxS!n zFP7~ucwi2~^I~Zsx#m@Ii17FckRz_7w-Xnj+^3G?-$eRCQi>EDU%W{j%w?h#DK|6? z#hQwLtu|#tQ%U&|mi<2eGzJj57T5Bvsw!f+CFFGjT*eO3puy7Zl8bvx1AME0%Q3Fc z7R0B^XK|o2%xZH;8qFWI<}dSYHn*aB-$z3UCHZ~H)&)1dgw9M^(Cy!Z<4|7n61+0k zT0PQen?I8t55&{2p%`21+#(fgYgdLNL@;r9p=)-b8F5R}rn68X8BP{~MAFgRidd3A zyP&J{5N$@|7-PDzd)tAw#CGV$fa5)YOezAywi=@#fUin2=r=<j`H8Fa+=hBW7N|U1 zzvx4b_#|EQRVjLN0NsPTXLd!=>B`3Sl)^oa&&9V!2?}WttlC%^H>Jtt^&S#q1NF!} zviM0egUgTw2&YoruFP)AcUyvm_pQf&IfpTs=9Vb~^b}?JlG3?|Rs-W#Jh$=vEr9bT zLkFpOOur+_&=&fEV`?HYdtArUn%)!cg`kP1W>wcbDj-WlkxL24Jn8JFcRpbROHV$M z-{QGB#<$^%_;7Bq=<{BDrxm(Vlabtfvdr3Yrf+h7RLl^GZC}Tl*bjRRK!_VWh!Rcy zb?bIo_O|Xa;-J3;)Ml8$kC270m5#`>=mc@7L9+Zu#TA>EL&s*{ofwa$6ZOhW>_gGE zpk{tTk)8IK8?wS~HcN3>5zvTvN7o3AMo)6OTV8b2W}uJqWQ~Ab&s)h@(*SRiV>Yy( zt>zzG$$4Cw&pm55$Q1VO_8vo5x1vQdwz?e^bBho|)jI{+W%$duTtH6KD0e+FJ(h6D z#}+LERoG^1(VrVmcwDINWn^ww@)%tW)S|s5mg*D@d5(ol^A#ZOD<0mR?iU42T#3c| z`Uv7O*bgMCwy7a`4jsI_waG5i_D-{f0M8(-T=Wyv4$2xx2ffy`;zkV4=M%GmrH&so zuvOpUEZ<_^#pz10P+KAvgUfo|N%!;r>JJ$s75>`DjQ7|Av`id1uzUBJ=&f&RV^06P zdRGpMMO}vVvvNc~_ZTh)B~PW0s^^|w)j;g<dS+3rvos-R<}#ZlBq@*Ne8tokLy(>? zXVvn${BdKnn+JU`Uw*KFwyYVtFKtZ@AUu}a&Ubt|pdco}Sf0d5uuBpEVA~Rr_D{G8 z$CfBe8hU6@$Oye~7B|cDMX%V15+L=Ny<SZ^k>r^(b8GYtrOq&YTaJ8gML1rg-<dbK zN;Z0#YlPF(T<s&vn)5;|XBt1Sgx4q*&7P%mN52X%JjYDTf(M4>tLz)K(yBSiX0S1I zM@|3*zZu3+j$g;QdzHxjx^VspSRChYc4ASB6^xClrDK~aR3bgn0jZ*=q)(WNxk{4< z0zRI%dSP%uwSmrUFpsr~Q+kU`9qx%GfX4qT4VmNQj?LOZwlJbuhx~=es=97ptl8d6 zieToqTdf-p<S?^tu*sWKY8$o_-X9z!3}F;XfnA#%9TZ1fqSw#7S)U7hE?Q~uTcVx6 zrXqvrfXWVNG`mdl&Stfz{)%%EnV%?vc*zDHTA#G{132W8s+@3JH`ncX_UsPn(oj@= zd!R0oA56?^A@z$AU2aUxu4&jK_Gyfr`X1*e!!f>SST|KxbNQOP=dde}d9eq*Zm2bS zIGfuV4{?KEmLKLkq=^k;AeXqewxaYXh7PSkj5<7L6!qIE0V25Da$<FetW@Q91nn<* z=(z@yX!`oOPyG=%K)R<{z|&=kzM-!I$F~FExOS#uML_#BoRR)Y)H>p?3R?vHJ(OP& z!waa38Kmd+EUri~(!cqmNv`E{Icfc_B}WATmSK}x^#f)q@Jd>d`-NK-DSyGiEXWgV ze(wEqbLfd;VpH3Ap;2vC#aP4NePx`fhHOnX1!MRiCC(0VE9^blG#asyQu^nIFAt#) zI<AaL_W9gMeih;HoFl9t#7$MT{1XJ}sl7=>hHLi1d-ZOM&HF*oz%VVNYrNn*<i%1A zG8d=Vs;amJQ&2s<?rQM{EEv5${T3i}_)Mm&aAe{kQ?%^GYu};WLfGmQdNB~;A{f(@ z&WQ;*7M6b+VY*P<by!%C@gWCx&DEisz!Bfj*+%E^QM-Z$MYCVWjfVafCG?i795--# zlg8!YO!oy7>>k(EjPOh@gugg_=0*EmdHZQ0%K~JEMBwFI;0a=Rj<piB=1>_U?9zc7 z<xz*hb){DKvn{vjh%dtaioi8moYi21`lF)7pdIh7(b{>d(}fHrwxHG2);!h?^OZ7x z!|8aEw%rpdAv9XVSbnTBfCH6d=}h^xtBEG&<pNB57=0{qsg>}1RTo((0T|HgG>R^o zvVhhq$|FZ08Y^J(G9uklH7ImvcTKk)XUr5x)5|30XwTb^KXA~-okGGrC0u}`Iz|m9 z7n7r`OHT4`RT^>fI291o!xc6L=PO|u->2Sv%4B8^Lpw|)=vop>DuL5GbK<&=6r&@S zIZ)}_WQaJi?w5Q5<<YM^Y%l7nV}c-%7>6V;8CwZ55inp=cXbDQ*tI#JpoL3hF6)vi z0-ILchAMfTY)mGdm=70?d8yNVcPY&2bWit9VI;#X@z`DiJ0e4~OFs-VQ_*JKfZ5vG zdyS8xvHJD42RKou*|rU-p0y-)RGITMB|_l*_PDoT!EubR&`Ot)(z-SQWod1RdBV7F zf<k~4Yg?a5LcjctkgC=DXfm=m#l`4pr_4)dA@O!<A;sG=x$i}F^%ZA2_h(Ed3&%wR zMIniwi<6@GCi>nZZ6hLGi(Lf-3oQbwA)QSSMx~Ib*Lh~UwMHH7GPYUTEf+(PkfOmD zr8q)>NaJ|_FNbf68F_PeZnUqmwikZ!RdGS=x&ue`FK6roi$6$sb6BNI$ZPoSY)aj< zW~7b^WBRlb&%_sqh#xRav7GZ3RYy)$+xYNW@PF)rR1+c|L~9d*B7IKZoudMS%m+9L z8Gh|k@op>ovHEmaDyJl?(kgY|PWy}lp_TFdEAj7O>n5cy#DUG(%?3hHaA#`+@m9*z znbz`zUo&zEsI^nie{4k$Ja3Md8*MeTIIq^e>38FXHDu<IwJ5=4wRKwLM<io&aMXD_ z4(!@HI<CZWwz5?ESL*XnBeUHFqNV4=(ft;TwYcCKfedul1#}kNKsI=EeoO2gO&Kf? z4!%@(j5lnUF9p;wpO!Fg11`iehA(FcV8_WF*`05ExT9muuQ>V}Y|t_E^sAHT6#D>L zH?*_0+u#r#R(hB{Gm3RM$m8yzvswH~F;CTb)_BOI)iUV}`Iab(8BtO)P(dt+xtV4K z3qRwwK_!AoGG+si^bYK>w>;(;cW8rEUd}xp`%Ks^1@Zj!=hNNzfQocX==>@P`79_S z6Ar@RszB*+hg&(70Z#R|($AOYqQMLCBXQuupLlp=4ch}`)w+g1&vF@iZ8AqGlH<bW zeue#!GLI9EN7fd?<c1mw&EN)}$17h7Apnj=O!*jEP;6E-Z)~Ns`DU5N)jDOH@G=b| zm?uFuqgI+%%kMk(AQQ8xS!U}Z#iASz%3G>qkeDwb&TelPn*S?l==~;%W@#Vb;`9l0 z3ycu_GJJSu<<6S(jkK6!O{VP@hT;dk|2$eSe4wXJe)y5bS~ABpQhCy$6?AllvbQsl z55CSEX#mVi9g{=wURTDX2zQb$CK$4VNVAxuxDPbt*5@ylJ}fb@A)7mUw?p#xCYVj9 z!wq^isD_HXhBerP>Ik#JGz~>w9vVR@p(4@nxDge8+i=b1$4+rdT#cp-g3RH^VI%K} z5lTK^4ii)sI*R$@|KLMdRIqXqZqyvMd&|!hKZ_=(IP4C8G8I)tON7VZ-w7WhgGW+P zL@e|rU=et$m-g(|vS;PZs&Y;ZXgkxS)Pvj(-Bt5D?n=RW+s_kzJT{h?#eKxqaUHG= zCFc=4Zc|LOqv~U<rmJISEE##Eln5g?A?8`Nx^hr{yBmc1G1*h5uMO{L&M!h!tDo+c zJI&FiTD$Lvy6%<`1D%?1-ny>_3PLPxXW3w0a=_<JwCJJLm(aQnn+)U~I*u=GCd^3` zq(5Td;*>}fe&m<`4WO8im!jU{G%LkVr7QLuNaG61FsGIjlSbXM|2|PIu)!AvzM?me z;A+AdE^VINjA*IM+@{`0WsIhsP2FD3jw_+1H_1EFddX21GC~w`hrGkJl|e6c<f1?Z zLD$QZf)FF8iII?5v(c=56o5MI<ddmK4(Sry`h#jaJVTmbA@8X@HS(do87+WlC^~^p z-%z3apo#YhCPJ7ZAcJ^7dnG%co_f~^DR}-=s_j)msmhY3B~0|!GM->y07BWzd&<A? z&Svwo6XrC9A`2ccm0l?TRLr6zZVKOv1S!)10J7t;$=dhOwBNn7mJwA6c*lIB*`~A& zc2DVk1e}2ezH6UpFcnd&7<pxML&b9>y@^olF~uuRsE@WK6C<d*1B*n^Rt(DEM?6gT z&p=&5s=Xo-*K~eT-D1=QN|d2fD~~!#>wJj)K5nH_%o)h@Z$+BM@Ao0DPEF|rIFibl z<@c?z5(XGW;y;a%+G=^XOIGvj?*>A6qu|;)Y)Ru%0ZewZx@u1}08esfZB;ahTQJ|X zgF3;9*|dh8aP3JztARKQN0CEl2SIz}jj$5#k9s=ln;4v0DTIWlBEW)cpUH>s!)!o7 z`4}#VJ3P8>i)Mp)%nQ;rPHZKa?fWu19g-A%^>U$Z-#~L%j+*ipF;eRkDFfluO?tjy z%KIe3+ITHSD4u@B-WR=bnUmzQIoO-75*`>J#E&u}^-H^2JvAi=5kd8OPd}lRiLY&E z9qO&XR|$LN8FA_{DKYI<L_8>k&(brUH$(ZI`rzKV)FJVg-=6Lj<(^~w#R;Cv3teZ` zH(0dpdVZN2wFA*$ZcX{-g)>ktBB_#kwXhs_CgQvtZgMI<Lii42@#TZNP%zS%&4Pi0 z>>%~cq&g~5XBrN;&O6!DDD)x2I?p(aXA*VtlKR>XfLS5nP``G<@WrE|e^f2ML$tAU zKe+;r_{N33jiyy_QKFL*7V9zQP*BF^+8OAFH4};2=K62pwuzV)eT$Oc&J$%60Wv9l z#kT#A+?r$I#?rDY%G_7aRFJ#$OM(r`iB(+^>%tRUR`n+H40!Q!TgE(Gfz_X!leB`E z5+3%L<$Jvhlug@>I5C2~EC_#n6HH^PY06$EB6jWQOd&U!Kh}l)X_<~o4~x2X%Xkyo zD2wJbcqam9;PJI~R8b3wT+R1Q0?!1(?toG?_P{<tMEacbR>wZdw8h(B`_hD7Is6qz zkXjvxfMD$;4>>{$6uD5f_>{@+?j}|E;dy~X&=&)yl}c-=)3|9{%dE>r6+u}q0uk*n zuEJeKveP1V!)^MNQ8=)4%KKP>v%mpjFDH4L_52niY2tRp81WJRzQ>mJbh(SD_->^t zQF0_o6|^$ljs<sjgT5Dxz6$(PAOeHlXJwlPV!f!BNX-}TZ8r~vV3BQ42jUe%84btJ z4$R`3qT;}+<nO6j&_?D$v#IgE_yqv2m#y##)`!5#Hljmk2RTZ00-ZdlrAuPyIX=Zr zyajhVJA^=kQC;{`j-+4NELL{}Ua()e)de}^qBjOlMDDc7111z{cH@=q>>ovDzQw~a z)#xB@r-S=TPW(3KUKdpo{4HJEn{RN+w~O(4SwV-ay&6xmz1t>&mjBVj2hWaxRn}y8 z6^pfs)wWdvv;e8%iYP%xqCN;pqF)&fD}1&C3E9gpyc2;~x^ak-)r->GXRNbq88WQ0 zd>cyC9%gN(7+<*MryMiX)5Gv)b7O$p1@jdCBy3J&zQp{`PqbRYlD0f4F-OA_LW<IT z^L$QQLSpS$y>Y}130gtQ9ePB^aEVWR&l>PQom`%+gs8oP&gSZm+Cgl}ar^a8Yc7{+ zBKJF(U_AYP%VNINHjv~x;*^FUnN~d;G|(%=b*K}y7vnKQ6?@+i*AfLS$sxPE!nswK zCyLIlJM&Z0XigFBlfHn{9PhLpdA!y`fV+$`uhWferJWsafG$DVK<^{EJd*2}U<?w( z;xmHo?N1ib74aR?K)P(4kTo-G%$yh)ZqmN^rLPkeYROIKMOR9Yr+gZ-c@R&XCcgR- z4dyu|oWYm>w6B7}ZbS{<GXW-mAwY~_FEE7BA)N3^xdiMq^Gr3g45QQr(bTS-%_=^M zY0kSP7`^!xQi0K(B=Ag_acMM9$9F%`ZS{;HP$yc|3X?4@XM@8x{AiPgG-d`AqzUNo zHzX(LNTy;xL2*?E0OwQ?yVl;>8UhnqL<##orgVo0fDvKPtX+>Zt(K2tCg%Vz;qAFK zR8VPEjK=snxo;e)r5V`lA6RG_=8U}myR{`G9?aNJ1#X<>)H=h<3}jOZYO^+`CF0tX z3KHsCihs{Tw4C`68tD6C45$EZikS7L<_Rb-(7@^+`~D~ex;2_Hyf47%&J%5)+slLs zId6&~HdR9DsB5&FZ*8Y;<_kfZ<vtpZU`ZV}`9udl1#8kDxMo+dY4wA!{>C;Q3O|ji zUM+j4<7+Phj3Sk6N&Ie(BJv%IDHv;CaVtYxioCy+brn~%JNogj3K21bnII-h3<WG7 z5El1#Wk4$o8=*mZv1cN!O?|Ss<qybr0?63IQXA$DyEp{u@Or=yfd<LEBMkM5A>(L& zelRESfZzV~Jtr{-s=Ss3!2LcEPl-~kpx_P&Do|{FSV53CO_>Y&NE9t*h%+<_bKxR+ zn#rr&y~YM1M@*|U;CY2j$X&fWvygqn4uzQ9B5vsFz)t*V+J5_($7&mN)JHrrW7m_c zBxaJKHH#75gGPY<G@ywCvfwR3)2*rZb}nID%8cg;ijpU!J{8e;m%v>_j?kh;1&BC! zd*<f4rb>HMGq!it66afm=g!H@EvP)P;^E?shVgQD?I1nwi?$!QQY^STxs<}ekgkMH zC=nFj{s2m};a;5*Iy#o03C!8-TapbSb23o3XlyJOGQFcz&p@9a#gV0v3@me+u-{jQ zp16Et;3S#V;#lB7bx|U%Pa4Nt6OAk8-CAo$&MpBSGu(ngM!$_Y(AQBzHRjejm-#`~ zoLuh<_j?vgv3NK{>MSDnvNMOv@v-Y`X1vvn0@Q?Gqfs-6={)zvezVST)hz+LTs0{U zLb8J*9T<g6>QTo*vU6k@PH(%AJ7)D-F?k)|Inc;7wEM3dqsJ}Hvb%?@tL9h{ig?bu zW^WeWQszppiHpxKHmoj}<=j&A>ktiTuzAj^8Jp`g#s@;xkzN-ZV<lm<;D^XT1Jq=z z9eI3WVUIyW4WUf2q&JRn`+-zC8~gKt6!t)ob-4)ecP|S*0|Z9b@G(oZP4{SL58@d2 zGWPFy#mTOpfl<x|ZJP#2uhLR=0xdUs=jYivR}b3Fz)4e)wK%?}4g;f>8il8>#Zu54 zonEOGn4-Q0B0oN*pLF!>=hSt*p7tdTXWX6pcRe>BtbjByhZoW%+Ia4vo*yf8jM=AR zoIpHERu7%E<z)zBZ5U1C8Yd+RN}D32`<CT%!J#HlA1k<ozE~ssIa5$WjW){gGZ#I_ zN}r}f?||4wUv^Cm${0ph5!VId94~x59R@Z-xu7X_nwEH&Sa!JBMlso1Wta5*PVe&- z7A?E3>gR)LNl>jjvU*ffYE%sqNP1A5IEOjIPfmmJfV$ur7pD@@3SbYgfJo@NZqBG4 z`7)a6d~*rH+Rsd+ZWXwjO8bWKCdhJ>ZsA=PeoJ7Uc(<%z%?7A;VXC497%gpH-FjXu z!6D>c2_{yi7&chtn0kWM{aF#uYGj&3iCd(HhWsKXx<MRy@HELX-`mN!vNQLf`K729 zE&*eWNUy5hllz(`@p_=KxXIhfeyvFC#+E$N3JL6)cf4UKrF&_SLZu@GrV#eNw3N8( z9d0aI`cA~v*^NN&sU9STyKS48Foku$Kun*xTd8Yiq7>wYyu1=2!hpb+jaad-UUQnZ zYm;EN!^&MmVP4vqtbuu{S6~w)Q%R;l({}d9qcpWOf`G=7nFZR5qO$oP+Z7!+=M-QL zsn=@97u4wdSep9sT^RZe@~SC_5Z`n#&e<-zyW}hC*H5~LHenOeqUiK6c^ijWK{f)B z_B_m)?9QL_e2_HrLx`{(zLevRtNSSn>uSdo9H%oLqO;NL0qYKd2uArCd#Zf`=1a^* zP#DrU9iWcjJ`nZMn~q#0<Hp8@kg=Rar*rY|@{#lcu`_?a?c7K!?)e)u`9WA{JJ#5p z_cMM6e)^d6oP<1kDdSU1LGLEe>Y|_$_sgT^8U{AVgVGkN1sI8A;qrS@61InR`F>p! zkNND(fuCD5X~6?Mmj;Qz(NcuvP5J#bh_nu`DmAr&KB5-n{&8*C&xIZm9kR$rqVpn< zxLk%@Qc!}Qe}Fe(g9pyx-7<XkQP|rw$34aS8c24^T;@O2$AFO2DppLWcwosCmkOtK zi=t4ieKj1PSsk_bg;CIqS4@v&9M<gU^|_#LyI>k4i+?LdFgF4dol1kjxT%@)q9@C6 z*XwSH*y@w|Vz#ABM(ET9OLFFC#>gYUEKm4%d}(;jKn_)Q_b{BtUeo~Xa|#9e$1gq} z`0XMsuKbqV77f1@@C=v-x_z}#kAC{QxN_zay*%WMKjdd03RG>jsER&aKq8FCn>%bR zYQLHz<msmr?j1SmwAg+QcUs|ECySBIXN-(6wYNrSy15ML_BrBRu%*?j>X(7kkMHA? zak^1$hf@DkP{Vw;lKCjm_Npr>q!|dtWlqWYw6U|X!>aY^LiE|nYzPZHzS~fyl@bz6 zfiD-bZzBFuTh7kN#4S0j!`QXgz+Ftg_cM#13Mf<^c<|FP*U6dl6Fte5;}+Iu7PSbJ z7}7wod#(&@W)ZE<kapRF-W<d4i7-D83?bkt2A<L&g+;kb)Ib~MYcsaUv!&z6Ls|4V z&i8b>Mwp#>73g%P^-G)uSo<=^(%rh;0d4_Bz3CJ&r;KiSU8`8;sAiJnizTm~8$ z%*A~dgMHQFzmDwn`eB)&Y6VP=yC8HICoAvy=OwgGGo-w(V6o2fb!dyxge_N(0}V)n zQx8sZRq}s`?ALnrAaj+l+5o|aNfdanL)<VLxql~Y5Cp#tr-Ma&cIg&-uv94+MUAV& z4cGxmvxRYL^hzpL&dyUTF3jv-%f=Cp)BZAh;c22_+R%SDLf0mQYM}ZetRl3aCpfa_ z8*%qcR{>0q*!Q%^V!)+-k^3%RY_M!u+<cMqtWF1Nih)o|*9ye5ng1&=Jd!HfU8+Zl zwafyva1L&l(G1Y&4Zs*77l-#ISh&cbInl4Wz%bOo_cg|}2oEReI3bwiBlK7)yV7$j zHrDwyBl#5n>b>%P*T=<%nzZ)?FBLB)+!;|&&akxcVao}<Y+e2*;?e0c0l#^LZ(^KF z8n=$)?OC3W-FiS-GwOapDB;C24tF6AiZFyQ0z&F;<~4?C)rkMez;58)$>DS<tA5}D zt;@_(MM62m#WW46up)tJh)3(K?2-vI(&H!RP^A{aWHDL_k4eg)N2nVRm<yp*Gv~_< z&z(gZbpL~9pHCNjdC1qV-}UiP*O<gJRvoW1F?$zo@Z`U)_>m$xCz&t&ED0UF@PAt3 zJ?xN+yRNW<VfuB0O$QR7-7<0v_SxqAh-AS+F0d6%PMKajrMxdlOsVOvMJK#o`ye29 zPrmY}mboS*J@pA2$ik_mU{Go}nLUZygJ9fyIu0#_TkZwsrc-p#Cf9GYK^TnjiN)ui z7g#|rw$&TzpD{QjP@S49g1kkG?A!QeE7}K=C{bu_OMfY$-V(u_J0rvzXm>&MSVU)P zPeKd^S?8fA;Rt3iRm1lR$|h!IO7%*(-q7PtvXxqIbJjHnbGVTZ;nUK9CsbE}V9GDb z5pRVOrXLE!Yy#Y3Rb`5lvIsij9t5R5(Km82Ofn%69wW#M{S8HR`a6kLsLBUDNH`ee z7a4K$;4SBNq0o+*BP3;o`7Eatvr~$>ti+O@0xV!CU*c1UIV5zV{3;mey_o?IPJDN4 zZ9lvPvC7naE>_d5Ld<KZ`Gg*cWbc}eMrfv}gkn0a)^Y>i-~~_)ru*oK;~!v_o9-#U zn>te3e~$#JD!@g9=HLGXKAM}BI^k)s#JqvqebvK4_F_pI0PY{(8d$sZro|og_WSei zOkr(9a3)}H>@$gP^}?EXS<s6JHw#*c(NS--`110;|C^rsK^FZ7J(r$|g_Y@_j9IpS z;2#9szjRSN`VT7XU%u=AMJ#=%s{Vud>zt+`$7{Jl_oek3g)=|!8v}VTBpw>XbSS(; zXrqf4e>oN~Gx6lFt`7J>B%*KdzakQ9T6(6MUAbR4dtGMcGHV}l%w1FTgl$#IheC1o zn1t#W*+)H}-6=cXI7^F%`vz7FVz2QfLyz4w+V*=!5-gw2$*FQ)q*YIjouFd&ou{3w zCWP`M793tlje=9l=R7NX#hcbDbUe_<f0oF)|A2UOU$?w(I!(R0uMYw2c?gMkLfWc; z)0za4%6Mp8IPgfg5!1go&7&oR#s0vJImV1Fa!B_*=FqZ+Lzn7BswA%OB)m$pQTv+4 zH-3?{VQ{)QlU-mIglUa4<nq}vcqJ?~0)t)K7Q=d!uZyj4-8P|*iZ23q;NvI;i;97< zoqveG;eFx!HLxYg+XL(n;TS<%=+vty+czMhhJDoZNDBG~R$bH2@HeyvJ+=|ugdGp; z^A*rL$jwPR=n2?su*Zaq+RI+)RByltH>w8=bJDNy!Hdp@o7HYRu~*b5Y&JG+dTtgV zN*|54Wv(9*<P{n!57kzSwQR!+KXf$|<>L=PTwAA&{`YG5GsXW{4onRHS`73b%;<lz zjQ?_*Kgieo26lS3Cf4>=wtq;(ACRPu#XGrLT!>#tSb|d0#6s7>PS(mo(uz%-TGqhG z;cq!}9iw;h^uOwS|4X!{rU$U%QGd{^>FF5h@z@xc{=v5vvDYy-(c`r=GB?1Z`%{b8 zPVa-S{a)mc`O%LL`=jz7fKSI-*uccd_<xGX*&A3W;<5g%{$U9J)A;E1`*JqG`(RT4 zJG1(ON&dgb{KvnXgRcD_7Wqdk{x<nt$Ijrx)&F<!Cbo9=e8xJqc#I5xe2MG)!=`8W z>*+rui}xq?f3G?LOFb)n6H6mJS|t-pUQ0WZe*%9TDVgZo8{7SZvHo$X{&Qz!WW@V; zG1I*>*#RG<^$&}InGTPEh4nA`@yUO^K5BnpfA_!j{+_ciFyH|IAL07gnVCNV_1EWL z<UjGh)<>Ox|McVhuXiRUraxyNM>@QZ_kZ>Ez4ebC{w?`&#`0hN{o5)dE8BmJ<e$F( zu=U?r_f`s)ChvhW!29@4`}Z0C->dpV6~OLKG{sExKVtdOYuSJC{vAF<0{)GBPyg?_ z0@Ait`VM*qws>TEIwrPOc=R;%02(?xGGlvtYddz@cL9TU)W}xH+So+Tj>gK?h@AXS zOMJElI`$@3mi!;$2W0&040H_i^mOzLbnizdI!ZbQQaU>Fe{b}EloS3bX27TOeu-Ea z{c-na2>*~W_#XiTXIle9C^|fPCMddpZFm4?W=3W_L%hEj6M%u?Jt7|)p5;F<1~yju zcL9h0!dU3ur~E&#cjNyk2Vi}V&wrF-VrF4{pN0Rx80qNVm*an8OiXM{|K0982Keu~ zOw3Fy|J~<zjO~3X{YM+`V`KgAJ~IKB=>Dx;dt06NZvk7Vj~_fa6IX+eSbaz%$XZ#w oPx@ckg%4ZA((rw5|E!C@!U#IH_J5-L?vEJ&MNBLpB?$HZ04YL`F#rGn literal 0 HcmV?d00001 diff --git a/lift.py b/examples/lift.py similarity index 100% rename from lift.py rename to examples/lift.py diff --git a/particle.py b/examples/lj_embedded.py similarity index 65% rename from particle.py rename to examples/lj_embedded.py index 8680d2b..160c608 100644 --- a/particle.py +++ b/examples/lj_embedded.py @@ -1,5 +1,5 @@ import pairs -from ir.layouts import Layout_SoA + dt = 0.005 cutoff_radius = 2.5 @@ -13,21 +13,6 @@ mass = psim.add_real_property('mass', 1.0) position = psim.add_vector_property('position') velocity = psim.add_vector_property('velocity') force = psim.add_vector_property('force', vol=True) - -#def lj(i, j): -# sr2 = 1.0 / rsq(i, j) -# sr6 = sr2 * sr2 * sr2 * sigma6 -# force[i] += delta(i, j) * 48.0 * sr6 * (sr6 - 0.5) * sr2 * epsilon - -#def euler(i): -# velocity[i] += dt * force[i] / mass[i] -# position[i] += dt * velocity[i] - -# psim.compute(lj) -# psim.compute(euler) - -#grid = psim.grid_3d(0.0, 4.0, 0.0, 4.0, 0.0, 4.0) -#psim.create_particle_lattice(grid, spacing=[0.82323, 0.82323, 0.82323]) psim.from_file("data/minimd_setup_4x4x4.input", ['mass', 'position', 'velocity']) psim.create_cell_lists(2.8, 2.8) psim.create_neighbor_lists() diff --git a/examples/lj_func.py b/examples/lj_func.py new file mode 100644 index 0000000..5b2a7d4 --- /dev/null +++ b/examples/lj_func.py @@ -0,0 +1,45 @@ +import pairs + + +def delta(i, j): + return position[i] - position[j] + + +def rsq(i, j): + dp = delta(i, j) + return dp.x() * dp.x() + dp.y() * dp.y() + dp.z() * dp.z() + + +def lj(i, j): + sr2 = 1.0 / rsq + sr6 = sr2 * sr2 * sr2 * sigma6 + #f = 48.0 * sr6 * (sr6 - 0.5) * sr2 * epsilon + #force[i] += delta * f + force[i] += delta * 48.0 * sr6 * (sr6 - 0.5) * sr2 * epsilon + + +def euler(i): + velocity[i] += dt * force[i] / mass[i] + position[i] += dt * velocity[i] + + +dt = 0.005 +cutoff_radius = 2.5 +skin = 0.3 +sigma = 1.0 +epsilon = 1.0 +sigma6 = sigma ** 6 + +psim = pairs.simulation("lj_ns") +psim.add_real_property('mass', 1.0) +psim.add_vector_property('position') +psim.add_vector_property('velocity') +psim.add_vector_property('force', vol=True) +psim.from_file("data/minimd_setup_4x4x4.input", ['mass', 'position', 'velocity']) +psim.create_cell_lists(2.8, 2.8) +psim.create_neighbor_lists() +psim.periodic(2.8) +psim.vtk_output("output/test") +psim.compute(psim, lj, cutoff_radius, 'position', {'sigma6': sigma6, 'epsilon': epsilon}) +psim.compute(psim, euler, symbols={'dt': dt}) +psim.generate() diff --git a/examples/lj_ns.cpp b/examples/lj_ns.cpp new file mode 100644 index 0000000..bc536ce --- /dev/null +++ b/examples/lj_ns.cpp @@ -0,0 +1,825 @@ +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +//--- +#include "runtime/pairs.hpp" +#include "runtime/read_from_file.hpp" +#include "runtime/vtk.hpp" + +using namespace pairs; + +int main() { + PairsSim *ps = new PairsSim(); + int particle_capacity = 10000; + int nlocal = 0; + int nghost = 0; + double grid0_d0_min = 0; + double grid0_d0_max = 0; + double grid0_d1_min = 0; + double grid0_d1_max = 0; + double grid0_d2_min = 0; + double grid0_d2_max = 0; + int nstencil = 0; + int ncells = 1; + int ncells_capacity = 100; + int cell_capacity = 20; + int neighborlist_capacity = 32; + int npbc = 0; + int pbc_capacity = 100; + int resize = 0; + double grid_buffer[6]; + int dim_cells[3]; + int *cell_particles = (int *) malloc((sizeof(int) * (ncells_capacity * cell_capacity))); + int *cell_sizes = (int *) malloc((sizeof(int) * ncells_capacity)); + int *stencil = (int *) malloc((sizeof(int) * 27)); + int *particle_cell = (int *) malloc((sizeof(int) * particle_capacity)); + int *neighborlists = (int *) malloc((sizeof(int) * (particle_capacity * neighborlist_capacity))); + int *numneighs = (int *) malloc((sizeof(int) * particle_capacity)); + int *pbc_map = (int *) malloc((sizeof(int) * pbc_capacity)); + int *pbc_mult = (int *) malloc((sizeof(int) * (pbc_capacity * 3))); + double *mass = (double *) malloc((sizeof(double) * (particle_capacity + pbc_capacity))); + ps->addProperty(Property(0, "mass", mass, Prop_Float)); + double *position = (double *) malloc((sizeof(double) * ((particle_capacity + pbc_capacity) * 3))); + ps->addProperty(Property(1, "position", position, Prop_Vector, AoS, (particle_capacity + pbc_capacity), 3)); + double *velocity = (double *) malloc((sizeof(double) * ((particle_capacity + pbc_capacity) * 3))); + ps->addProperty(Property(2, "velocity", velocity, Prop_Vector, AoS, (particle_capacity + pbc_capacity), 3)); + double *force = (double *) malloc((sizeof(double) * ((particle_capacity + pbc_capacity) * 3))); + ps->addProperty(Property(3, "force", force, Prop_Vector, AoS, (particle_capacity + pbc_capacity), 3)); + const int prop_list_0[] = {0, 1, 2}; + nlocal = pairs::read_particle_data(ps, "data/minimd_setup_4x4x4.input", grid_buffer, prop_list_0, 3); + const double a0 = grid_buffer[0]; + grid0_d0_min = a0; + const double a1 = grid_buffer[1]; + grid0_d0_max = a1; + const double a2 = grid_buffer[2]; + grid0_d1_min = a2; + const double a3 = grid_buffer[3]; + grid0_d1_max = a3; + const double a4 = grid_buffer[4]; + grid0_d2_min = a4; + const double a5 = grid_buffer[5]; + grid0_d2_max = a5; + fprintf(stdout, "CellListsStencilBuild\n"); + fflush(stdout); + const double e462 = grid0_d0_max - grid0_d0_min; + const double e463 = e462 / 2.8; + const int e464 = ceil(e463) + 2; + dim_cells[0] = e464; + const double e466 = grid0_d1_max - grid0_d1_min; + const double e467 = e466 / 2.8; + const int e468 = ceil(e467) + 2; + dim_cells[1] = e468; + const int a54 = dim_cells[0]; + const int a56 = dim_cells[1]; + const int e469 = a54 * a56; + const double e470 = grid0_d2_max - grid0_d2_min; + const double e471 = e470 / 2.8; + const int e472 = ceil(e471) + 2; + dim_cells[2] = e472; + const int a58 = dim_cells[2]; + const int e473 = e469 * a58; + ncells = e473; + resize = 1; + while((resize > 0)) { + resize = 0; + const bool e475 = ncells >= ncells_capacity; + if(e475) { + resize = ncells; + } + const bool e476 = resize > 0; + if(e476) { + fprintf(stdout, "Resize ncells_capacity\n"); + fflush(stdout); + const int e477 = resize * 2; + ncells_capacity = e477; + cell_particles = (int *) realloc(cell_particles, (sizeof(int) * (ncells_capacity * cell_capacity))); + cell_sizes = (int *) realloc(cell_sizes, (sizeof(int) * ncells_capacity)); + } + } + nstencil = 0; + for(int i15 = -1; i15 < 2; i15++) { + const int a59 = dim_cells[0]; + const int e481 = i15 * a59; + for(int i16 = -1; i16 < 2; i16++) { + const int e482 = e481 + i16; + const int a60 = dim_cells[1]; + const int e483 = e482 * a60; + for(int i17 = -1; i17 < 2; i17++) { + const int e484 = e483 + i17; + stencil[nstencil] = e484; + const int e485 = nstencil + 1; + nstencil = e485; + } + } + } + const int e486 = nlocal + npbc; + pairs::vtk_write_data(ps, "output/test_local", 0, nlocal, 0); + pairs::vtk_write_data(ps, "output/test_pbc", nlocal, e486, 0); + for(int i14 = 0; i14 < 101; i14++) { + const int e452 = i14 % 20; + const bool e453 = e452 == 0; + if(e453) { + fprintf(stdout, "EnforcePBC\n"); + fflush(stdout); + const double e115 = grid0_d0_max - grid0_d0_min; + const double e122 = grid0_d0_max - grid0_d0_min; + const double e129 = grid0_d1_max - grid0_d1_min; + const double e136 = grid0_d1_max - grid0_d1_min; + const double e143 = grid0_d2_max - grid0_d2_min; + const double e150 = grid0_d2_max - grid0_d2_min; + for(int i3 = 0; i3 < nlocal; i3++) { + const int e110 = i3 * 3; + const double p8_0 = position[e110]; + const bool e112 = p8_0 < grid0_d0_min; + if(e112) { + const int e113 = i3 * 3; + const double p9_0 = position[e113]; + const double e116 = p9_0 + e115; + position[e113] = e116; + } + const int e117 = i3 * 3; + const double p10_0 = position[e117]; + const bool e119 = p10_0 > grid0_d0_max; + if(e119) { + const int e120 = i3 * 3; + const double p11_0 = position[e120]; + const double e123 = p11_0 - e122; + position[e120] = e123; + } + const int e124 = i3 * 3; + const int e125 = e124 + 1; + const double p12_1 = position[e125]; + const bool e126 = p12_1 < grid0_d1_min; + if(e126) { + const int e127 = i3 * 3; + const int e128 = e127 + 1; + const double p13_1 = position[e128]; + const double e130 = p13_1 + e129; + position[e128] = e130; + } + const int e131 = i3 * 3; + const int e132 = e131 + 1; + const double p14_1 = position[e132]; + const bool e133 = p14_1 > grid0_d1_max; + if(e133) { + const int e134 = i3 * 3; + const int e135 = e134 + 1; + const double p15_1 = position[e135]; + const double e137 = p15_1 - e136; + position[e135] = e137; + } + const int e138 = i3 * 3; + const int e139 = e138 + 2; + const double p16_2 = position[e139]; + const bool e140 = p16_2 < grid0_d2_min; + if(e140) { + const int e141 = i3 * 3; + const int e142 = e141 + 2; + const double p17_2 = position[e142]; + const double e144 = p17_2 + e143; + position[e142] = e144; + } + const int e145 = i3 * 3; + const int e146 = e145 + 2; + const double p18_2 = position[e146]; + const bool e147 = p18_2 > grid0_d2_max; + if(e147) { + const int e148 = i3 * 3; + const int e149 = e148 + 2; + const double p19_2 = position[e149]; + const double e151 = p19_2 - e150; + position[e149] = e151; + } + } + } + const int e454 = i14 % 20; + const bool e455 = e454 == 0; + if(e455) { + fprintf(stdout, "SetupPBC\n"); + fflush(stdout); + resize = 1; + while((resize > 0)) { + resize = 0; + npbc = 0; + const int e153 = nlocal + npbc; + const double e157 = grid0_d0_min + 2.8; + const double e168 = grid0_d0_max - grid0_d0_min; + const double e185 = grid0_d0_max - 2.8; + const double e196 = grid0_d0_max - grid0_d0_min; + for(int i4 = 0; i4 < e153; i4++) { + const int e154 = nlocal + npbc; + const int e155 = i4 * 3; + const double p20_0 = position[e155]; + const bool e158 = p20_0 < e157; + if(e158) { + const bool e159 = npbc >= pbc_capacity; + if(e159) { + const bool e160 = resize > npbc; + resize = (e160) ? ((resize + 1)) : (npbc); + } else { + pbc_map[npbc] = i4; + const int e162 = npbc * 3; + pbc_mult[e162] = 1; + const int e164 = e154 * 3; + const double p21_0 = position[e164]; + const int e166 = i4 * 3; + const double p22_0 = position[e166]; + const double e169 = p22_0 + e168; + position[e164] = e169; + const int e170 = npbc * 3; + const int e171 = e170 + 1; + pbc_mult[e171] = 0; + const int e172 = e154 * 3; + const int e173 = e172 + 1; + const double p23_1 = position[e173]; + const int e174 = i4 * 3; + const int e175 = e174 + 1; + const double p24_1 = position[e175]; + position[e173] = p24_1; + const int e176 = npbc * 3; + const int e177 = e176 + 2; + pbc_mult[e177] = 0; + const int e178 = e154 * 3; + const int e179 = e178 + 2; + const double p25_2 = position[e179]; + const int e180 = i4 * 3; + const int e181 = e180 + 2; + const double p26_2 = position[e181]; + position[e179] = p26_2; + const int e182 = npbc + 1; + npbc = e182; + } + } + const int e183 = i4 * 3; + const double p27_0 = position[e183]; + const bool e186 = p27_0 > e185; + if(e186) { + const bool e187 = npbc >= pbc_capacity; + if(e187) { + const bool e188 = resize > npbc; + resize = (e188) ? ((resize + 1)) : (npbc); + } else { + pbc_map[npbc] = i4; + const int e190 = npbc * 3; + pbc_mult[e190] = -1; + const int e192 = e154 * 3; + const double p28_0 = position[e192]; + const int e194 = i4 * 3; + const double p29_0 = position[e194]; + const double e197 = p29_0 - e196; + position[e192] = e197; + const int e198 = npbc * 3; + const int e199 = e198 + 1; + pbc_mult[e199] = 0; + const int e200 = e154 * 3; + const int e201 = e200 + 1; + const double p30_1 = position[e201]; + const int e202 = i4 * 3; + const int e203 = e202 + 1; + const double p31_1 = position[e203]; + position[e201] = p31_1; + const int e204 = npbc * 3; + const int e205 = e204 + 2; + pbc_mult[e205] = 0; + const int e206 = e154 * 3; + const int e207 = e206 + 2; + const double p32_2 = position[e207]; + const int e208 = i4 * 3; + const int e209 = e208 + 2; + const double p33_2 = position[e209]; + position[e207] = p33_2; + const int e210 = npbc + 1; + npbc = e210; + } + } + } + const int e211 = nlocal + npbc; + const double e215 = grid0_d1_min + 2.8; + const double e226 = grid0_d1_max - grid0_d1_min; + const double e243 = grid0_d1_max - 2.8; + const double e254 = grid0_d1_max - grid0_d1_min; + for(int i5 = 0; i5 < e211; i5++) { + const int e212 = nlocal + npbc; + const int e213 = i5 * 3; + const int e214 = e213 + 1; + const double p34_1 = position[e214]; + const bool e216 = p34_1 < e215; + if(e216) { + const bool e217 = npbc >= pbc_capacity; + if(e217) { + const bool e218 = resize > npbc; + resize = (e218) ? ((resize + 1)) : (npbc); + } else { + pbc_map[npbc] = i5; + const int e220 = npbc * 3; + const int e221 = e220 + 1; + pbc_mult[e221] = 1; + const int e222 = e212 * 3; + const int e223 = e222 + 1; + const double p35_1 = position[e223]; + const int e224 = i5 * 3; + const int e225 = e224 + 1; + const double p36_1 = position[e225]; + const double e227 = p36_1 + e226; + position[e223] = e227; + const int e228 = npbc * 3; + pbc_mult[e228] = 0; + const int e230 = e212 * 3; + const double p37_0 = position[e230]; + const int e232 = i5 * 3; + const double p38_0 = position[e232]; + position[e230] = p38_0; + const int e234 = npbc * 3; + const int e235 = e234 + 2; + pbc_mult[e235] = 0; + const int e236 = e212 * 3; + const int e237 = e236 + 2; + const double p39_2 = position[e237]; + const int e238 = i5 * 3; + const int e239 = e238 + 2; + const double p40_2 = position[e239]; + position[e237] = p40_2; + const int e240 = npbc + 1; + npbc = e240; + } + } + const int e241 = i5 * 3; + const int e242 = e241 + 1; + const double p41_1 = position[e242]; + const bool e244 = p41_1 > e243; + if(e244) { + const bool e245 = npbc >= pbc_capacity; + if(e245) { + const bool e246 = resize > npbc; + resize = (e246) ? ((resize + 1)) : (npbc); + } else { + pbc_map[npbc] = i5; + const int e248 = npbc * 3; + const int e249 = e248 + 1; + pbc_mult[e249] = -1; + const int e250 = e212 * 3; + const int e251 = e250 + 1; + const double p42_1 = position[e251]; + const int e252 = i5 * 3; + const int e253 = e252 + 1; + const double p43_1 = position[e253]; + const double e255 = p43_1 - e254; + position[e251] = e255; + const int e256 = npbc * 3; + pbc_mult[e256] = 0; + const int e258 = e212 * 3; + const double p44_0 = position[e258]; + const int e260 = i5 * 3; + const double p45_0 = position[e260]; + position[e258] = p45_0; + const int e262 = npbc * 3; + const int e263 = e262 + 2; + pbc_mult[e263] = 0; + const int e264 = e212 * 3; + const int e265 = e264 + 2; + const double p46_2 = position[e265]; + const int e266 = i5 * 3; + const int e267 = e266 + 2; + const double p47_2 = position[e267]; + position[e265] = p47_2; + const int e268 = npbc + 1; + npbc = e268; + } + } + } + const int e269 = nlocal + npbc; + const double e273 = grid0_d2_min + 2.8; + const double e284 = grid0_d2_max - grid0_d2_min; + const double e301 = grid0_d2_max - 2.8; + const double e312 = grid0_d2_max - grid0_d2_min; + for(int i6 = 0; i6 < e269; i6++) { + const int e270 = nlocal + npbc; + const int e271 = i6 * 3; + const int e272 = e271 + 2; + const double p48_2 = position[e272]; + const bool e274 = p48_2 < e273; + if(e274) { + const bool e275 = npbc >= pbc_capacity; + if(e275) { + const bool e276 = resize > npbc; + resize = (e276) ? ((resize + 1)) : (npbc); + } else { + pbc_map[npbc] = i6; + const int e278 = npbc * 3; + const int e279 = e278 + 2; + pbc_mult[e279] = 1; + const int e280 = e270 * 3; + const int e281 = e280 + 2; + const double p49_2 = position[e281]; + const int e282 = i6 * 3; + const int e283 = e282 + 2; + const double p50_2 = position[e283]; + const double e285 = p50_2 + e284; + position[e281] = e285; + const int e286 = npbc * 3; + pbc_mult[e286] = 0; + const int e288 = e270 * 3; + const double p51_0 = position[e288]; + const int e290 = i6 * 3; + const double p52_0 = position[e290]; + position[e288] = p52_0; + const int e292 = npbc * 3; + const int e293 = e292 + 1; + pbc_mult[e293] = 0; + const int e294 = e270 * 3; + const int e295 = e294 + 1; + const double p53_1 = position[e295]; + const int e296 = i6 * 3; + const int e297 = e296 + 1; + const double p54_1 = position[e297]; + position[e295] = p54_1; + const int e298 = npbc + 1; + npbc = e298; + } + } + const int e299 = i6 * 3; + const int e300 = e299 + 2; + const double p55_2 = position[e300]; + const bool e302 = p55_2 > e301; + if(e302) { + const bool e303 = npbc >= pbc_capacity; + if(e303) { + const bool e304 = resize > npbc; + resize = (e304) ? ((resize + 1)) : (npbc); + } else { + pbc_map[npbc] = i6; + const int e306 = npbc * 3; + const int e307 = e306 + 2; + pbc_mult[e307] = -1; + const int e308 = e270 * 3; + const int e309 = e308 + 2; + const double p56_2 = position[e309]; + const int e310 = i6 * 3; + const int e311 = e310 + 2; + const double p57_2 = position[e311]; + const double e313 = p57_2 - e312; + position[e309] = e313; + const int e314 = npbc * 3; + pbc_mult[e314] = 0; + const int e316 = e270 * 3; + const double p58_0 = position[e316]; + const int e318 = i6 * 3; + const double p59_0 = position[e318]; + position[e316] = p59_0; + const int e320 = npbc * 3; + const int e321 = e320 + 1; + pbc_mult[e321] = 0; + const int e322 = e270 * 3; + const int e323 = e322 + 1; + const double p60_1 = position[e323]; + const int e324 = i6 * 3; + const int e325 = e324 + 1; + const double p61_1 = position[e325]; + position[e323] = p61_1; + const int e326 = npbc + 1; + npbc = e326; + } + } + } + const bool e327 = resize > 0; + if(e327) { + fprintf(stdout, "Resize pbc_capacity\n"); + fflush(stdout); + const int e328 = resize * 2; + pbc_capacity = e328; + pbc_map = (int *) realloc(pbc_map, (sizeof(int) * pbc_capacity)); + pbc_mult = (int *) realloc(pbc_mult, (sizeof(int) * (pbc_capacity * 3))); + mass = (double *) realloc(mass, (sizeof(double) * (particle_capacity + pbc_capacity))); + ps->updateProperty(0, mass); + position = (double *) realloc(position, (sizeof(double) * ((particle_capacity + pbc_capacity) * 3))); + ps->updateProperty(1, position, (particle_capacity + pbc_capacity), 3); + velocity = (double *) realloc(velocity, (sizeof(double) * ((particle_capacity + pbc_capacity) * 3))); + ps->updateProperty(2, velocity, (particle_capacity + pbc_capacity), 3); + force = (double *) realloc(force, (sizeof(double) * ((particle_capacity + pbc_capacity) * 3))); + ps->updateProperty(3, force, (particle_capacity + pbc_capacity), 3); + } + } + } else { + fprintf(stdout, "UpdatePBC\n"); + fflush(stdout); + const double e348 = grid0_d0_max - grid0_d0_min; + const double e358 = grid0_d1_max - grid0_d1_min; + const double e368 = grid0_d2_max - grid0_d2_min; + for(int i7 = 0; i7 < npbc; i7++) { + const int e341 = nlocal + i7; + const int e342 = e341 * 3; + const double p62_0 = position[e342]; + const int a32 = pbc_map[i7]; + const int e344 = a32 * 3; + const double p63_0 = position[e344]; + const int e346 = i7 * 3; + const int a33 = pbc_mult[e346]; + const double e349 = a33 * e348; + const double e350 = p63_0 + e349; + position[e342] = e350; + const int e351 = nlocal + i7; + const int e352 = e351 * 3; + const int e353 = e352 + 1; + const double p64_1 = position[e353]; + const int a34 = pbc_map[i7]; + const int e354 = a34 * 3; + const int e355 = e354 + 1; + const double p65_1 = position[e355]; + const int e356 = i7 * 3; + const int e357 = e356 + 1; + const int a35 = pbc_mult[e357]; + const double e359 = a35 * e358; + const double e360 = p65_1 + e359; + position[e353] = e360; + const int e361 = nlocal + i7; + const int e362 = e361 * 3; + const int e363 = e362 + 2; + const double p66_2 = position[e363]; + const int a36 = pbc_map[i7]; + const int e364 = a36 * 3; + const int e365 = e364 + 2; + const double p67_2 = position[e365]; + const int e366 = i7 * 3; + const int e367 = e366 + 2; + const int a37 = pbc_mult[e367]; + const double e369 = a37 * e368; + const double e370 = p67_2 + e369; + position[e363] = e370; + } + } + const int e456 = i14 % 20; + const bool e457 = e456 == 0; + if(e457) { + fprintf(stdout, "CellListsBuild\n"); + fflush(stdout); + resize = 1; + while((resize > 0)) { + resize = 0; + for(int i8 = 0; i8 < ncells; i8++) { + cell_sizes[i8] = 0; + } + const int e511 = nlocal + npbc; + for(int i9 = 0; i9 < e511; i9++) { + const int e372 = i9 * 3; + const double p68_0 = position[e372]; + const double e374 = p68_0 - grid0_d0_min; + const double e375 = e374 / 2.8; + const int e376 = i9 * 3; + const int e377 = e376 + 1; + const double p69_1 = position[e377]; + const double e378 = p69_1 - grid0_d1_min; + const double e379 = e378 / 2.8; + const int e380 = i9 * 3; + const int e381 = e380 + 2; + const double p70_2 = position[e381]; + const double e382 = p70_2 - grid0_d2_min; + const double e383 = e382 / 2.8; + const int a39 = dim_cells[1]; + const int e384 = (int)(e375) * a39; + const int e385 = e384 + (int)(e379); + const int a40 = dim_cells[2]; + const int e386 = e385 * a40; + const int e387 = e386 + (int)(e383); + const bool e388 = e387 >= 0; + const bool e389 = e387 <= ncells; + const bool e390 = e388 && e389; + if(e390) { + const int a41 = cell_sizes[e387]; + const bool e391 = a41 >= cell_capacity; + if(e391) { + resize = a41; + } else { + const int e392 = e387 * cell_capacity; + const int e393 = e392 + a41; + cell_particles[e393] = i9; + particle_cell[i9] = e387; + } + const int e394 = a41 + 1; + cell_sizes[e387] = e394; + } + } + const bool e395 = resize > 0; + if(e395) { + fprintf(stdout, "Resize cell_capacity\n"); + fflush(stdout); + const int e396 = resize * 2; + cell_capacity = e396; + cell_particles = (int *) realloc(cell_particles, (sizeof(int) * (ncells_capacity * cell_capacity))); + } + } + } + const int e458 = i14 % 20; + const bool e459 = e458 == 0; + if(e459) { + fprintf(stdout, "NeighborListsBuild\n"); + fflush(stdout); + resize = 1; + while((resize > 0)) { + resize = 0; + for(int i10 = 0; i10 < nlocal; i10++) { + numneighs[i10] = 0; + for(int i11 = 0; i11 < nstencil; i11++) { + const int a46 = particle_cell[i10]; + const int a47 = stencil[i11]; + const int e400 = a46 + a47; + const bool e401 = e400 >= 0; + const bool e402 = e400 <= ncells; + const bool e403 = e401 && e402; + if(e403) { + const int e404 = e400 * cell_capacity; + const int e412 = i10 * 3; + const double p71_0 = position[e412]; + const int e421 = i10 * 3; + const int e422 = e421 + 1; + const double p71_1 = position[e422]; + const int e431 = i10 * 3; + const int e432 = e431 + 2; + const double p71_2 = position[e432]; + const int e439 = i10 * neighborlist_capacity; + const int a48 = cell_sizes[e400]; + for(int i12 = 0; i12 < a48; i12++) { + const int e405 = e404 + i12; + const int a49 = cell_particles[e405]; + const bool e406 = a49 != i10; + if(e406) { + const int e414 = a49 * 3; + const double p72_0 = position[e414]; + const int e423 = a49 * 3; + const int e424 = e423 + 1; + const double p72_1 = position[e424]; + const int e433 = a49 * 3; + const int e434 = e433 + 2; + const double p72_2 = position[e434]; + const double e407_0 = p71_0 - p72_0; + const double e407_1 = p71_1 - p72_1; + const double e407_2 = p71_2 - p72_2; + const double e416 = e407_0 * e407_0; + const double e425 = e407_1 * e407_1; + const double e426 = e416 + e425; + const double e435 = e407_2 * e407_2; + const double e436 = e426 + e435; + const bool e437 = e436 < 2.8; + if(e437) { + const int a50 = numneighs[i10]; + const bool e438 = a50 >= neighborlist_capacity; + if(e438) { + resize = a50; + } else { + const int e440 = e439 + a50; + neighborlists[e440] = a49; + const int e441 = a50 + 1; + numneighs[i10] = e441; + } + } + } + } + } + } + } + const bool e442 = resize > 0; + if(e442) { + fprintf(stdout, "Resize neighborlist_capacity\n"); + fflush(stdout); + const int e443 = resize * 2; + neighborlist_capacity = e443; + neighborlists = (int *) realloc(neighborlists, (sizeof(int) * (particle_capacity * neighborlist_capacity))); + } + } + } + fprintf(stdout, "PropertiesResetVolatile\n"); + fflush(stdout); + for(int i13 = 0; i13 < nlocal; i13++) { + const int e446 = i13 * 3; + const double p73_0 = force[e446]; + const int e448 = i13 * 3; + const int e449 = e448 + 1; + const double p73_1 = force[e449]; + const int e450 = i13 * 3; + const int e451 = e450 + 2; + const double p73_2 = force[e451]; + force[e446] = 0.0; + force[e449] = 0.0; + force[e451] = 0.0; + } + for(int i0 = 0; i0 < nlocal; i0++) { + const int e1 = i0 * neighborlist_capacity; + const int e47 = i0 * 3; + const double p0_0 = position[e47]; + const int e55 = i0 * 3; + const int e56 = e55 + 1; + const double p0_1 = position[e56]; + const int e63 = i0 * 3; + const int e64 = e63 + 2; + const double p0_2 = position[e64]; + const int e51 = i0 * 3; + const int e59 = i0 * 3; + const int e60 = e59 + 1; + const int e67 = i0 * 3; + const int e68 = e67 + 2; + const int a6 = numneighs[i0]; + for(int i1 = 0; i1 < a6; i1++) { + const int e2 = e1 + i1; + const int a7 = neighborlists[e2]; + const int e49 = a7 * 3; + const double p1_0 = position[e49]; + const int e57 = a7 * 3; + const int e58 = e57 + 1; + const double p1_1 = position[e58]; + const int e65 = a7 * 3; + const int e66 = e65 + 2; + const double p1_2 = position[e66]; + const double e3_0 = p0_0 - p1_0; + const double e3_1 = p0_1 - p1_1; + const double e3_2 = p0_2 - p1_2; + const double e12 = e3_0 * e3_0; + const double e21 = e3_1 * e3_1; + const double e22 = e12 + e21; + const double e31 = e3_2 * e3_2; + const double e32 = e22 + e31; + const bool e33 = e32 < 2.5; + if(e33) { + const double e34 = 1.0 / e32; + const double e35 = e34 * e34; + const double e36 = e35 * e34; + const double p2_0 = force[e51]; + const double p2_1 = force[e60]; + const double p2_2 = force[e68]; + const double e40 = e36 - 0.5; + const double e507 = 48.0 * e36; + const double e508 = e507 * e40; + const double e509 = e508 * e34; + const double e43_0 = e3_0 * e509; + const double e43_1 = e3_1 * e509; + const double e43_2 = e3_2 * e509; + const double e44_0 = p2_0 + e43_0; + const double e44_1 = p2_1 + e43_1; + const double e44_2 = p2_2 + e43_2; + force[e51] = e44_0; + force[e60] = e44_1; + force[e68] = e44_2; + } + } + } + for(int i2 = 0; i2 < nlocal; i2++) { + const int e76 = i2 * 3; + const double p3_0 = velocity[e76]; + const int e82 = i2 * 3; + const int e83 = e82 + 1; + const double p3_1 = velocity[e83]; + const int e88 = i2 * 3; + const int e89 = e88 + 2; + const double p3_2 = velocity[e89]; + const int e74 = i2 * 3; + const double p4_0 = force[e74]; + const int e80 = i2 * 3; + const int e81 = e80 + 1; + const double p4_1 = force[e81]; + const int e86 = i2 * 3; + const int e87 = e86 + 2; + const double p4_2 = force[e87]; + const double e69_0 = 0.005 * p4_0; + const double e69_1 = 0.005 * p4_1; + const double e69_2 = 0.005 * p4_2; + const double p5 = mass[i2]; + const double e70_0 = e69_0 / p5; + const double e70_1 = e69_1 / p5; + const double e70_2 = e69_2 / p5; + const double e71_0 = p3_0 + e70_0; + const double e71_1 = p3_1 + e70_1; + const double e71_2 = p3_2 + e70_2; + velocity[e76] = e71_0; + velocity[e83] = e71_1; + velocity[e89] = e71_2; + const int e96 = i2 * 3; + const double p6_0 = position[e96]; + const int e102 = i2 * 3; + const int e103 = e102 + 1; + const double p6_1 = position[e103]; + const int e108 = i2 * 3; + const int e109 = e108 + 2; + const double p6_2 = position[e109]; + const int e94 = i2 * 3; + const double p7_0 = velocity[e94]; + const int e100 = i2 * 3; + const int e101 = e100 + 1; + const double p7_1 = velocity[e101]; + const int e106 = i2 * 3; + const int e107 = e106 + 2; + const double p7_2 = velocity[e107]; + const double e90_0 = 0.005 * p7_0; + const double e90_1 = 0.005 * p7_1; + const double e90_2 = 0.005 * p7_2; + const double e91_0 = p6_0 + e90_0; + const double e91_1 = p6_1 + e90_1; + const double e91_2 = p6_2 + e90_2; + position[e96] = e91_0; + position[e103] = e91_1; + position[e109] = e91_2; + } + const int e461 = nlocal + npbc; + const int e460 = i14 + 1; + pairs::vtk_write_data(ps, "output/test_local", 0, nlocal, e460); + pairs::vtk_write_data(ps, "output/test_pbc", nlocal, e461, e460); + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..374b58c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +requires = [ + "setuptools>=42", + "wheel" +] +build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c9a1f5f --- /dev/null +++ b/setup.py @@ -0,0 +1,46 @@ +import setuptools + + +def readme(): + with open('README.md') as f: + return f.read() + + +modules = [ + 'code_gen', + 'coupling', + 'graph', + 'ir', + 'mapping', + 'runtime', + 'sim', + 'transformations', +] + +setuptools.setup(name='pairs', + description="A code generator for particle simulations", + version="0.0.1", + long_description=readme(), + long_description_content_type="text/markdown", + author="Rafael Ravedutti Lucio Machado", + license='MIT', + author_email="rafael.r.ravedutti@fau.de", + url="https://github.com/rafaelravedutti/pairs", + install_requires=[], + packages=['pairs'] + [f"pairs.{mod}" for mod in modules], + package_dir={'pairs': 'src/pairs'}, + package_data={'pairs.runtime': ['runtime/*.hpp']}, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + project_urls={ + "Bug Tracker": "https://github.com/rafaelravedutti/pairs", + "Documentation": "https://github.com/rafaelravedutti/pairs", + "Source Code": "https://github.com/rafaelravedutti/pairs", + }, + extras_require={}, + tests_require=[], + python_requires=">=3.6", +) diff --git a/code_gen/__init__.py b/src/__init__.py similarity index 100% rename from code_gen/__init__.py rename to src/__init__.py diff --git a/pairs.py b/src/pairs/__init__.py similarity index 53% rename from pairs.py rename to src/pairs/__init__.py index d816433..5a71e58 100644 --- a/pairs.py +++ b/src/pairs/__init__.py @@ -1,5 +1,5 @@ -from code_gen.cgen import CGen -from sim.particle_simulation import ParticleSimulation +from pairs.code_gen.cgen import CGen +from pairs.sim.particle_simulation import ParticleSimulation def simulation(ref, dims=3, timesteps=100): diff --git a/coupling/__init__.py b/src/pairs/code_gen/__init__.py similarity index 100% rename from coupling/__init__.py rename to src/pairs/code_gen/__init__.py diff --git a/code_gen/cgen.py b/src/pairs/code_gen/cgen.py similarity index 93% rename from code_gen/cgen.py rename to src/pairs/code_gen/cgen.py index 93ea927..219e9e9 100644 --- a/code_gen/cgen.py +++ b/src/pairs/code_gen/cgen.py @@ -1,23 +1,23 @@ -from ir.assign import Assign -from ir.arrays import Array, ArrayAccess, ArrayDecl -from ir.block import Block -from ir.branches import Branch -from ir.cast import Cast -from ir.bin_op import BinOp, Decl, VectorAccess -from ir.data_types import Type_Int, Type_Float, Type_String, Type_Vector -from ir.functions import Call -from ir.layouts import Layout_AoS, Layout_SoA, Layout_Invalid -from ir.lit import Lit -from ir.loops import For, Iter, ParticleFor, While -from ir.math import Ceil, Sqrt -from ir.memory import Malloc, Realloc -from ir.properties import Property, PropertyAccess, PropertyList, RegisterProperty, UpdateProperty -from ir.select import Select -from ir.sizeof import Sizeof -from ir.utils import Print -from ir.variables import Var, VarDecl -from sim.timestep import Timestep -from code_gen.printer import Printer +from pairs.ir.assign import Assign +from pairs.ir.arrays import Array, ArrayAccess, ArrayDecl +from pairs.ir.block import Block +from pairs.ir.branches import Branch +from pairs.ir.cast import Cast +from pairs.ir.bin_op import BinOp, Decl, VectorAccess +from pairs.ir.data_types import Type_Int, Type_Float, Type_String, Type_Vector +from pairs.ir.functions import Call +from pairs.ir.layouts import Layout_AoS, Layout_SoA, Layout_Invalid +from pairs.ir.lit import Lit +from pairs.ir.loops import For, Iter, ParticleFor, While +from pairs.ir.math import Ceil, Sqrt +from pairs.ir.memory import Malloc, Realloc +from pairs.ir.properties import Property, PropertyAccess, PropertyList, RegisterProperty, UpdateProperty +from pairs.ir.select import Select +from pairs.ir.sizeof import Sizeof +from pairs.ir.utils import Print +from pairs.ir.variables import Var, VarDecl +from pairs.sim.timestep import Timestep +from pairs.code_gen.printer import Printer class CGen: diff --git a/code_gen/printer.py b/src/pairs/code_gen/printer.py similarity index 100% rename from code_gen/printer.py rename to src/pairs/code_gen/printer.py diff --git a/ir/__init__.py b/src/pairs/coupling/__init__.py similarity index 100% rename from ir/__init__.py rename to src/pairs/coupling/__init__.py diff --git a/coupling/parse_cpp.py b/src/pairs/coupling/parse_cpp.py similarity index 97% rename from coupling/parse_cpp.py rename to src/pairs/coupling/parse_cpp.py index 726475e..8c94702 100644 --- a/coupling/parse_cpp.py +++ b/src/pairs/coupling/parse_cpp.py @@ -1,10 +1,10 @@ -from ast.block import Block -from ast.branches import Branch -from ast.data_types import Type_Float, Type_Vector -from ast.math import Sqrt -from ast.select import Select import clang.cindex from clang.cindex import CursorKind as kind +from pairs.ast.block import Block +from pairs.ast.branches import Branch +from pairs.ast.data_types import Type_Float, Type_Vector +from pairs.ast.math import Sqrt +from pairs.ast.select import Select def print_tree(node, indent=0): diff --git a/sim/__init__.py b/src/pairs/graph/__init__.py similarity index 100% rename from sim/__init__.py rename to src/pairs/graph/__init__.py diff --git a/graph/graphviz.py b/src/pairs/graph/graphviz.py similarity index 86% rename from graph/graphviz.py rename to src/pairs/graph/graphviz.py index e078b42..535abe4 100644 --- a/graph/graphviz.py +++ b/src/pairs/graph/graphviz.py @@ -1,11 +1,11 @@ -from ir.arrays import Array -from ir.bin_op import BinOp, Decl -from ir.lit import Lit -from ir.loops import Iter -from ir.properties import Property -from ir.variables import Var -from ir.visitor import Visitor from graphviz import Digraph +from pairs.ir.arrays import Array +from pairs.ir.bin_op import BinOp, Decl +from pairs.ir.lit import Lit +from pairs.ir.loops import Iter +from pairs.ir.properties import Property +from pairs.ir.variables import Var +from pairs.ir.visitor import Visitor class ASTGraph: diff --git a/ir/operators.py b/src/pairs/ir/__init__.py similarity index 100% rename from ir/operators.py rename to src/pairs/ir/__init__.py diff --git a/ir/arrays.py b/src/pairs/ir/arrays.py similarity index 94% rename from ir/arrays.py rename to src/pairs/ir/arrays.py index a49e39a..49aeb88 100644 --- a/ir/arrays.py +++ b/src/pairs/ir/arrays.py @@ -1,12 +1,12 @@ -from ir.assign import Assign -from ir.ast_node import ASTNode -from ir.bin_op import BinOp, ASTTerm -from ir.data_types import Type_Array -from ir.layouts import Layout_AoS, Layout_SoA -from ir.lit import as_lit_ast -from ir.memory import Realloc -from ir.variables import Var from functools import reduce +from pairs.ir.assign import Assign +from pairs.ir.ast_node import ASTNode +from pairs.ir.bin_op import BinOp, ASTTerm +from pairs.ir.data_types import Type_Array +from pairs.ir.layouts import Layout_AoS, Layout_SoA +from pairs.ir.lit import as_lit_ast +from pairs.ir.memory import Realloc +from pairs.ir.variables import Var class Arrays: diff --git a/ir/assign.py b/src/pairs/ir/assign.py similarity index 83% rename from ir/assign.py rename to src/pairs/ir/assign.py index 4465699..97af6ea 100644 --- a/ir/assign.py +++ b/src/pairs/ir/assign.py @@ -1,8 +1,8 @@ -from ir.ast_node import ASTNode -from ir.data_types import Type_Vector -from ir.lit import as_lit_ast -from ir.vector_expr import VectorExpression from functools import reduce +from pairs.ir.ast_node import ASTNode +from pairs.ir.data_types import Type_Vector +from pairs.ir.lit import as_lit_ast +from pairs.ir.vector_expr import VectorExpression class Assign(ASTNode): diff --git a/ir/ast_node.py b/src/pairs/ir/ast_node.py similarity index 88% rename from ir/ast_node.py rename to src/pairs/ir/ast_node.py index cbfc0f4..94e75fa 100644 --- a/ir/ast_node.py +++ b/src/pairs/ir/ast_node.py @@ -1,4 +1,4 @@ -from ir.data_types import Type_Invalid +from pairs.ir.data_types import Type_Invalid class ASTNode: diff --git a/ir/bin_op.py b/src/pairs/ir/bin_op.py similarity index 96% rename from ir/bin_op.py rename to src/pairs/ir/bin_op.py index 46c3e4d..95f48dc 100644 --- a/ir/bin_op.py +++ b/src/pairs/ir/bin_op.py @@ -1,8 +1,8 @@ -from ir.ast_node import ASTNode -from ir.assign import Assign -from ir.data_types import Type_Float, Type_Bool, Type_Vector -from ir.lit import as_lit_ast -from ir.vector_expr import VectorExpression +from pairs.ir.ast_node import ASTNode +from pairs.ir.assign import Assign +from pairs.ir.data_types import Type_Float, Type_Bool, Type_Vector +from pairs.ir.lit import as_lit_ast +from pairs.ir.vector_expr import VectorExpression class Decl(ASTNode): diff --git a/ir/block.py b/src/pairs/ir/block.py similarity index 97% rename from ir/block.py rename to src/pairs/ir/block.py index b136db8..853de45 100644 --- a/ir/block.py +++ b/src/pairs/ir/block.py @@ -1,4 +1,4 @@ -from ir.ast_node import ASTNode +from pairs.ir.ast_node import ASTNode class Block(ASTNode): diff --git a/ir/branches.py b/src/pairs/ir/branches.py similarity index 92% rename from ir/branches.py rename to src/pairs/ir/branches.py index 224e671..93962ad 100644 --- a/ir/branches.py +++ b/src/pairs/ir/branches.py @@ -1,6 +1,6 @@ -from ir.ast_node import ASTNode -from ir.block import Block -from ir.lit import as_lit_ast +from pairs.ir.ast_node import ASTNode +from pairs.ir.block import Block +from pairs.ir.lit import as_lit_ast class Branch(ASTNode): diff --git a/ir/cast.py b/src/pairs/ir/cast.py similarity index 86% rename from ir/cast.py rename to src/pairs/ir/cast.py index 7207b10..061eb47 100644 --- a/ir/cast.py +++ b/src/pairs/ir/cast.py @@ -1,5 +1,5 @@ -from ir.bin_op import ASTTerm -from ir.data_types import Type_Int, Type_Float +from pairs.ir.bin_op import ASTTerm +from pairs.ir.data_types import Type_Int, Type_Float class Cast(ASTTerm): diff --git a/ir/data_types.py b/src/pairs/ir/data_types.py similarity index 100% rename from ir/data_types.py rename to src/pairs/ir/data_types.py diff --git a/ir/functions.py b/src/pairs/ir/functions.py similarity index 85% rename from ir/functions.py rename to src/pairs/ir/functions.py index 046cd77..8b01b90 100644 --- a/ir/functions.py +++ b/src/pairs/ir/functions.py @@ -1,6 +1,6 @@ -from ir.bin_op import ASTTerm -from ir.data_types import Type_Int, Type_Invalid -from ir.lit import as_lit_ast +from pairs.ir.bin_op import ASTTerm +from pairs.ir.data_types import Type_Int, Type_Invalid +from pairs.ir.lit import as_lit_ast class Call(ASTTerm): diff --git a/ir/layouts.py b/src/pairs/ir/layouts.py similarity index 100% rename from ir/layouts.py rename to src/pairs/ir/layouts.py diff --git a/ir/lit.py b/src/pairs/ir/lit.py similarity index 88% rename from ir/lit.py rename to src/pairs/ir/lit.py index ab62157..ff738b5 100644 --- a/ir/lit.py +++ b/src/pairs/ir/lit.py @@ -1,5 +1,5 @@ -from ir.ast_node import ASTNode -from ir.data_types import Type_Invalid, Type_Int, Type_Float, Type_Bool, Type_String, Type_Vector +from pairs.ir.ast_node import ASTNode +from pairs.ir.data_types import Type_Invalid, Type_Int, Type_Float, Type_Bool, Type_String, Type_Vector def is_literal(a): diff --git a/ir/loops.py b/src/pairs/ir/loops.py similarity index 93% rename from ir/loops.py rename to src/pairs/ir/loops.py index 0243dcf..40d73d2 100644 --- a/ir/loops.py +++ b/src/pairs/ir/loops.py @@ -1,9 +1,9 @@ -from ir.ast_node import ASTNode -from ir.bin_op import BinOp, ASTTerm -from ir.block import Block -from ir.branches import Filter -from ir.data_types import Type_Int -from ir.lit import as_lit_ast +from pairs.ir.ast_node import ASTNode +from pairs.ir.bin_op import BinOp, ASTTerm +from pairs.ir.block import Block +from pairs.ir.branches import Filter +from pairs.ir.data_types import Type_Int +from pairs.ir.lit import as_lit_ast class Iter(ASTTerm): diff --git a/ir/math.py b/src/pairs/ir/math.py similarity index 89% rename from ir/math.py rename to src/pairs/ir/math.py index 93d6269..9ef762f 100644 --- a/ir/math.py +++ b/src/pairs/ir/math.py @@ -1,5 +1,5 @@ -from ir.bin_op import ASTTerm -from ir.data_types import Type_Int, Type_Float +from pairs.ir.bin_op import ASTTerm +from pairs.ir.data_types import Type_Int, Type_Float class Sqrt(ASTTerm): diff --git a/ir/memory.py b/src/pairs/ir/memory.py similarity index 88% rename from ir/memory.py rename to src/pairs/ir/memory.py index 21b0ace..72cd1f0 100644 --- a/ir/memory.py +++ b/src/pairs/ir/memory.py @@ -1,8 +1,8 @@ -from ir.ast_node import ASTNode -from ir.bin_op import BinOp -from ir.sizeof import Sizeof from functools import reduce import operator +from pairs.ir.ast_node import ASTNode +from pairs.ir.bin_op import BinOp +from pairs.ir.sizeof import Sizeof class Malloc(ASTNode): diff --git a/ir/mutator.py b/src/pairs/ir/mutator.py similarity index 100% rename from ir/mutator.py rename to src/pairs/ir/mutator.py diff --git a/src/pairs/ir/operators.py b/src/pairs/ir/operators.py new file mode 100644 index 0000000..e69de29 diff --git a/ir/properties.py b/src/pairs/ir/properties.py similarity index 94% rename from ir/properties.py rename to src/pairs/ir/properties.py index 2d5be92..c17c78a 100644 --- a/ir/properties.py +++ b/src/pairs/ir/properties.py @@ -1,10 +1,10 @@ -from ir.ast_node import ASTNode -from ir.assign import Assign -from ir.bin_op import BinOp, Decl, ASTTerm, VectorAccess -from ir.data_types import Type_Vector -from ir.layouts import Layout_AoS -from ir.lit import as_lit_ast -from ir.vector_expr import VectorExpression +from pairs.ir.ast_node import ASTNode +from pairs.ir.assign import Assign +from pairs.ir.bin_op import BinOp, Decl, ASTTerm, VectorAccess +from pairs.ir.data_types import Type_Vector +from pairs.ir.layouts import Layout_AoS +from pairs.ir.lit import as_lit_ast +from pairs.ir.vector_expr import VectorExpression class Properties: diff --git a/ir/select.py b/src/pairs/ir/select.py similarity index 77% rename from ir/select.py rename to src/pairs/ir/select.py index 0079d2f..8e5e3ae 100644 --- a/ir/select.py +++ b/src/pairs/ir/select.py @@ -1,6 +1,6 @@ -from ir.ast_node import ASTNode -from ir.bin_op import BinOp -from ir.lit import as_lit_ast +from pairs.ir.ast_node import ASTNode +from pairs.ir.bin_op import BinOp +from pairs.ir.lit import as_lit_ast class Select(ASTNode): diff --git a/ir/sizeof.py b/src/pairs/ir/sizeof.py similarity index 69% rename from ir/sizeof.py rename to src/pairs/ir/sizeof.py index 9d042bb..4072313 100644 --- a/ir/sizeof.py +++ b/src/pairs/ir/sizeof.py @@ -1,5 +1,5 @@ -from ir.bin_op import ASTTerm -from ir.data_types import Type_Int +from pairs.ir.bin_op import ASTTerm +from pairs.ir.data_types import Type_Int class Sizeof(ASTTerm): diff --git a/ir/transform.py b/src/pairs/ir/transform.py similarity index 92% rename from ir/transform.py rename to src/pairs/ir/transform.py index ba738b6..4705552 100644 --- a/ir/transform.py +++ b/src/pairs/ir/transform.py @@ -1,10 +1,10 @@ -from ir.arrays import ArrayAccess -from ir.bin_op import BinOp -from ir.data_types import Type_Int, Type_Vector -from ir.layouts import Layout_AoS, Layout_SoA -from ir.lit import Lit -from ir.loops import Iter -from ir.properties import Property +from pairs.ir.arrays import ArrayAccess +from pairs.ir.bin_op import BinOp +from pairs.ir.data_types import Type_Int, Type_Vector +from pairs.ir.layouts import Layout_AoS, Layout_SoA +from pairs.ir.lit import Lit +from pairs.ir.loops import Iter +from pairs.ir.properties import Property class Transform: diff --git a/ir/utils.py b/src/pairs/ir/utils.py similarity index 82% rename from ir/utils.py rename to src/pairs/ir/utils.py index a4446f1..8151d68 100644 --- a/ir/utils.py +++ b/src/pairs/ir/utils.py @@ -1,4 +1,4 @@ -from ir.ast_node import ASTNode +from pairs.ir.ast_node import ASTNode class Print(ASTNode): diff --git a/ir/variables.py b/src/pairs/ir/variables.py similarity index 93% rename from ir/variables.py rename to src/pairs/ir/variables.py index b4b40da..9f456e8 100644 --- a/ir/variables.py +++ b/src/pairs/ir/variables.py @@ -1,6 +1,6 @@ -from ir.ast_node import ASTNode -from ir.assign import Assign -from ir.bin_op import ASTTerm +from pairs.ir.ast_node import ASTNode +from pairs.ir.assign import Assign +from pairs.ir.bin_op import ASTTerm class Variables: diff --git a/ir/vector_expr.py b/src/pairs/ir/vector_expr.py similarity index 92% rename from ir/vector_expr.py rename to src/pairs/ir/vector_expr.py index bd3bb0b..706a07d 100644 --- a/ir/vector_expr.py +++ b/src/pairs/ir/vector_expr.py @@ -1,6 +1,6 @@ -from ir.ast_node import ASTNode -from ir.data_types import Type_Vector -from ir.lit import Lit +from pairs.ir.ast_node import ASTNode +from pairs.ir.data_types import Type_Vector +from pairs.ir.lit import Lit class VectorExpression(ASTNode): diff --git a/ir/visitor.py b/src/pairs/ir/visitor.py similarity index 100% rename from ir/visitor.py rename to src/pairs/ir/visitor.py diff --git a/src/pairs/mapping/.funcs.py.swp b/src/pairs/mapping/.funcs.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..a5728d920b85bc0845eb39ccdc3a0ad5fbdf7362 GIT binary patch literal 16384 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 K*PC2ifqejCHIIA% literal 0 HcmV?d00001 diff --git a/src/pairs/mapping/__init__.py b/src/pairs/mapping/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/new_syntax.py b/src/pairs/mapping/funcs.py similarity index 75% rename from new_syntax.py rename to src/pairs/mapping/funcs.py index bdbeb0d..7b47ec6 100644 --- a/new_syntax.py +++ b/src/pairs/mapping/funcs.py @@ -1,30 +1,7 @@ -import pairs -from ir.assign import Assign -from ir.bin_op import BinOp import ast import inspect - - -def delta(i, j): - return position[i] - position[j] - - -def rsq(i, j): - dp = delta(i, j) - return dp.x() * dp.x() + dp.y() * dp.y() + dp.z() * dp.z() - - -def lj(i, j): - sr2 = 1.0 / rsq - sr6 = sr2 * sr2 * sr2 * sigma6 - #f = 48.0 * sr6 * (sr6 - 0.5) * sr2 * epsilon - #force[i] += delta * f - force[i] += delta * 48.0 * sr6 * (sr6 - 0.5) * sr2 * epsilon - - -def euler(i): - velocity[i] += dt * force[i] / mass[i] - position[i] += dt * velocity[i] +from pairs.ir.assign import Assign +from pairs.ir.bin_op import BinOp class UndefinedSymbol(): @@ -142,7 +119,7 @@ class BuildParticleIR(ast.NodeVisitor): return self.visit(node.value)[self.visit(node.slice)] -def add_kernel(sim, func, cutoff_radius=None, position=None, symbols={}): +def compute(sim, func, cutoff_radius=None, position=None, symbols={}): src = inspect.getsource(func) tree = ast.parse(src, mode='exec') #print(ast.dump(ast.parse(src, mode='exec'))) @@ -162,33 +139,9 @@ def add_kernel(sim, func, cutoff_radius=None, position=None, symbols={}): ir.visit(tree) elif nparams == 2: - for i, j, delta, rsq in psim.particle_pairs(cutoff_radius, sim.property(position)): + for i, j, delta, rsq in sim.particle_pairs(cutoff_radius, sim.property(position)): ir.add_symbols({params[0]: i, params[1]: j, 'delta': delta, 'rsq': rsq}) ir.visit(tree) else: raise Exception(f"Invalid number of parameters: {nparams}") - - -dt = 0.005 -cutoff_radius = 2.5 -skin = 0.3 -sigma = 1.0 -epsilon = 1.0 -sigma6 = sigma ** 6 - -psim = pairs.simulation("lj_ns") -psim.add_real_property('mass', 1.0) -psim.add_vector_property('position') -psim.add_vector_property('velocity') -psim.add_vector_property('force', vol=True) -psim.from_file("data/minimd_setup_4x4x4.input", ['mass', 'position', 'velocity']) -psim.create_cell_lists(2.8, 2.8) -psim.create_neighbor_lists() -psim.periodic(2.8) -psim.vtk_output("output/test") - -add_kernel(psim, lj, cutoff_radius, 'position', {'sigma6': sigma6, 'epsilon': epsilon}) -add_kernel(psim, euler, symbols={'dt': dt}) - -psim.generate() diff --git a/src/pairs/runtime/__init__.py b/src/pairs/runtime/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/runtime/pairs.hpp b/src/pairs/runtime/pairs.hpp similarity index 100% rename from runtime/pairs.hpp rename to src/pairs/runtime/pairs.hpp diff --git a/runtime/read_from_file.hpp b/src/pairs/runtime/read_from_file.hpp similarity index 100% rename from runtime/read_from_file.hpp rename to src/pairs/runtime/read_from_file.hpp diff --git a/runtime/vtk.hpp b/src/pairs/runtime/vtk.hpp similarity index 100% rename from runtime/vtk.hpp rename to src/pairs/runtime/vtk.hpp diff --git a/src/pairs/sim/__init__.py b/src/pairs/sim/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sim/arrays.py b/src/pairs/sim/arrays.py similarity index 82% rename from sim/arrays.py rename to src/pairs/sim/arrays.py index 7406019..232964a 100644 --- a/sim/arrays.py +++ b/src/pairs/sim/arrays.py @@ -1,5 +1,5 @@ -from ir.memory import Malloc -from ir.arrays import ArrayDecl +from pairs.ir.memory import Malloc +from pairs.ir.arrays import ArrayDecl class ArraysDecl: diff --git a/sim/cell_lists.py b/src/pairs/sim/cell_lists.py similarity index 93% rename from sim/cell_lists.py rename to src/pairs/sim/cell_lists.py index 40ec518..6e94efd 100644 --- a/sim/cell_lists.py +++ b/src/pairs/sim/cell_lists.py @@ -1,13 +1,13 @@ -from ir.bin_op import BinOp -from ir.branches import Branch, Filter -from ir.cast import Cast -from ir.data_types import Type_Int -from ir.math import Ceil -from ir.loops import For, ParticleFor -from ir.utils import Print from functools import reduce -from sim.resize import Resize import math +from pairs.ir.bin_op import BinOp +from pairs.ir.branches import Branch, Filter +from pairs.ir.cast import Cast +from pairs.ir.data_types import Type_Int +from pairs.ir.math import Ceil +from pairs.ir.loops import For, ParticleFor +from pairs.ir.utils import Print +from pairs.sim.resize import Resize class CellLists: diff --git a/sim/grid.py b/src/pairs/sim/grid.py similarity index 97% rename from sim/grid.py rename to src/pairs/sim/grid.py index 0eea7ed..6d71d2f 100644 --- a/sim/grid.py +++ b/src/pairs/sim/grid.py @@ -1,4 +1,4 @@ -from ir.data_types import Type_Float +from pairs.ir.data_types import Type_Float class Grid: diff --git a/sim/kernel_wrapper.py b/src/pairs/sim/kernel_wrapper.py similarity index 87% rename from sim/kernel_wrapper.py rename to src/pairs/sim/kernel_wrapper.py index 7ac32e3..ccf7f5a 100644 --- a/sim/kernel_wrapper.py +++ b/src/pairs/sim/kernel_wrapper.py @@ -1,4 +1,4 @@ -from ir.block import Block +from pairs.ir.block import Block class KernelWrapper(): diff --git a/sim/lattice.py b/src/pairs/sim/lattice.py similarity index 95% rename from sim/lattice.py rename to src/pairs/sim/lattice.py index b9985e6..d2332c7 100644 --- a/sim/lattice.py +++ b/src/pairs/sim/lattice.py @@ -1,5 +1,5 @@ -from ir.data_types import Type_Vector -from ir.loops import For +from pairs.ir.data_types import Type_Vector +from pairs.ir.loops import For class ParticleLattice(): diff --git a/sim/neighbor_lists.py b/src/pairs/sim/neighbor_lists.py similarity index 89% rename from sim/neighbor_lists.py rename to src/pairs/sim/neighbor_lists.py index f2fa90b..f134c1d 100644 --- a/sim/neighbor_lists.py +++ b/src/pairs/sim/neighbor_lists.py @@ -1,8 +1,8 @@ -from ir.branches import Branch, Filter -from ir.data_types import Type_Int -from ir.loops import For, ParticleFor, NeighborFor -from ir.utils import Print -from sim.resize import Resize +from pairs.ir.branches import Branch, Filter +from pairs.ir.data_types import Type_Int +from pairs.ir.loops import For, ParticleFor, NeighborFor +from pairs.ir.utils import Print +from pairs.sim.resize import Resize class NeighborLists: diff --git a/sim/particle_simulation.py b/src/pairs/sim/particle_simulation.py similarity index 82% rename from sim/particle_simulation.py rename to src/pairs/sim/particle_simulation.py index 9bf20a5..2eb5c89 100644 --- a/sim/particle_simulation.py +++ b/src/pairs/sim/particle_simulation.py @@ -1,29 +1,30 @@ -from ir.arrays import Arrays -from ir.block import Block -from ir.branches import Filter -from ir.data_types import Type_Int, Type_Float, Type_Vector -from ir.layouts import Layout_AoS -from ir.loops import ParticleFor, NeighborFor -from ir.properties import Properties -from ir.variables import Variables -from graph.graphviz import ASTGraph -from sim.arrays import ArraysDecl -from sim.cell_lists import CellLists, CellListsBuild, CellListsStencilBuild -from sim.grid import Grid2D, Grid3D -from sim.kernel_wrapper import KernelWrapper -from sim.lattice import ParticleLattice -from sim.neighbor_lists import NeighborLists, NeighborListsBuild -from sim.pbc import PBC, UpdatePBC, EnforcePBC, SetupPBC -from sim.properties import PropertiesAlloc, PropertiesResetVolatile -from sim.read_from_file import ReadFromFile -from sim.setup_wrapper import SetupWrapper -from sim.timestep import Timestep -from sim.variables import VariablesDecl -from sim.vtk import VTKWrite -from transformations.prioritize_scalar_ops import prioritaze_scalar_ops -from transformations.set_used_bin_ops import set_used_bin_ops -from transformations.simplify import simplify_expressions -from transformations.LICM import move_loop_invariant_code +from pairs.ir.arrays import Arrays +from pairs.ir.block import Block +from pairs.ir.branches import Filter +from pairs.ir.data_types import Type_Int, Type_Float, Type_Vector +from pairs.ir.layouts import Layout_AoS +from pairs.ir.loops import ParticleFor, NeighborFor +from pairs.ir.properties import Properties +from pairs.ir.variables import Variables +from pairs.graph.graphviz import ASTGraph +from pairs.mapping.funcs import compute +from pairs.sim.arrays import ArraysDecl +from pairs.sim.cell_lists import CellLists, CellListsBuild, CellListsStencilBuild +from pairs.sim.grid import Grid2D, Grid3D +from pairs.sim.kernel_wrapper import KernelWrapper +from pairs.sim.lattice import ParticleLattice +from pairs.sim.neighbor_lists import NeighborLists, NeighborListsBuild +from pairs.sim.pbc import PBC, UpdatePBC, EnforcePBC, SetupPBC +from pairs.sim.properties import PropertiesAlloc, PropertiesResetVolatile +from pairs.sim.read_from_file import ReadFromFile +from pairs.sim.setup_wrapper import SetupWrapper +from pairs.sim.timestep import Timestep +from pairs.sim.variables import VariablesDecl +from pairs.sim.vtk import VTKWrite +from pairs.transformations.prioritize_scalar_ops import prioritaze_scalar_ops +from pairs.transformations.set_used_bin_ops import set_used_bin_ops +from pairs.transformations.simplify import simplify_expressions +from pairs.transformations.LICM import move_loop_invariant_code class ParticleSimulation: @@ -128,6 +129,9 @@ class ParticleSimulation: self.properties.add_capacity(self.pbc.pbc_capacity) return self.pbc + def compute(self, sim, func, cutoff_radius=None, position=None, symbols={}): + return compute(sim, func, cutoff_radius, position, symbols) + def particle_pairs(self, cutoff_radius=None, position=None): self.clear_block() for i in ParticleFor(self): diff --git a/sim/pbc.py b/src/pairs/sim/pbc.py similarity index 94% rename from sim/pbc.py rename to src/pairs/sim/pbc.py index 1f066be..c480c4d 100644 --- a/sim/pbc.py +++ b/src/pairs/sim/pbc.py @@ -1,9 +1,9 @@ -from ir.branches import Branch, Filter -from ir.data_types import Type_Int -from ir.loops import For, ParticleFor -from ir.utils import Print -from ir.select import Select -from sim.resize import Resize +from pairs.ir.branches import Branch, Filter +from pairs.ir.data_types import Type_Int +from pairs.ir.loops import For, ParticleFor +from pairs.ir.utils import Print +from pairs.ir.select import Select +from pairs.sim.resize import Resize class PBC: diff --git a/sim/properties.py b/src/pairs/sim/properties.py similarity index 84% rename from sim/properties.py rename to src/pairs/sim/properties.py index eca3617..7839eed 100644 --- a/sim/properties.py +++ b/src/pairs/sim/properties.py @@ -1,9 +1,9 @@ +from pairs.ir.data_types import Type_Float, Type_Vector +from pairs.ir.loops import ParticleFor +from pairs.ir.memory import Malloc, Realloc +from pairs.ir.properties import RegisterProperty, UpdateProperty +from pairs.ir.utils import Print from functools import reduce -from ir.data_types import Type_Float, Type_Vector -from ir.loops import ParticleFor -from ir.memory import Malloc, Realloc -from ir.properties import RegisterProperty, UpdateProperty -from ir.utils import Print import operator diff --git a/sim/read_from_file.py b/src/pairs/sim/read_from_file.py similarity index 81% rename from sim/read_from_file.py rename to src/pairs/sim/read_from_file.py index 6a597a2..dc3355b 100644 --- a/sim/read_from_file.py +++ b/src/pairs/sim/read_from_file.py @@ -1,7 +1,7 @@ -from ir.data_types import Type_Float -from ir.functions import Call_Int -from ir.properties import PropertyList -from sim.grid import MutableGrid +from pairs.ir.data_types import Type_Float +from pairs.ir.functions import Call_Int +from pairs.ir.properties import PropertyList +from pairs.sim.grid import MutableGrid class ReadFromFile(): diff --git a/sim/resize.py b/src/pairs/sim/resize.py similarity index 84% rename from sim/resize.py rename to src/pairs/sim/resize.py index f862578..308ceaa 100644 --- a/sim/resize.py +++ b/src/pairs/sim/resize.py @@ -1,10 +1,10 @@ +from pairs.ir.branches import Filter +from pairs.ir.data_types import Type_Int, Type_Float, Type_Vector +from pairs.ir.loops import While +from pairs.ir.memory import Realloc +from pairs.ir.properties import UpdateProperty +from pairs.ir.utils import Print from functools import reduce -from ir.branches import Filter -from ir.data_types import Type_Int, Type_Float, Type_Vector -from ir.loops import While -from ir.memory import Realloc -from ir.properties import UpdateProperty -from ir.utils import Print import operator diff --git a/sim/setup_wrapper.py b/src/pairs/sim/setup_wrapper.py similarity index 87% rename from sim/setup_wrapper.py rename to src/pairs/sim/setup_wrapper.py index bc0d535..6297667 100644 --- a/sim/setup_wrapper.py +++ b/src/pairs/sim/setup_wrapper.py @@ -1,4 +1,4 @@ -from ir.block import Block +from pairs.ir.block import Block class SetupWrapper(): diff --git a/sim/timestep.py b/src/pairs/sim/timestep.py similarity index 91% rename from sim/timestep.py rename to src/pairs/sim/timestep.py index f15ee7c..3e312f2 100644 --- a/sim/timestep.py +++ b/src/pairs/sim/timestep.py @@ -1,7 +1,7 @@ -from ir.bin_op import BinOp -from ir.block import Block -from ir.branches import Branch -from ir.loops import For +from pairs.ir.bin_op import BinOp +from pairs.ir.block import Block +from pairs.ir.branches import Branch +from pairs.ir.loops import For class Timestep: diff --git a/sim/variables.py b/src/pairs/sim/variables.py similarity index 85% rename from sim/variables.py rename to src/pairs/sim/variables.py index 4d37e32..6869ed1 100644 --- a/sim/variables.py +++ b/src/pairs/sim/variables.py @@ -1,4 +1,4 @@ -from ir.variables import VarDecl +from pairs.ir.variables import VarDecl class VariablesDecl: diff --git a/sim/vtk.py b/src/pairs/sim/vtk.py similarity index 84% rename from sim/vtk.py rename to src/pairs/sim/vtk.py index c499726..86de551 100644 --- a/sim/vtk.py +++ b/src/pairs/sim/vtk.py @@ -1,6 +1,6 @@ -from ir.ast_node import ASTNode -from ir.functions import Call_Void -from ir.lit import as_lit_ast +from pairs.ir.ast_node import ASTNode +from pairs.ir.functions import Call_Void +from pairs.ir.lit import as_lit_ast class VTKWrite(ASTNode): diff --git a/transformations/LICM.py b/src/pairs/transformations/LICM.py similarity index 97% rename from transformations/LICM.py rename to src/pairs/transformations/LICM.py index 0ac4d37..264aa37 100644 --- a/transformations/LICM.py +++ b/src/pairs/transformations/LICM.py @@ -1,8 +1,8 @@ -from ir.bin_op import BinOp -from ir.loops import For, While -from ir.mutator import Mutator -from ir.properties import PropertyAccess -from ir.visitor import Visitor +from pairs.ir.bin_op import BinOp +from pairs.ir.loops import For, While +from pairs.ir.mutator import Mutator +from pairs.ir.properties import PropertyAccess +from pairs.ir.visitor import Visitor class SetBlockVariants(Mutator): diff --git a/src/pairs/transformations/__init__.py b/src/pairs/transformations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/transformations/prioritize_scalar_ops.py b/src/pairs/transformations/prioritize_scalar_ops.py similarity index 93% rename from transformations/prioritize_scalar_ops.py rename to src/pairs/transformations/prioritize_scalar_ops.py index cf099a8..47957f6 100644 --- a/transformations/prioritize_scalar_ops.py +++ b/src/pairs/transformations/prioritize_scalar_ops.py @@ -1,6 +1,6 @@ -from ir.bin_op import BinOp -from ir.data_types import Type_Float, Type_Vector -from ir.mutator import Mutator +from pairs.ir.bin_op import BinOp +from pairs.ir.data_types import Type_Float, Type_Vector +from pairs.ir.mutator import Mutator class PrioritazeScalarOps(Mutator): diff --git a/transformations/set_used_bin_ops.py b/src/pairs/transformations/set_used_bin_ops.py similarity index 93% rename from transformations/set_used_bin_ops.py rename to src/pairs/transformations/set_used_bin_ops.py index 404cb65..ac26bf1 100644 --- a/transformations/set_used_bin_ops.py +++ b/src/pairs/transformations/set_used_bin_ops.py @@ -1,4 +1,4 @@ -from ir.visitor import Visitor +from pairs.ir.visitor import Visitor class SetUsedBinOps(Visitor): diff --git a/transformations/simplify.py b/src/pairs/transformations/simplify.py similarity index 90% rename from transformations/simplify.py rename to src/pairs/transformations/simplify.py index 69803d8..ecba0d6 100644 --- a/transformations/simplify.py +++ b/src/pairs/transformations/simplify.py @@ -1,6 +1,6 @@ -from ir.data_types import Type_Int -from ir.lit import Lit -from ir.mutator import Mutator +from pairs.ir.data_types import Type_Int +from pairs.ir.lit import Lit +from pairs.ir.mutator import Mutator class SimplifyExpressions(Mutator): -- GitLab